The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=656a39c1a062411dca09d1566a7a0709c30f3bc7

commit 656a39c1a062411dca09d1566a7a0709c30f3bc7
Author:     Alexander V. Chernikov <[email protected]>
AuthorDate: 2023-05-27 11:11:04 +0000
Commit:     Alexander V. Chernikov <[email protected]>
CommitDate: 2023-05-27 11:13:14 +0000

    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;

Reply via email to