Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142015582
D39144.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D39144.id.diff
View Options
diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h
--- a/sys/netlink/netlink_snl.h
+++ b/sys/netlink/netlink_snl.h
@@ -388,18 +388,25 @@
return (snl_parse_attrs_raw(ss, nla_head, len, ps, pslen, target));
}
-static inline bool
-snl_parse_header(struct snl_state *ss, void *hdr, int len,
- const struct snl_hdr_parser *parser, void *target)
+static inline void
+snl_parse_fields(struct snl_state *ss, struct nlmsghdr *hdr, int hdrlen __unused,
+ const struct snl_field_parser *ps, int pslen, void *target)
{
- /* Extract fields first (if any) */
- for (int i = 0; i < parser->fp_size; i++) {
- const struct snl_field_parser *fp = &parser->fp[i];
+ for (int i = 0; i < pslen; i++) {
+ const struct snl_field_parser *fp = &ps[i];
void *src = (char *)hdr + fp->off_in;
void *dst = (char *)target + fp->off_out;
fp->cb(ss, src, dst);
}
+}
+
+static inline bool
+snl_parse_header(struct snl_state *ss, void *hdr, int len,
+ const struct snl_hdr_parser *parser, void *target)
+{
+ /* Extract fields first (if any) */
+ snl_parse_fields(ss, hdr, parser->hdr_off, parser->fp, parser->fp_size, target);
struct nlattr *nla_head = (struct nlattr *)(void *)((char *)hdr + parser->hdr_off);
bool result = snl_parse_attrs_raw(ss, nla_head, len - parser->hdr_off,
@@ -575,13 +582,20 @@
*((uint32_t *)target) = *((uint32_t *)src);
}
+static inline void
+snl_field_get_ptr(struct snl_state *ss __unused, void *src, void *target)
+{
+ *((void **)target) = src;
+}
+
struct snl_errmsg_data {
- uint32_t nlmsg_seq;
+ struct nlmsghdr *orig_hdr;
int error;
- char *error_str;
uint32_t error_offs;
+ char *error_str;
struct nlattr *cookie;
};
+
#define _IN(_field) offsetof(struct nlmsgerr, _field)
#define _OUT(_field) offsetof(struct snl_errmsg_data, _field)
static const struct snl_attr_parser nla_p_errmsg[] = {
@@ -592,7 +606,7 @@
static const struct snl_field_parser nlf_p_errmsg[] = {
{ .off_in = _IN(error), .off_out = _OUT(error), .cb = snl_field_get_uint32 },
- { .off_in = _IN(msg.nlmsg_seq), .off_out = _OUT(nlmsg_seq), .cb = snl_field_get_uint32 },
+ { .off_in = _IN(msg), .off_out = _OUT(orig_hdr), .cb = snl_field_get_ptr },
};
#undef _IN
#undef _OUT
@@ -609,6 +623,22 @@
#undef _OUT
SNL_DECLARE_PARSER(snl_donemsg_parser, struct nlmsgerr, nlf_p_donemsg, nla_p_donemsg);
+static inline bool
+snl_parse_errmsg(struct snl_state *ss, struct nlmsghdr *hdr, struct snl_errmsg_data *e)
+{
+ if ((hdr->nlmsg_flags & NLM_F_CAPPED) != 0)
+ return (snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e));
+
+ const struct snl_hdr_parser *ps = &snl_errmsg_parser;
+ struct nlmsgerr *errmsg = (struct nlmsgerr *)(hdr + 1);
+ int hdrlen = sizeof(int) + NLMSG_ALIGN(errmsg->msg.nlmsg_len);
+ struct nlattr *attr_head = (struct nlattr *)(void *)((char *)errmsg + hdrlen);
+ int attr_len = hdr->nlmsg_len - sizeof(struct nlmsghdr) - hdrlen;
+
+ snl_parse_fields(ss, (struct nlmsghdr *)errmsg, hdrlen, ps->fp, ps->fp_size, e);
+ return (snl_parse_attrs_raw(ss, attr_head, attr_len, ps->np, ps->np_size, e));
+}
+
static inline bool
snl_read_reply_code(struct snl_state *ss, uint32_t nlmsg_seq, struct snl_errmsg_data *e)
{
@@ -617,7 +647,7 @@
if (hdr == NULL) {
e->error = EINVAL;
} else if (hdr->nlmsg_type == NLMSG_ERROR) {
- if (!snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e))
+ if (!snl_parse_errmsg(ss, hdr, e))
e->error = EINVAL;
return (e->error == 0);
}
@@ -636,7 +666,7 @@
if (hdr == NULL) {
e->error = EINVAL;
} else if (hdr->nlmsg_type == NLMSG_ERROR) {
- if (!snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e))
+ if (!snl_parse_errmsg(ss, hdr, e))
e->error = EINVAL;
} if (hdr->nlmsg_type == NLMSG_DONE) {
snl_parse_nlmsg(ss, hdr, &snl_donemsg_parser, e);
diff --git a/tests/sys/netlink/test_snl.c b/tests/sys/netlink/test_snl.c
--- a/tests/sys/netlink/test_snl.c
+++ b/tests/sys/netlink/test_snl.c
@@ -44,6 +44,129 @@
}
+ATF_TC(snl_parse_errmsg_capped);
+ATF_TC_HEAD(snl_parse_errmsg_capped, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors");
+}
+
+ATF_TC_BODY(snl_parse_errmsg_capped, tc)
+{
+ struct snl_state ss;
+ struct snl_writer nw;
+
+ require_netlink();
+
+ if (!snl_init(&ss, NETLINK_ROUTE))
+ atf_tc_fail("snl_init() failed");
+
+ int optval = 1;
+ ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0);
+
+ snl_init_writer(&ss, &nw);
+
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
+ ATF_CHECK(hdr != NULL);
+ ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
+ snl_add_msg_attr_string(&nw, 143, "some random string");
+ ATF_CHECK(snl_finalize_msg(&nw) != NULL);
+
+ ATF_CHECK(snl_send_message(&ss, hdr));
+
+ struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
+ ATF_CHECK(rx_hdr != NULL);
+ ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
+
+ struct snl_errmsg_data e = {};
+ ATF_CHECK(rx_hdr->nlmsg_len == sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr));
+ ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
+ ATF_CHECK(e.error != 0);
+ ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr)));
+}
+
+ATF_TC(snl_parse_errmsg_capped_extack);
+ATF_TC_HEAD(snl_parse_errmsg_capped_extack, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors with extack");
+}
+
+ATF_TC_BODY(snl_parse_errmsg_capped_extack, tc)
+{
+ struct snl_state ss;
+ struct snl_writer nw;
+
+ require_netlink();
+
+ if (!snl_init(&ss, NETLINK_ROUTE))
+ atf_tc_fail("snl_init() failed");
+
+ int optval = 1;
+ ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0);
+ optval = 1;
+ ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
+
+ snl_init_writer(&ss, &nw);
+
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
+ ATF_CHECK(hdr != NULL);
+ ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
+ snl_add_msg_attr_string(&nw, 143, "some random string");
+ ATF_CHECK(snl_finalize_msg(&nw) != NULL);
+
+ ATF_CHECK(snl_send_message(&ss, hdr));
+
+ struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
+ ATF_CHECK(rx_hdr != NULL);
+ ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
+
+ struct snl_errmsg_data e = {};
+ ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
+ ATF_CHECK(e.error != 0);
+ ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr)));
+
+ ATF_CHECK(e.error_str != NULL);
+}
+
+ATF_TC(snl_parse_errmsg_uncapped_extack);
+ATF_TC_HEAD(snl_parse_errmsg_uncapped_extack, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing errors with extack");
+}
+
+ATF_TC_BODY(snl_parse_errmsg_uncapped_extack, tc)
+{
+ struct snl_state ss;
+ struct snl_writer nw;
+
+ require_netlink();
+
+ ATF_CHECK(snl_init(&ss, NETLINK_ROUTE));
+
+ int optval = 1;
+ ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
+
+ snl_init_writer(&ss, &nw);
+
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
+ ATF_CHECK(hdr != NULL);
+ ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
+ snl_add_msg_attr_string(&nw, 143, "some random string");
+ ATF_CHECK(snl_finalize_msg(&nw) != NULL);
+
+ ATF_CHECK(snl_send_message(&ss, hdr));
+
+ struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
+ ATF_CHECK(rx_hdr != NULL);
+ ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
+
+ struct snl_errmsg_data e = {};
+ ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
+ ATF_CHECK(e.error != 0);
+ ATF_CHECK(!memcmp(hdr, e.orig_hdr, hdr->nlmsg_len));
+
+ ATF_CHECK(e.error_str != NULL);
+}
+
ATF_TC(snl_list_ifaces);
ATF_TC_HEAD(snl_list_ifaces, tc)
{
@@ -105,6 +228,9 @@
{
ATF_TP_ADD_TC(tp, snl_verify_core_parsers);
ATF_TP_ADD_TC(tp, snl_verify_route_parsers);
+ ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped);
+ ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped_extack);
+ ATF_TP_ADD_TC(tp, snl_parse_errmsg_uncapped_extack);
ATF_TP_ADD_TC(tp, snl_list_ifaces);
return (atf_no_error());
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 15, 11:13 PM (10 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27655771
Default Alt Text
D39144.id.diff (7 KB)
Attached To
Mode
D39144: netlink: fix capped uncapped ack handling in snl(3).
Attached
Detach File
Event Timeline
Log In to Comment