From 656a39c1a062411dca09d1566a7a0709c30f3bc7 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Sat, 27 May 2023 11:11:04 +0000 Subject: [PATCH] netlink: use newly-added snl(3) array parsing for handling multipath routes. MFC after: 2 weeks --- sbin/route/route_netlink.c | 12 ++++---- sys/netlink/netlink_snl_route_parsers.h | 37 ++++++------------------- usr.bin/netstat/route_netlink.c | 6 ++-- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c index 01494fbefd51..0dbd90151e10 100644 --- a/sbin/route/route_netlink.c +++ b/sbin/route/route_netlink.c @@ -533,14 +533,14 @@ print_nlmsg_route(struct nl_helper *h, struct nlmsghdr *hdr, return; } - if (r.rta_multipath != NULL) { + if (r.rta_multipath.num_nhops != 0) { bool first = true; memset(buf, ' ', sizeof(buf)); buf[len] = '\0'; - for (int 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.num_nhops; i++) { + struct rta_mpath_nh *nh = r.rta_multipath.nhops[i]; if (!first) printf("%s", buf); @@ -834,9 +834,9 @@ flushroute_one(struct nl_helper *h, struct snl_parsed_route *r) print_nlmsg(h, hdr, &attrs); } else { - if (r->rta_multipath != NULL) { - for (int i = 0; i < r->rta_multipath->num_nhops; i++) { - struct rta_mpath_nh *nh = &r->rta_multipath->nhops[i]; + 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]; print_flushed_route(r, nh->gw); } diff --git a/sys/netlink/netlink_snl_route_parsers.h b/sys/netlink/netlink_snl_route_parsers.h index 0ab338cbe6e8..a89462210133 100644 --- a/sys/netlink/netlink_snl_route_parsers.h +++ b/sys/netlink/netlink_snl_route_parsers.h @@ -90,48 +90,27 @@ SNL_DECLARE_PARSER_EXT(_mpath_nh_parser, sizeof(struct rtnexthop), _cb_p_mp_nh); struct rta_mpath { - int num_nhops; - struct rta_mpath_nh nhops[0]; + 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, +nlattr_get_multipath(struct snl_state *ss, struct nlattr *nla, const void *arg, void *target) { - int data_len = nla->nla_len - sizeof(struct nlattr); - struct rtnexthop *rtnh; + uint32_t start_size = 4; - int max_nhops = data_len / sizeof(struct rtnexthop); - size_t sz = (max_nhops + 2) * sizeof(struct rta_mpath_nh); + while (start_size < NLA_DATA_LEN(nla) / sizeof(struct rtnexthop)) + start_size *= 2; - struct rta_mpath *mp = snl_allocz(ss, sz); - if (mp == NULL) - return (false); - mp->num_nhops = 0; - - for (rtnh = (struct rtnexthop *)(void *)(nla + 1); data_len > 0; ) { - struct rta_mpath_nh *mpnh = &mp->nhops[mp->num_nhops++]; - - if (!snl_parse_header(ss, rtnh, rtnh->rtnh_len, &_mpath_nh_parser, mpnh)) - return (false); - - int len = NL_ITEM_ALIGN(rtnh->rtnh_len); - data_len -= len; - rtnh = (struct rtnexthop *)(void *)((char *)rtnh + len); - } - if (data_len != 0 || mp->num_nhops == 0) { - return (false); - } - - *((struct rta_mpath **)target) = mp; - return (true); + return (snl_attr_get_parray_sz(ss, nla, start_size, &_mpath_nh_parser, target)); } struct snl_parsed_route { struct sockaddr *rta_dst; struct sockaddr *rta_gw; struct nlattr *rta_metrics; - struct rta_mpath *rta_multipath; + struct rta_mpath rta_multipath; uint32_t rta_expires; uint32_t rta_oif; uint32_t rta_expire; diff --git a/usr.bin/netstat/route_netlink.c b/usr.bin/netstat/route_netlink.c index 6e7e505c9619..3b1880fb9d90 100644 --- a/usr.bin/netstat/route_netlink.c +++ b/usr.bin/netstat/route_netlink.c @@ -237,11 +237,11 @@ p_rtentry_netlink(struct snl_state *ss, const char *name, struct nlmsghdr *hdr) if (rt.rtax_weight == 0) rt.rtax_weight = rt_default_weight; - if (rt.rta_multipath != NULL) { + if (rt.rta_multipath.num_nhops != 0) { uint32_t orig_rtflags = rt.rta_rtflags; uint32_t orig_mtu = rt.rtax_mtu; - for (int 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.num_nhops; i++) { + struct rta_mpath_nh *nhop = rt.rta_multipath.nhops[i]; rt.rta_gw = nhop->gw; rt.rta_oif = nhop->ifindex;