Changeset View
Changeset View
Standalone View
Standalone View
sys/net/route.c
Show First 20 Lines • Show All 1,270 Lines • ▼ Show 20 Lines | |||||
#define netmask info->rti_info[RTAX_NETMASK] | #define netmask info->rti_info[RTAX_NETMASK] | ||||
#define ifaaddr info->rti_info[RTAX_IFA] | #define ifaaddr info->rti_info[RTAX_IFA] | ||||
#define ifpaddr info->rti_info[RTAX_IFP] | #define ifpaddr info->rti_info[RTAX_IFP] | ||||
#define flags info->rti_flags | #define flags info->rti_flags | ||||
/* | /* | ||||
* Look up rt_addrinfo for a specific fib. Note that if rti_ifa is defined, | * Look up rt_addrinfo for a specific fib. Note that if rti_ifa is defined, | ||||
* it will be referenced so the caller must free it. | * it will be referenced so the caller must free it. | ||||
* | |||||
* Assume basic consitency checks are executed by callers: | |||||
* RTAX_DST exists, if RTF_GATEWAY is set, RTAX_GATEWAY exists as well. | |||||
*/ | */ | ||||
int | int | ||||
rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) | rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) | ||||
{ | { | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
struct ifaddr *ifa; | |||||
int needref, error; | int needref, error; | ||||
/* | /* | ||||
* ifp may be specified by sockaddr_dl | * ifp may be specified by sockaddr_dl | ||||
* when protocol address is ambiguous. | * when protocol address is ambiguous. | ||||
*/ | */ | ||||
error = 0; | error = 0; | ||||
needref = (info->rti_ifa == NULL); | needref = (info->rti_ifa == NULL); | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
/* If we have interface specified by the ifindex in the address, use it */ | |||||
if (info->rti_ifp == NULL && ifpaddr != NULL && | if (info->rti_ifp == NULL && ifpaddr != NULL && | ||||
ifpaddr->sa_family == AF_LINK && | ifpaddr->sa_family == AF_LINK) { | ||||
(ifa = ifa_ifwithnet(ifpaddr, 0, fibnum)) != NULL) { | const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifpaddr; | ||||
info->rti_ifp = ifa->ifa_ifp; | if (sdl->sdl_index != 0) | ||||
info->rti_ifp = ifnet_byindex_locked(sdl->sdl_index); | |||||
} | } | ||||
/* | |||||
* If we have source address specified, try to find it | |||||
* TODO: avoid enumerating all ifas on all interfaces. | |||||
*/ | |||||
if (info->rti_ifa == NULL && ifaaddr != NULL) | if (info->rti_ifa == NULL && ifaaddr != NULL) | ||||
info->rti_ifa = ifa_ifwithaddr(ifaaddr); | info->rti_ifa = ifa_ifwithaddr(ifaaddr); | ||||
if (info->rti_ifa == NULL) { | if (info->rti_ifa == NULL) { | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
sa = ifaaddr != NULL ? ifaaddr : | /* | ||||
(gateway != NULL ? gateway : dst); | * Most common use case for the userland-supplied routes. | ||||
if (sa != NULL && info->rti_ifp != NULL) | * | ||||
* Choose sockaddr to select ifa. | |||||
* -- if ifp is set -- | |||||
* Order of preference: | |||||
* 1) IFA address | |||||
* 2) gateway address | |||||
* Note: for interface routes link-level gateway address | |||||
* is specified to indicate the interface index without | |||||
* specifying RTF_GATEWAY. In this case, ignore gateway | |||||
* Note: gateway AF may be different from dst AF. In this case, | |||||
* ignore gateway | |||||
* 3) final destination. | |||||
* 4) if all of these fails, try to get at least link-level ifa. | |||||
* -- else -- | |||||
* try to lookup gateway or dst in the routing table to get ifa | |||||
*/ | |||||
if (info->rti_info[RTAX_IFA] != NULL) | |||||
sa = info->rti_info[RTAX_IFA]; | |||||
else if ((info->rti_flags & RTF_GATEWAY) != 0 && | |||||
gateway->sa_family == dst->sa_family) | |||||
sa = gateway; | |||||
else | |||||
sa = dst; | |||||
if (info->rti_ifp != NULL) { | |||||
info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); | info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); | ||||
else if (dst != NULL && gateway != NULL) | /* Case 4 */ | ||||
if (info->rti_ifa == NULL && gateway != NULL) | |||||
info->rti_ifa = ifaof_ifpforaddr(gateway, info->rti_ifp); | |||||
} else if (dst != NULL && gateway != NULL) | |||||
info->rti_ifa = ifa_ifwithroute(flags, dst, gateway, | info->rti_ifa = ifa_ifwithroute(flags, dst, gateway, | ||||
fibnum); | fibnum); | ||||
else if (sa != NULL) | else if (sa != NULL) | ||||
info->rti_ifa = ifa_ifwithroute(flags, sa, sa, | info->rti_ifa = ifa_ifwithroute(flags, sa, sa, | ||||
fibnum); | fibnum); | ||||
} | } | ||||
if (needref && info->rti_ifa != NULL) { | if (needref && info->rti_ifa != NULL) { | ||||
if (info->rti_ifp == NULL) | if (info->rti_ifp == NULL) | ||||
▲ Show 20 Lines • Show All 952 Lines • Show Last 20 Lines |