diff --git a/dcb/dcb.c b/dcb/dcb.c
index 9bbbbfa74619..89f9b0ec7ef9 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -59,25 +59,19 @@ static void dcb_free(struct dcb *dcb)
 struct dcb_get_attribute {
 	struct dcb *dcb;
 	int attr;
-	void *data;
-	size_t data_len;
+	void *payload;
+	__u16 payload_len;
 };
 
 static int dcb_get_attribute_attr_ieee_cb(const struct nlattr *attr, void *data)
 {
 	struct dcb_get_attribute *ga = data;
-	uint16_t len;
 
 	if (mnl_attr_get_type(attr) != ga->attr)
 		return MNL_CB_OK;
 
-	len = mnl_attr_get_payload_len(attr);
-	if (len != ga->data_len) {
-		fprintf(stderr, "Wrong len %d, expected %zd\n", len, ga->data_len);
-		return MNL_CB_ERROR;
-	}
-
-	memcpy(ga->data, mnl_attr_get_payload(attr), ga->data_len);
+	ga->payload = mnl_attr_get_payload(attr);
+	ga->payload_len = mnl_attr_get_payload_len(attr);
 	return MNL_CB_STOP;
 }
 
@@ -94,6 +88,16 @@ static int dcb_get_attribute_cb(const struct nlmsghdr *nlh, void *data)
 	return mnl_attr_parse(nlh, sizeof(struct dcbmsg), dcb_get_attribute_attr_cb, data);
 }
 
+static int dcb_get_attribute_bare_cb(const struct nlmsghdr *nlh, void *data)
+{
+	/* Bare attributes (e.g. DCB_ATTR_DCBX) are not wrapped inside an IEEE
+	 * container, so this does not have to go through unpacking in
+	 * dcb_get_attribute_attr_cb().
+	 */
+	return mnl_attr_parse(nlh, sizeof(struct dcbmsg),
+			      dcb_get_attribute_attr_ieee_cb, data);
+}
+
 struct dcb_set_attribute_response {
 	int response_attr;
 };
@@ -155,25 +159,70 @@ static struct nlmsghdr *dcb_prepare(struct dcb *dcb, const char *dev,
 	return nlh;
 }
 
-int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr, void *data, size_t data_len)
+static int __dcb_get_attribute(struct dcb *dcb, int command,
+			       const char *dev, int attr,
+			       void **payload_p, __u16 *payload_len_p,
+			       int (*get_attribute_cb)(const struct nlmsghdr *nlh,
+						       void *data))
 {
 	struct dcb_get_attribute ga;
 	struct nlmsghdr *nlh;
 	int ret;
 
-	nlh = dcb_prepare(dcb, dev, RTM_GETDCB, DCB_CMD_IEEE_GET);
+	nlh = dcb_prepare(dcb, dev, RTM_GETDCB, command);
 
 	ga = (struct dcb_get_attribute) {
 		.dcb = dcb,
 		.attr = attr,
-		.data = data,
-		.data_len = data_len,
+		.payload = NULL,
 	};
-	ret = dcb_talk(dcb, nlh, dcb_get_attribute_cb, &ga);
+	ret = dcb_talk(dcb, nlh, get_attribute_cb, &ga);
 	if (ret) {
 		perror("Attribute read");
 		return ret;
 	}
+	if (ga.payload == NULL) {
+		perror("Attribute not found");
+		return -ENOENT;
+	}
+
+	*payload_p = ga.payload;
+	*payload_len_p = ga.payload_len;
+	return 0;
+}
+
+int dcb_get_attribute_va(struct dcb *dcb, const char *dev, int attr,
+			 void **payload_p, __u16 *payload_len_p)
+{
+	return __dcb_get_attribute(dcb, DCB_CMD_IEEE_GET, dev, attr,
+				   payload_p, payload_len_p,
+				   dcb_get_attribute_cb);
+}
+
+int dcb_get_attribute_bare(struct dcb *dcb, int cmd, const char *dev, int attr,
+			   void **payload_p, __u16 *payload_len_p)
+{
+	return __dcb_get_attribute(dcb, cmd, dev, attr,
+				   payload_p, payload_len_p,
+				   dcb_get_attribute_bare_cb);
+}
+
+int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr, void *data, size_t data_len)
+{
+	__u16 payload_len;
+	void *payload;
+	int ret;
+
+	ret = dcb_get_attribute_va(dcb, dev, attr, &payload, &payload_len);
+	if (ret)
+		return ret;
+
+	if (payload_len != data_len) {
+		fprintf(stderr, "Wrong len %d, expected %zd\n", payload_len, data_len);
+		return -EINVAL;
+	}
+
+	memcpy(data, payload, data_len);
 	return 0;
 }
 
diff --git a/dcb/dcb.h b/dcb/dcb.h
index da14937c8925..8c7327a43588 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -33,9 +33,13 @@ int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr,
 		      void *data, size_t data_len);
 int dcb_set_attribute(struct dcb *dcb, const char *dev, int attr,
 		      const void *data, size_t data_len);
+int dcb_get_attribute_va(struct dcb *dcb, const char *dev, int attr,
+			 void **payload_p, __u16 *payload_len_p);
 int dcb_set_attribute_va(struct dcb *dcb, int command, const char *dev,
 			 int (*cb)(struct dcb *dcb, struct nlmsghdr *nlh, void *data),
 			 void *data);
+int dcb_get_attribute_bare(struct dcb *dcb, int cmd, const char *dev, int attr,
+			   void **payload_p, __u16 *payload_len_p);
 int dcb_set_attribute_bare(struct dcb *dcb, int command, const char *dev,
 			   int attr, const void *data, size_t data_len,
 			   int response_attr);
