Index: head/sys/net/route.h =================================================================== --- head/sys/net/route.h +++ head/sys/net/route.h @@ -436,6 +436,8 @@ /* New API */ void rib_walk(int af, u_int fibnum, rt_walktree_f_t *wa_f, void *arg); +struct nhop_object *rib_lookup(uint32_t fibnum, const struct sockaddr *dst, + uint32_t flags, uint32_t flowid); #endif #endif Index: head/sys/net/route.c =================================================================== --- head/sys/net/route.c +++ head/sys/net/route.c @@ -683,7 +683,6 @@ u_int fibnum) { struct ifaddr *ifa; - int not_found = 0; NET_EPOCH_ASSERT(); if ((flags & RTF_GATEWAY) == 0) { @@ -710,34 +709,17 @@ if (ifa == NULL) ifa = ifa_ifwithnet(gateway, 0, fibnum); if (ifa == NULL) { - struct rtentry *rt; + struct nhop_object *nh; - rt = rtalloc1_fib(gateway, 0, flags, fibnum); - if (rt == NULL) - goto out; + nh = rib_lookup(fibnum, gateway, NHR_NONE, 0); + /* * dismiss a gateway that is reachable only * through the default router */ - switch (gateway->sa_family) { - case AF_INET: - if (satosin(rt_key(rt))->sin_addr.s_addr == INADDR_ANY) - not_found = 1; - break; - case AF_INET6: - if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(rt_key(rt))->sin6_addr)) - not_found = 1; - break; - default: - break; - } - if (!not_found && rt->rt_nhop->nh_ifa != NULL) { - ifa = rt->rt_nhop->nh_ifa; - } - RT_REMREF(rt); - RT_UNLOCK(rt); - if (not_found || ifa == NULL) - goto out; + if ((nh == NULL) || (nh->nh_flags & NHF_DEFAULT)) + return (NULL); + ifa = nh->nh_ifa; } if (ifa->ifa_addr->sa_family != dst->sa_family) { struct ifaddr *oifa = ifa; @@ -745,7 +727,7 @@ if (ifa == NULL) ifa = oifa; } - out: + return (ifa); } Index: head/sys/net/route/route_helpers.c =================================================================== --- head/sys/net/route/route_helpers.c +++ head/sys/net/route/route_helpers.c @@ -55,6 +55,12 @@ #include #include #include +#ifdef INET +#include +#endif +#ifdef INET6 +#include +#endif #include /* @@ -79,5 +85,50 @@ RIB_RLOCK(rnh); rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f, arg); RIB_RUNLOCK(rnh); +} + +/* + * Wrapper for the control plane functions for performing af-agnostic + * lookups. + * @fibnum: fib to perform the lookup. + * @dst: sockaddr with family and addr filled in. IPv6 addresses needs to be in + * deembedded from. + * @flags: fib(9) flags. + * @flowid: flow id for path selection in multipath use case. + * + * Returns nhop_object or NULL. + * + * Requires NET_EPOCH. + * + */ +struct nhop_object * +rib_lookup(uint32_t fibnum, const struct sockaddr *dst, uint32_t flags, + uint32_t flowid) +{ + struct nhop_object *nh; + + nh = NULL; + + switch (dst->sa_family) { +#ifdef INET + case AF_INET: + { + const struct sockaddr_in *a = (const struct sockaddr_in *)dst; + nh = fib4_lookup(fibnum, a->sin_addr, 0, flags, flowid); + break; + } +#endif +#ifdef INET6 + case AF_INET6: + { + const struct sockaddr_in6 *a = (const struct sockaddr_in6*)dst; + nh = fib6_lookup(fibnum, &a->sin6_addr, a->sin6_scope_id, + flags, flowid); + break; + } +#endif + } + + return (nh); }