From 1e443270387834e84a335ec500cf069172ab261c Mon Sep 17 00:00:00 2001 Message-Id: <1e443270387834e84a335ec500cf069172ab261c@dist-git> From: Laine Stump Date: Mon, 14 Jan 2019 11:35:05 -0500 Subject: [PATCH] util: check accept_ra for all nexthop interfaces of multipath routes When checking the setting of accept_ra, we have assumed that all routes have a single nexthop, so the interface of the route would be in the RTA_OIF attribute of the netlink RTM_NEWROUTE message. But multipath routes don't have an RTA_OIF; instead, they have an RTA_MULTIPATH attribute, which is an array of rtnexthop, with each rtnexthop having an interface. This patch adds a loop to look at the setting of accept_ra of the interface for every rtnexthop in the array. Signed-off-by: Laine Stump Reviewed-by: Erik Skultety (cherry picked from commit d40b820c5d3b0c9d5222844110881af66cdbb746) https://bugzilla.redhat.com/1583131 Conflicts: src/util/virnetdevip.c - more context conflicts due to addition of VIR_AUTOPTR and resulting removal of cleanup/error labels upstream. Signed-off-by: Laine Stump Reviewed-by: Jiri Denemark --- src/util/virnetdevip.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c index d56f4f05f3..fff41ec498 100644 --- a/src/util/virnetdevip.c +++ b/src/util/virnetdevip.c @@ -601,6 +601,43 @@ virNetDevIPCheckIPv6ForwardingCallback(struct nlmsghdr *resp, goto cleanup; } + /* if no RTA_OIF was found, see if this is a multipath route (one + * which has an array of nexthops, each with its own interface) + */ + + rta_attr = (struct rtattr *)nlmsg_find_attr(resp, sizeof(struct rtmsg), RTA_MULTIPATH); + if (rta_attr) { + /* The data of the attribute is an array of rtnexthop */ + struct rtnexthop *nh = RTA_DATA(rta_attr); + size_t len = RTA_PAYLOAD(rta_attr); + + /* validate the attribute array length */ + len = MIN(len, ((char *)resp + NLMSG_PAYLOAD(resp, 0) - (char *)rta_attr)); + + while (len >= sizeof(*nh) && len >= nh->rtnh_len) { + /* check accept_ra for the interface of each nexthop */ + + ifname = virNetDevGetName(nh->rtnh_ifindex); + + if (ifname) + accept_ra = virNetDevIPGetAcceptRA(ifname); + + VIR_DEBUG("Checking multipath route nexthop device %s (%d), accept_ra: %d", + ifname, nh->rtnh_ifindex, accept_ra); + + if (!ifname || + (accept_ra != 2 && virNetDevIPCheckIPv6ForwardingAddIF(data, &ifname) < 0)) { + goto error; + } + + VIR_FREE(ifname); /* in case it wasn't added to the array */ + data->hasRARoutes = true; + + len -= NLMSG_ALIGN(nh->rtnh_len); + nh = RTNH_NEXT(nh); + } + } + cleanup: VIR_FREE(ifname); return ret; -- 2.20.1