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
This commit is contained in:
Alexander V. Chernikov 2021-02-11 23:24:27 +00:00
parent 1253835121
commit 8170a7d438

View File

@ -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_family == AF_LINK) && !(info->rti_flags & RTF_GATEWAY)) {
/*
* 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 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);
} else {
/*
* 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.
* 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);
if (ifp == NULL) {
DPRINTF("invalid ifindex %d", sdl->sdl_index);
return (EINVAL);
}
fill_sdl_from_ifp(&nh->gwl_sa, ifp);
}
return (0);
}