Page MenuHomeFreeBSD

D58775.diff
No OneTemporary

D58775.diff

diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
--- a/sbin/route/route_netlink.c
+++ b/sbin/route/route_netlink.c
@@ -428,11 +428,11 @@
printf(" fib: %u\n", (unsigned int)r.rta_table);
printf(" flags: ");
printb(r.rta_rtflags, routeflags);
- printf("\n nhops: %u\n", r.rta_multipath.num_nhops);
- if (r.rta_multipath.num_nhops != 0) {
+ printf("\n nhops: %u\n", r.rta_multipath.count);
+ if (r.rta_multipath.count != 0) {
bool first = true;
- for (uint32_t i = 0; i < r.rta_multipath.num_nhops; i++) {
- struct rta_mpath_nh *nh = r.rta_multipath.nhops[i];
+ for (uint32_t i = 0; i < r.rta_multipath.count; i++) {
+ struct rta_mpath_nh *nh = r.rta_multipath.items[i];
printf("\tvia ");
print_nlmsg_route_nhop(h, &r, nh, first);
@@ -601,14 +601,14 @@
return;
}
- if (r.rta_multipath.num_nhops != 0) {
+ if (r.rta_multipath.count != 0) {
bool first = true;
memset(buf, ' ', sizeof(buf));
buf[len] = '\0';
- for (uint32_t i = 0; i < r.rta_multipath.num_nhops; i++) {
- struct rta_mpath_nh *nh = r.rta_multipath.nhops[i];
+ for (uint32_t i = 0; i < r.rta_multipath.count; i++) {
+ struct rta_mpath_nh *nh = r.rta_multipath.items[i];
if (!first)
printf("%s", buf);
@@ -903,9 +903,10 @@
print_nlmsg(h, hdr, &attrs);
}
else {
- if (r->rta_multipath.num_nhops != 0) {
- for (uint32_t i = 0; i < r->rta_multipath.num_nhops; i++) {
- struct rta_mpath_nh *nh = r->rta_multipath.nhops[i];
+ if (r->rta_multipath.count != 0) {
+ for (uint32_t i = 0; i < r->rta_multipath.count; i++) {
+ struct rta_mpath_nh *nh =
+ r->rta_multipath.items[i];
print_flushed_route(r, nh->gw);
}
@@ -975,4 +976,3 @@
return (e.error);
}
-
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
@@ -724,23 +724,60 @@
struct snl_parray {
uint32_t count;
void **items;
+ uint32_t _capacity;
};
+static inline bool
+snl_parray_append(struct snl_state *ss, struct snl_parray *array, void *item,
+ uint32_t start_size)
+{
+ void **new_items;
+ size_t alloc_size;
+ uint32_t new_size;
+
+ if (start_size == 0)
+ return (false);
+ if (array->_capacity == 0) {
+ new_size = start_size;
+ if (__builtin_mul_overflow((size_t)new_size,
+ sizeof(*new_items), &alloc_size))
+ return (false);
+ array->items = (void **)snl_allocz(ss, alloc_size);
+ if (array->items == NULL)
+ return (false);
+ array->_capacity = new_size;
+ } else if (array->count == array->_capacity) {
+ if (array->_capacity > UINT32_MAX / 2)
+ return (false);
+ new_size = array->_capacity * 2;
+ if (__builtin_mul_overflow((size_t)new_size,
+ sizeof(*new_items), &alloc_size))
+ return (false);
+ new_items = (void **)snl_allocz(ss, alloc_size);
+ if (new_items == NULL)
+ return (false);
+ memcpy(new_items, array->items,
+ array->count * sizeof(*new_items));
+ array->items = new_items;
+ array->_capacity = new_size;
+ }
+ array->items[array->count++] = item;
+ return (true);
+}
+
static inline bool
snl_attr_get_parray_sz(struct snl_state *ss, struct nlattr *container_nla,
- uint32_t start_size, const void *arg, void *target)
+ uint32_t start_size, const void *arg, struct snl_parray *array)
{
const struct snl_hdr_parser *p = (const struct snl_hdr_parser *)arg;
- struct snl_parray *array = (struct snl_parray *)target;
struct nlattr *nla;
- uint32_t count = 0, size = start_size;
- if (p->out_size == 0)
- return (false);
-
- array->items = (void **)snl_allocz(ss, size * sizeof(void *));
- if (array->items == NULL)
+ if (p->out_size == 0 || start_size == 0)
return (false);
+ /* A container attribute replaces, rather than extends, its output. */
+ array->count = 0;
+ array->items = NULL;
+ array->_capacity = 0;
/*
* If the provided parser is an attribute parser, assume that each
@@ -766,31 +803,49 @@
if (!(snl_parse_header(ss, data, data_len, p, item)))
return (false);
- if (count == size) {
- uint32_t new_size = size * 2;
- void **new_array = (void **)snl_allocz(ss, new_size *sizeof(void *));
-
- memcpy(new_array, array->items, size * sizeof(void *));
- array->items = new_array;
- size = new_size;
- }
- array->items[count++] = item;
+ if (!snl_parray_append(ss, array, item, start_size))
+ return (false);
}
- array->count = count;
return (true);
}
/*
* Parses and stores the unknown-size array.
- * Assumes each array item is a container and the NLAs in the container are parsable
- * by the parser provided in @arg.
- * Assumes @target is struct snl_parray
+ * Assumes each array item is a container and the NLAs in the container are
+ * parsable by the parser provided in @arg.
+ * @target must point to an actual struct snl_parray. Do not substitute a
+ * layout-compatible structure: the parser array includes private growth state.
*/
static inline bool
snl_attr_get_parray(struct snl_state *ss, struct nlattr *nla, const void *arg, void *target)
{
- return (snl_attr_get_parray_sz(ss, nla, 8, arg, target));
+ return (snl_attr_get_parray_sz(ss, nla, 8, arg,
+ (struct snl_parray *)target));
+}
+
+/*
+ * Append one repeated nested attribute to an array. Unlike
+ * snl_attr_get_parray(), the attribute itself is one array member rather
+ * than a container holding an entire array. Use this for modern Netlink
+ * multi-attributes. @target must point to an actual struct snl_parray.
+ */
+static inline bool
+snl_attr_get_multi(struct snl_state *ss, struct nlattr *nla, const void *arg,
+ void *target)
+{
+ const struct snl_hdr_parser *p = arg;
+ struct snl_parray *array = target;
+ void *item;
+
+ if (p->out_size == 0)
+ return (false);
+ item = snl_allocz(ss, p->out_size);
+ if (item == NULL)
+ return (false);
+ if (!snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), p, item))
+ return (false);
+ return (snl_parray_append(ss, array, item, 8));
}
static inline bool
@@ -849,11 +904,6 @@
int bit_value;
};
-struct snl_attr_bits {
- uint32_t num_bits;
- struct snl_attr_bit **bits;
-};
-
#define _OUT(_field) offsetof(struct snl_attr_bit, _field)
static const struct snl_attr_parser _nla_p_bit[] = {
{ .type = NLA_BITSET_BIT_INDEX, .off = _OUT(bit_index), .cb = snl_attr_get_uint32 },
@@ -867,7 +917,7 @@
uint32_t nla_bitset_size;
uint32_t *nla_bitset_mask;
uint32_t *nla_bitset_value;
- struct snl_attr_bits bits;
+ struct snl_parray bits;
};
#define _OUT(_field) offsetof(struct snl_attr_bitset, _field)
diff --git a/sys/netlink/netlink_snl_generic.h b/sys/netlink/netlink_snl_generic.h
--- a/sys/netlink/netlink_snl_generic.h
+++ b/sys/netlink/netlink_snl_generic.h
@@ -65,11 +65,6 @@
const char *mcast_grp_name;
};
-struct _snl_genl_ctrl_mcast_groups {
- uint32_t num_groups;
- struct _snl_genl_ctrl_mcast_group **groups;
-};
-
#define _OUT(_field) offsetof(struct _snl_genl_ctrl_mcast_group, _field)
static struct snl_attr_parser _nla_p_getmc[] = {
{
@@ -90,7 +85,7 @@
struct _getfamily_attrs {
uint16_t family_id;
const char *family_name;
- struct _snl_genl_ctrl_mcast_groups mcast_groups;
+ struct snl_parray mcast_groups;
};
#define _IN(_field) offsetof(struct genlmsghdr, _field)
@@ -165,10 +160,13 @@
return (0);
if (family_id != NULL)
*family_id = attrs.family_id;
- for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++)
- if (strcmp(attrs.mcast_groups.groups[i]->mcast_grp_name,
- group_name) == 0)
- return (attrs.mcast_groups.groups[i]->mcast_grp_id);
+ for (u_int i = 0; i < attrs.mcast_groups.count; i++) {
+ struct _snl_genl_ctrl_mcast_group *group;
+
+ group = attrs.mcast_groups.items[i];
+ if (strcmp(group->mcast_grp_name, group_name) == 0)
+ return (group->mcast_grp_id);
+ }
return (0);
}
diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h
--- a/sys/netlink/netlink_snl_route_parsers.h
+++ b/sys/netlink/netlink_snl_route_parsers.h
@@ -93,21 +93,18 @@
sizeof(struct rta_mpath_nh), _fp_p_mp_nh, _nla_p_mp_nh,
_cb_p_mp_nh);
-struct rta_mpath {
- uint32_t num_nhops;
- struct rta_mpath_nh **nhops;
-};
-
static bool
nlattr_get_multipath(struct snl_state *ss, struct nlattr *nla,
const void *arg __unused, void *target)
{
+ struct snl_parray *mpath = target;
uint32_t start_size = 4;
while (start_size < NLA_DATA_LEN(nla) / sizeof(struct rtnexthop))
start_size *= 2;
- return (snl_attr_get_parray_sz(ss, nla, start_size, &_mpath_nh_parser, target));
+ return (snl_attr_get_parray_sz(ss, nla, start_size,
+ &_mpath_nh_parser, mpath));
}
struct snl_parsed_route {
@@ -115,7 +112,7 @@
struct sockaddr *rta_gw;
struct sockaddr *rta_pref_src;
struct nlattr *rta_metrics;
- struct rta_mpath rta_multipath;
+ struct snl_parray rta_multipath;
uint32_t rta_oif;
uint32_t rta_expire;
uint32_t rta_table;
diff --git a/tests/sys/netlink/test_rtnl_route.c b/tests/sys/netlink/test_rtnl_route.c
--- a/tests/sys/netlink/test_rtnl_route.c
+++ b/tests/sys/netlink/test_rtnl_route.c
@@ -129,7 +129,7 @@
ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &snl_rtm_route_parser, &r));
ATF_CHECK(r.rta_knh_id != 0);
- ATF_CHECK_INTEQ(r.rta_multipath.num_nhops, 2);
+ ATF_CHECK_INTEQ(r.rta_multipath.count, 2);
cleanup_route_by_dst(&ss, &nw, "192.0.2.0");
}
@@ -179,7 +179,7 @@
ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &snl_rtm_route_parser, &r));
ATF_CHECK(r.rta_knh_id != 0);
- ATF_CHECK_INTEQ(r.rta_multipath.num_nhops, 0);
+ ATF_CHECK_INTEQ(r.rta_multipath.count, 0);
/* Append anoher nhop */
snl_init_writer(&ss, &nw);
@@ -202,7 +202,7 @@
ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &snl_rtm_route_parser, &r));
ATF_CHECK(r.rta_knh_id != 0);
- ATF_CHECK_INTEQ(r.rta_multipath.num_nhops, 2);
+ ATF_CHECK_INTEQ(r.rta_multipath.count, 2);
cleanup_route_by_dst(&ss, &nw, "198.51.100.0");
}
@@ -293,7 +293,7 @@
ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &snl_rtm_route_parser, &r));
ATF_CHECK(r.rta_knh_id != 0);
- ATF_CHECK_INTEQ(r.rta_multipath.num_nhops, 3);
+ ATF_CHECK_INTEQ(r.rta_multipath.count, 3);
/* wait for 2 seconds and try again */
sleep(2);
@@ -306,7 +306,7 @@
ATF_REQUIRE(snl_send_message(&ss, hdr));
ATF_REQUIRE((rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq)) != NULL);
ATF_CHECK(snl_parse_nlmsg(&ss, rx_hdr, &snl_rtm_route_parser, &r));
- ATF_CHECK_INTEQ(r.rta_multipath.num_nhops, 2);
+ ATF_CHECK_INTEQ(r.rta_multipath.count, 2);
cleanup_route_by_dst(&ss, &nw, "203.0.113.0");
}
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
@@ -37,6 +37,70 @@
}
+ATF_TC(snl_parse_bitset_array);
+ATF_TC_HEAD(snl_parse_bitset_array, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Tests snl(3) parsing a growing nested bit array");
+ atf_tc_set_md_var(tc, "require.kmods", "netlink");
+}
+
+ATF_TC_BODY(snl_parse_bitset_array, tc)
+{
+ struct snl_attr_bit *bit;
+ struct snl_parsed_link link = {};
+ struct snl_state ss;
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ uint32_t mask, value;
+ char name[16];
+ int bits_off, entry_off, fbsd_off, caps_off;
+
+ ATF_REQUIRE(snl_init(&ss, NETLINK_ROUTE));
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_msg_request(&nw, RTM_NEWLINK);
+ ATF_REQUIRE(hdr != NULL);
+ ATF_REQUIRE(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
+
+ fbsd_off = snl_add_msg_attr_nested(&nw, IFLA_FREEBSD);
+ ATF_REQUIRE(fbsd_off != 0);
+ caps_off = snl_add_msg_attr_nested(&nw, IFLAF_CAPS);
+ ATF_REQUIRE(caps_off != 0);
+ ATF_REQUIRE(snl_add_msg_attr_u32(&nw, NLA_BITSET_SIZE, 32));
+ mask = 0x1ff;
+ value = 0x155;
+ ATF_REQUIRE(snl_add_msg_attr(&nw, NLA_BITSET_MASK, sizeof(mask),
+ &mask));
+ ATF_REQUIRE(snl_add_msg_attr(&nw, NLA_BITSET_VALUE, sizeof(value),
+ &value));
+ bits_off = snl_add_msg_attr_nested(&nw, NLA_BITSET_BITS);
+ ATF_REQUIRE(bits_off != 0);
+ for (uint32_t i = 0; i < 9; i++) {
+ entry_off = snl_add_msg_attr_nested(&nw, i + 1);
+ ATF_REQUIRE(entry_off != 0);
+ ATF_REQUIRE(snl_add_msg_attr_u32(&nw,
+ NLA_BITSET_BIT_INDEX, i));
+ snprintf(name, sizeof(name), "bit-%u", i);
+ ATF_REQUIRE(snl_add_msg_attr_string(&nw,
+ NLA_BITSET_BIT_NAME, name));
+ if ((i & 1) == 0)
+ ATF_REQUIRE(snl_add_msg_attr_flag(&nw,
+ NLA_BITSET_BIT_VALUE));
+ snl_end_attr_nested(&nw, entry_off);
+ }
+ snl_end_attr_nested(&nw, bits_off);
+ snl_end_attr_nested(&nw, caps_off);
+ snl_end_attr_nested(&nw, fbsd_off);
+ hdr = snl_finalize_msg(&nw);
+ ATF_REQUIRE(hdr != NULL);
+
+ ATF_REQUIRE(snl_parse_nlmsg(&ss, hdr, &snl_rtm_link_parser, &link));
+ ATF_REQUIRE_EQ(link.iflaf_caps.bits.count, 9);
+ bit = link.iflaf_caps.bits.items[8];
+ ATF_CHECK_EQ(bit->bit_index, 8);
+ ATF_CHECK_STREQ(bit->bit_name, "bit-8");
+ ATF_CHECK_EQ(bit->bit_value, 1);
+}
ATF_TC(snl_verify_route_parsers);
ATF_TC_HEAD(snl_verify_route_parsers, tc)
{
@@ -230,6 +294,7 @@
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, snl_verify_core_parsers);
+ ATF_TP_ADD_TC(tp, snl_parse_bitset_array);
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);
diff --git a/tests/sys/netlink/test_snl_generic.c b/tests/sys/netlink/test_snl_generic.c
--- a/tests/sys/netlink/test_snl_generic.c
+++ b/tests/sys/netlink/test_snl_generic.c
@@ -90,9 +90,10 @@
struct _getfamily_attrs attrs = {};
ATF_CHECK(snl_parse_nlmsg(&ss, hdr, &_genl_ctrl_getfam_parser, &attrs));
- ATF_CHECK_EQ(attrs.mcast_groups.num_groups, 1);
+ ATF_CHECK_EQ(attrs.mcast_groups.count, 1);
- struct _snl_genl_ctrl_mcast_group *group = attrs.mcast_groups.groups[0];
+ struct _snl_genl_ctrl_mcast_group *group =
+ attrs.mcast_groups.items[0];
ATF_CHECK(group->mcast_grp_id > 0);
ATF_CHECK(!strcmp(group->mcast_grp_name, "notify"));
@@ -107,4 +108,3 @@
return (atf_no_error());
}
-
diff --git a/usr.bin/genl/genl.c b/usr.bin/genl/genl.c
--- a/usr.bin/genl/genl.c
+++ b/usr.bin/genl/genl.c
@@ -98,10 +98,6 @@
uint32_t id;
uint32_t flags;
};
-struct genl_ctrl_ops {
- uint32_t num_ops;
- struct genl_ctrl_op **ops;
-};
static struct snl_attr_parser nla_p_getops[] = {
#define _OUT(_field) offsetof(struct genl_ctrl_op, _field)
{
@@ -123,10 +119,6 @@
uint32_t id;
const char *name;
};
-struct genl_mcast_groups {
- uint32_t num_groups;
- struct genl_mcast_group **groups;
-};
static struct snl_attr_parser nla_p_getmc[] = {
#define _OUT(_field) offsetof(struct genl_mcast_group, _field)
{
@@ -150,8 +142,8 @@
uint32_t version;
uint32_t hdrsize;
uint32_t max_attr;
- struct genl_mcast_groups mcast_groups;
- struct genl_ctrl_ops ops;
+ struct snl_parray mcast_groups;
+ struct snl_parray ops;
};
static struct snl_attr_parser nla_p_getfamily[] = {
@@ -208,19 +200,21 @@
};
static void
-dump_operations(struct genl_ctrl_ops *ops)
+dump_operations(struct snl_parray *ops)
{
- if (ops->num_ops == 0)
+ struct genl_ctrl_op *op;
+
+ if (ops->count == 0)
return;
printf("\tsupported operations: \n");
- for (uint32_t i = 0; i < ops->num_ops; i++) {
+ for (uint32_t i = 0; i < ops->count; i++) {
bool p = true;
+ op = ops->items[i];
printf("\t - ID: %#02x, Capabilities: %#02x",
- ops->ops[i]->id,
- ops->ops[i]->flags);
+ op->id, op->flags);
for (size_t j = 0; j < nitems(op_caps); j++)
- if ((ops->ops[i]->flags & op_caps[j].flag) ==
+ if ((op->flags & op_caps[j].flag) ==
op_caps[j].flag) {
printf("%s%s", p ? " (" : "; ",
op_caps[j].str);
@@ -231,15 +225,18 @@
}
static void
-dump_mcast_groups(struct genl_mcast_groups *mcast_groups)
+dump_mcast_groups(struct snl_parray *mcast_groups)
{
- if (mcast_groups->num_groups == 0)
+ struct genl_mcast_group *group;
+
+ if (mcast_groups->count == 0)
return;
printf("\tmulticast groups: \n");
- for (uint32_t i = 0; i < mcast_groups->num_groups; i++)
+ for (uint32_t i = 0; i < mcast_groups->count; i++) {
+ group = mcast_groups->items[i];
printf("\t - ID: %#02x, Name: %s\n",
- mcast_groups->groups[i]->id,
- mcast_groups->groups[i]->name);
+ group->id, group->name);
+ }
}
static void
@@ -298,9 +295,13 @@
const char *
group_name(uint32_t id)
{
- for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++)
- if (attrs.mcast_groups.groups[i]->id == id)
- return (attrs.mcast_groups.groups[i]->name);
+ struct genl_mcast_group *group;
+
+ for (u_int i = 0; i < attrs.mcast_groups.count; i++) {
+ group = attrs.mcast_groups.items[i];
+ if (group->id == id)
+ return (group->name);
+ }
return ("???");
}
@@ -340,14 +341,16 @@
if (argc == 1)
all = true;
- for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++) {
+ for (u_int i = 0; i < attrs.mcast_groups.count; i++) {
+ struct genl_mcast_group *group;
+
+ group = attrs.mcast_groups.items[i];
if (all ||
- strcmp(attrs.mcast_groups.groups[i]->name, argv[1]) == 0) {
+ strcmp(group->name, argv[1]) == 0) {
found = true;
if (setsockopt(ss.fd, SOL_NETLINK,
NETLINK_ADD_MEMBERSHIP,
- &attrs.mcast_groups.groups[i]->id,
- sizeof(attrs.mcast_groups.groups[i]->id))
+ &group->id, sizeof(group->id))
== -1)
err(EXIT_FAILURE, "Cannot subscribe to command "
"notify");
diff --git a/usr.bin/netstat/route_netlink.c b/usr.bin/netstat/route_netlink.c
--- a/usr.bin/netstat/route_netlink.c
+++ b/usr.bin/netstat/route_netlink.c
@@ -235,11 +235,12 @@
if (rt.rtax_weight == 0)
rt.rtax_weight = rt_default_weight;
- if (rt.rta_multipath.num_nhops != 0) {
+ if (rt.rta_multipath.count != 0) {
uint32_t orig_rtflags = rt.rta_rtflags;
uint32_t orig_mtu = rt.rtax_mtu;
- for (uint32_t i = 0; i < rt.rta_multipath.num_nhops; i++) {
- struct rta_mpath_nh *nhop = rt.rta_multipath.nhops[i];
+ for (uint32_t i = 0; i < rt.rta_multipath.count; i++) {
+ struct rta_mpath_nh *nhop =
+ rt.rta_multipath.items[i];
rt.rta_gw = nhop->gw;
rt.rta_oif = nhop->ifindex;
@@ -341,4 +342,3 @@
return (true);
}
-
diff --git a/usr.sbin/arp/arp_netlink.c b/usr.sbin/arp/arp_netlink.c
--- a/usr.sbin/arp/arp_netlink.c
+++ b/usr.sbin/arp/arp_netlink.c
@@ -132,7 +132,7 @@
if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r))
return (0);
- if (r.rta_multipath.num_nhops > 0 || (r.rta_rtflags & RTF_GATEWAY))
+ if (r.rta_multipath.count > 0 || (r.rta_rtflags & RTF_GATEWAY))
return (0);
/* Check if the interface is of supported type */
@@ -448,4 +448,3 @@
return (e.error != 0);
}
-
diff --git a/usr.sbin/ndp/ndp_netlink.c b/usr.sbin/ndp/ndp_netlink.c
--- a/usr.sbin/ndp/ndp_netlink.c
+++ b/usr.sbin/ndp/ndp_netlink.c
@@ -164,7 +164,7 @@
if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r))
return (0);
- if (r.rta_multipath.num_nhops > 0 || (r.rta_rtflags & RTF_GATEWAY))
+ if (r.rta_multipath.count > 0 || (r.rta_rtflags & RTF_GATEWAY))
return (0);
/* Check if the interface is of supported type */
@@ -521,4 +521,3 @@
return (e.error != 0);
}
-

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 10, 3:50 PM (16 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38600305
Default Alt Text
D58775.diff (18 KB)

Event Timeline