aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-05-27 11:11:04 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-05-27 11:13:14 +0000
commit656a39c1a062411dca09d1566a7a0709c30f3bc7 (patch)
tree87caef1b06407d43ef84cf6325ffc283ed910189
parent5f19f790b3923354871ce049b84c7807ecb0cad5 (diff)
downloadsrc-656a39c1a062411dca09d1566a7a0709c30f3bc7.tar.gz
src-656a39c1a062411dca09d1566a7a0709c30f3bc7.zip
netlink: use newly-added snl(3) array parsing for handling multipath
routes. MFC after: 2 weeks
-rw-r--r--sbin/route/route_netlink.c12
-rw-r--r--sys/netlink/netlink_snl_route_parsers.h37
-rw-r--r--usr.bin/netstat/route_netlink.c6
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;