aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-02-11 23:24:27 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-02-12 19:45:35 +0000
commit8170a7d43835047f9c1548a081eea45116473995 (patch)
tree66eedf02ccf8bf7d10f724f2142d0c4d96105b1f
parent1253835121cb38fd93478849e32a4a4c13436fb2 (diff)
downloadsrc-8170a7d43835047f9c1548a081eea45116473995.tar.gz
src-8170a7d43835047f9c1548a081eea45116473995.zip
Fix interface route addition with net/bird.
The case of adding interface route by specifying interface address as the gateway was missed during code refactoring. Re-add it back by copying non-AF_LINK gateway data when RTF_GATEWAY is not set. Reviewed by: donner MFC after: 3 days
-rw-r--r--sys/net/route/nhop_ctl.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c
index 542380afd64b..7de553799fab 100644
--- a/sys/net/route/nhop_ctl.c
+++ b/sys/net/route/nhop_ctl.c
@@ -219,42 +219,44 @@ set_nhop_gw_from_info(struct nhop_object *nh, struct rt_addrinfo *info)
gw = info->rti_info[RTAX_GATEWAY];
KASSERT(gw != NULL, ("gw is NULL"));
- if (info->rti_flags & RTF_GATEWAY) {
- if (gw->sa_len > sizeof(struct sockaddr_in6)) {
- DPRINTF("nhop SA size too big: AF %d len %u",
- gw->sa_family, gw->sa_len);
- return (ENOMEM);
- }
- memcpy(&nh->gw_sa, gw, gw->sa_len);
- } else {
+ if ((gw->sa_family == AF_LINK) && !(info->rti_flags & RTF_GATEWAY)) {
/*
- * Interface route. Currently the route.c code adds
- * sa of type AF_LINK, which is 56 bytes long. The only
- * meaningful data there is the interface index. It is used
- * used is the IPv6 loopback output, where we need to preserve
- * the original interface to maintain proper scoping.
+ * Interface route with interface specified by the interface
+ * index in sockadd_dl structure. It is used in the IPv6 loopback
+ * output code, where we need to preserve the original interface
+ * to maintain proper scoping.
* Despite the fact that nexthop code stores original interface
* in the separate field (nh_aifp, see below), write AF_LINK
* compatible sa with shorter total length.
*/
- struct sockaddr_dl *sdl;
- struct ifnet *ifp;
-
- /* Fetch and validate interface index */
- sdl = (struct sockaddr_dl *)gw;
- if (sdl->sdl_family != AF_LINK) {
- DPRINTF("unsupported AF: %d", sdl->sdl_family);
- return (ENOTSUP);
- }
- ifp = ifnet_byindex(sdl->sdl_index);
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)gw;
+ struct ifnet *ifp = ifnet_byindex(sdl->sdl_index);
if (ifp == NULL) {
DPRINTF("invalid ifindex %d", sdl->sdl_index);
return (EINVAL);
}
fill_sdl_from_ifp(&nh->gwl_sa, ifp);
- }
+ } else {
+ /*
+ * Multiple options here:
+ *
+ * 1) RTF_GATEWAY with IPv4/IPv6 gateway data
+ * 2) Interface route with IPv4/IPv6 address of the
+ * matching interface. Some routing daemons do that
+ * instead of specifying ifindex in AF_LINK.
+ *
+ * In both cases, save the original nexthop to make the callers
+ * happy.
+ */
+ if (gw->sa_len > sizeof(struct sockaddr_in6)) {
+ DPRINTF("nhop SA size too big: AF %d len %u",
+ gw->sa_family, gw->sa_len);
+ return (ENOMEM);
+ }
+ memcpy(&nh->gw_sa, gw, gw->sa_len);
+ }
return (0);
}