routing: Bring back the ability to specify transmit interface via its name.

Some software references outgoing interfaces by specifying name instead of
 index.

Use rti_ifp from rt_addrinfo if provided instead of always using
 address interface when constructing nexthop.

PR: 		255678
Reported by:	martin.larsson2 at gmail.com
MFC after:	1 week
This commit is contained in:
Alexander V. Chernikov 2021-08-29 19:51:28 +00:00
parent 0939f965d8
commit d98954e229
2 changed files with 37 additions and 10 deletions

View File

@ -502,6 +502,38 @@ rt_flushifroutes(struct ifnet *ifp)
rib_foreach_table_walk_del(AF_UNSPEC, rt_ifdelroute, ifp);
}
/*
* Tries to extract interface from RTAX_IFP passed in rt_addrinfo.
* Interface can be specified ether as interface index (sdl_index) or
* the interface name (sdl_data).
*
* Returns found ifp or NULL
*/
static struct ifnet *
info_get_ifp(struct rt_addrinfo *info)
{
const struct sockaddr_dl *sdl;
sdl = (const struct sockaddr_dl *)info->rti_info[RTAX_IFP];
if (sdl->sdl_family != AF_LINK)
return (NULL);
if (sdl->sdl_index != 0)
return (ifnet_byindex(sdl->sdl_index));
if (sdl->sdl_nlen > 0) {
char if_name[IF_NAMESIZE];
if (sdl->sdl_nlen + offsetof(struct sockaddr_dl, sdl_data) > sdl->sdl_len)
return (NULL);
if (sdl->sdl_nlen >= IF_NAMESIZE)
return (NULL);
bzero(if_name, sizeof(if_name));
memcpy(if_name, sdl->sdl_data, sdl->sdl_nlen);
return (ifunit(if_name));
}
return (NULL);
}
/*
* Look up rt_addrinfo for a specific fib.
*
@ -511,12 +543,11 @@ rt_flushifroutes(struct ifnet *ifp)
int
rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
{
const struct sockaddr *dst, *gateway, *ifpaddr, *ifaaddr;
const struct sockaddr *dst, *gateway, *ifaaddr;
int error, flags;
dst = info->rti_info[RTAX_DST];
gateway = info->rti_info[RTAX_GATEWAY];
ifpaddr = info->rti_info[RTAX_IFP];
ifaaddr = info->rti_info[RTAX_IFA];
flags = info->rti_flags;
@ -526,13 +557,9 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
*/
error = 0;
/* If we have interface specified by the ifindex in the address, use it */
if (info->rti_ifp == NULL && ifpaddr != NULL &&
ifpaddr->sa_family == AF_LINK) {
const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifpaddr;
if (sdl->sdl_index != 0)
info->rti_ifp = ifnet_byindex(sdl->sdl_index);
}
/* If we have interface specified by RTAX_IFP address, try to use it */
if ((info->rti_ifp == NULL) && (info->rti_info[RTAX_IFP] != NULL))
info->rti_ifp = info_get_ifp(info);
/*
* If we have source address specified, try to find it
* TODO: avoid enumerating all ifas on all interfaces.

View File

@ -286,7 +286,7 @@ fill_nhop_from_info(struct nhop_priv *nh_priv, struct rt_addrinfo *info)
if ((error = set_nhop_gw_from_info(nh, info)) != 0)
return (error);
nh->nh_ifp = info->rti_ifa->ifa_ifp;
nh->nh_ifp = (info->rti_ifp != NULL) ? info->rti_ifp : info->rti_ifa->ifa_ifp;
nh->nh_ifa = info->rti_ifa;
/* depends on the gateway */
nh->nh_aifp = get_aifp(nh);