Make in_arpinput(), inp_lookup_mcast_ifp(), icmp_reflect(),
ip_dooptions(), icmp6_redirect_input(), in6_lltable_rtcheck(), in6p_lookup_mcast_ifp() and in6_selecthlim() use new routing api. Eliminate now-unused ip_rtaddr(). Fix lookup key fib6_lookup_nh_basic() which was lost diring merge. Make fib6_lookup_nh_basic() and fib6_lookup_nh_extended() always return IPv6 destination address with embedded scope. Currently rw_gateway has it scope embedded, do the same for non-gatewayed destinations. Sponsored by: Yandex LLC
This commit is contained in:
parent
907809bec0
commit
9977be4a64
@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_fib.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <net/if_llatbl.h>
|
||||
#include <netinet/if_ether.h>
|
||||
@ -671,7 +672,6 @@ in_arpinput(struct mbuf *m)
|
||||
struct arphdr *ah;
|
||||
struct ifnet *ifp = m->m_pkthdr.rcvif;
|
||||
struct llentry *la = NULL, *la_tmp;
|
||||
struct rtentry *rt;
|
||||
struct ifaddr *ifa;
|
||||
struct in_ifaddr *ia;
|
||||
struct sockaddr sa;
|
||||
@ -682,6 +682,8 @@ in_arpinput(struct mbuf *m)
|
||||
int carped;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr *dst;
|
||||
struct nhop4_basic nh4;
|
||||
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = 0;
|
||||
@ -921,10 +923,8 @@ in_arpinput(struct mbuf *m)
|
||||
if (!V_arp_proxyall)
|
||||
goto drop;
|
||||
|
||||
sin.sin_addr = itaddr;
|
||||
/* XXX MRT use table 0 for arp reply */
|
||||
rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
|
||||
if (!rt)
|
||||
if (fib4_lookup_nh_basic(0, itaddr, 0, 0, &nh4) != 0)
|
||||
goto drop;
|
||||
|
||||
/*
|
||||
@ -932,11 +932,8 @@ in_arpinput(struct mbuf *m)
|
||||
* as this one came out of, or we'll get into a fight
|
||||
* over who claims what Ether address.
|
||||
*/
|
||||
if (!rt->rt_ifp || rt->rt_ifp == ifp) {
|
||||
RTFREE_LOCKED(rt);
|
||||
if (nh4.nh_ifp == ifp)
|
||||
goto drop;
|
||||
}
|
||||
RTFREE_LOCKED(rt);
|
||||
|
||||
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
|
||||
(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
|
||||
@ -947,21 +944,16 @@ in_arpinput(struct mbuf *m)
|
||||
* avoids ARP chaos if an interface is connected to the
|
||||
* wrong network.
|
||||
*/
|
||||
sin.sin_addr = isaddr;
|
||||
|
||||
/* XXX MRT use table 0 for arp checks */
|
||||
rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
|
||||
if (!rt)
|
||||
if (fib4_lookup_nh_basic(0, isaddr, 0, 0, &nh4) != 0)
|
||||
goto drop;
|
||||
if (rt->rt_ifp != ifp) {
|
||||
if (nh4.nh_ifp != ifp) {
|
||||
ARP_LOG(LOG_INFO, "proxy: ignoring request"
|
||||
" from %s via %s, expecting %s\n",
|
||||
inet_ntoa(isaddr), ifp->if_xname,
|
||||
rt->rt_ifp->if_xname);
|
||||
RTFREE_LOCKED(rt);
|
||||
" from %s via %s\n",
|
||||
inet_ntoa(isaddr), ifp->if_xname);
|
||||
goto drop;
|
||||
}
|
||||
RTFREE_LOCKED(rt);
|
||||
|
||||
#ifdef DEBUG_PROXY
|
||||
printf("arp: proxying for %s\n", inet_ntoa(itaddr));
|
||||
|
@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_fib.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
@ -1883,6 +1884,8 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
{
|
||||
struct rm_priotracker in_ifa_tracker;
|
||||
struct ifnet *ifp;
|
||||
struct nhop4_basic nh4;
|
||||
uint32_t fibnum;
|
||||
|
||||
KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
|
||||
KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)),
|
||||
@ -1892,16 +1895,10 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
if (!in_nullhost(ina)) {
|
||||
INADDR_TO_IFP(ina, ifp);
|
||||
} else {
|
||||
struct route ro;
|
||||
|
||||
ro.ro_rt = NULL;
|
||||
memcpy(&ro.ro_dst, gsin, sizeof(struct sockaddr_in));
|
||||
in_rtalloc_ign(&ro, 0, inp ? inp->inp_inc.inc_fibnum : 0);
|
||||
if (ro.ro_rt != NULL) {
|
||||
ifp = ro.ro_rt->rt_ifp;
|
||||
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
|
||||
RTFREE(ro.ro_rt);
|
||||
} else {
|
||||
fibnum = inp ? inp->inp_inc.inc_fibnum : 0;
|
||||
if (fib4_lookup_nh_basic(fibnum, gsin->sin_addr, 0, 0, &nh4)==0)
|
||||
ifp = nh4.nh_ifp;
|
||||
else {
|
||||
struct in_ifaddr *ia;
|
||||
struct ifnet *mifp;
|
||||
|
||||
|
@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_fib.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
@ -655,6 +656,7 @@ icmp_reflect(struct mbuf *m)
|
||||
struct ifnet *ifp;
|
||||
struct in_ifaddr *ia;
|
||||
struct in_addr t;
|
||||
struct nhop4_extended nh_ext;
|
||||
struct mbuf *opts = 0;
|
||||
int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
|
||||
|
||||
@ -748,14 +750,12 @@ icmp_reflect(struct mbuf *m)
|
||||
* When we don't have a route back to the packet source, stop here
|
||||
* and drop the packet.
|
||||
*/
|
||||
ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m));
|
||||
if (ia == NULL) {
|
||||
if (fib4_lookup_nh_ext(M_GETFIB(m), ip->ip_dst, 0, 0, &nh_ext) != 0) {
|
||||
m_freem(m);
|
||||
ICMPSTAT_INC(icps_noroute);
|
||||
goto done;
|
||||
}
|
||||
t = IA_SIN(ia)->sin_addr;
|
||||
ifa_free(&ia->ia_ifa);
|
||||
t = nh_ext.nh_src;
|
||||
match:
|
||||
#ifdef MAC
|
||||
mac_netinet_icmp_replyinplace(m);
|
||||
|
@ -878,33 +878,6 @@ ipproto_unregister(short ipproto)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given address of next destination (final or next hop), return (referenced)
|
||||
* internet address info of interface to be used to get there.
|
||||
*/
|
||||
struct in_ifaddr *
|
||||
ip_rtaddr(struct in_addr dst, u_int fibnum)
|
||||
{
|
||||
struct route sro;
|
||||
struct sockaddr_in *sin;
|
||||
struct in_ifaddr *ia;
|
||||
|
||||
bzero(&sro, sizeof(sro));
|
||||
sin = (struct sockaddr_in *)&sro.ro_dst;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(*sin);
|
||||
sin->sin_addr = dst;
|
||||
in_rtalloc_ign(&sro, 0, fibnum);
|
||||
|
||||
if (sro.ro_rt == NULL)
|
||||
return (NULL);
|
||||
|
||||
ia = ifatoia(sro.ro_rt->rt_ifa);
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
RTFREE(sro.ro_rt);
|
||||
return (ia);
|
||||
}
|
||||
|
||||
u_char inetctlerrmap[PRC_NCMDS] = {
|
||||
0, 0, 0, 0,
|
||||
0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
|
||||
|
@ -290,15 +290,19 @@ ip_dooptions(struct mbuf *m, int pass)
|
||||
* destination, use the incoming interface (should be
|
||||
* same).
|
||||
*/
|
||||
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == NULL &&
|
||||
(ia = ip_rtaddr(ipaddr.sin_addr, M_GETFIB(m))) == NULL) {
|
||||
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) != NULL) {
|
||||
memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
ifa_free(&ia->ia_ifa);
|
||||
} else if (fib4_lookup_nh_ext(M_GETFIB(m),
|
||||
ipaddr.sin_addr, 0, 0, &nh_ext) == 0) {
|
||||
memcpy(cp + off, &nh_ext.nh_src,
|
||||
sizeof(struct in_addr));
|
||||
} else {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_HOST;
|
||||
goto bad;
|
||||
}
|
||||
(void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
ifa_free(&ia->ia_ifa);
|
||||
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
||||
break;
|
||||
|
||||
|
@ -222,8 +222,6 @@ int ipproto_register(short);
|
||||
int ipproto_unregister(short);
|
||||
struct mbuf *
|
||||
ip_reass(struct mbuf *);
|
||||
struct in_ifaddr *
|
||||
ip_rtaddr(struct in_addr, u_int fibnum);
|
||||
void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
|
||||
struct mbuf *);
|
||||
void ip_slowtimo(void);
|
||||
|
@ -100,6 +100,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
|
||||
#include <netinet6/in6_fib.h>
|
||||
#include <netinet6/in6_ifattach.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
#include <netinet6/ip6protosw.h>
|
||||
@ -2289,7 +2290,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
||||
int icmp6len = ntohs(ip6->ip6_plen);
|
||||
char *lladdr = NULL;
|
||||
int lladdrlen = 0;
|
||||
struct rtentry *rt = NULL;
|
||||
int is_router;
|
||||
int is_onlink;
|
||||
struct in6_addr src6 = ip6->ip6_src;
|
||||
@ -2344,18 +2344,13 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
||||
}
|
||||
{
|
||||
/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
|
||||
struct sockaddr_in6 sin6;
|
||||
struct in6_addr *gw6;
|
||||
struct nhop6_basic nh6;
|
||||
struct in6_addr kdst;
|
||||
uint32_t scopeid;
|
||||
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
|
||||
rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB);
|
||||
if (rt) {
|
||||
if (rt->rt_gateway == NULL ||
|
||||
rt->rt_gateway->sa_family != AF_INET6) {
|
||||
RTFREE_LOCKED(rt);
|
||||
in6_splitscope(&reddst6, &kdst, &scopeid);
|
||||
if (fib6_lookup_nh_basic(RT_DEFAULT_FIB, &kdst, scopeid, 0, 0,&nh6)==0){
|
||||
if ((nh6.nh_flags & NHF_GATEWAY) == 0) {
|
||||
nd6log((LOG_ERR,
|
||||
"ICMP6 redirect rejected; no route "
|
||||
"with inet6 gateway found for redirect dst: %s\n",
|
||||
@ -2363,14 +2358,12 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
|
||||
if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
|
||||
RTFREE_LOCKED(rt);
|
||||
if (IN6_ARE_ADDR_EQUAL(&src6, &nh6.nh_addr) == 0) {
|
||||
nd6log((LOG_ERR,
|
||||
"ICMP6 redirect rejected; "
|
||||
"not equal to gw-for-src=%s (must be same): "
|
||||
"%s\n",
|
||||
ip6_sprintf(ip6buf, gw6),
|
||||
ip6_sprintf(ip6buf, &nh6.nh_addr),
|
||||
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
||||
goto bad;
|
||||
}
|
||||
@ -2381,8 +2374,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
||||
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
||||
goto bad;
|
||||
}
|
||||
RTFREE_LOCKED(rt);
|
||||
rt = NULL;
|
||||
}
|
||||
if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
|
||||
nd6log((LOG_ERR,
|
||||
|
@ -107,6 +107,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet6/ip6_mroute.h>
|
||||
#include <netinet6/in6_ifattach.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
#include <netinet6/in6_fib.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
|
||||
VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix);
|
||||
@ -2144,17 +2145,22 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
{
|
||||
struct rtentry *rt;
|
||||
const struct sockaddr_in6 *sin6;
|
||||
struct nhop6_basic nh6;
|
||||
struct in6_addr dst;
|
||||
uint32_t scopeid;
|
||||
int error;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
|
||||
KASSERT(l3addr->sa_family == AF_INET6,
|
||||
("sin_family %d", l3addr->sa_family));
|
||||
|
||||
/* Our local addresses are always only installed on the default FIB. */
|
||||
/* XXX rtalloc1 should take a const param */
|
||||
rt = in6_rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0,
|
||||
RT_DEFAULT_FIB);
|
||||
if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
|
||||
|
||||
sin6 = (const struct sockaddr_in6 *)l3addr;
|
||||
in6_splitscope(&sin6->sin6_addr, &dst, &scopeid);
|
||||
error = fib6_lookup_nh_basic(RT_DEFAULT_FIB, &dst, scopeid, 0, 0, &nh6);
|
||||
if (error != 0 || (nh6.nh_flags & NHF_GATEWAY) || nh6.nh_ifp != ifp) {
|
||||
struct ifaddr *ifa;
|
||||
/*
|
||||
* Create an ND6 cache for an IPv6 neighbor
|
||||
@ -2163,17 +2169,12 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
ifa = ifaof_ifpforaddr(l3addr, ifp);
|
||||
if (ifa != NULL) {
|
||||
ifa_free(ifa);
|
||||
if (rt != NULL)
|
||||
RTFREE_LOCKED(rt);
|
||||
return 0;
|
||||
}
|
||||
log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
|
||||
ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
|
||||
if (rt != NULL)
|
||||
RTFREE_LOCKED(rt);
|
||||
ip6_sprintf(ip6buf, &sin6->sin6_addr));
|
||||
return EINVAL;
|
||||
}
|
||||
RTFREE_LOCKED(rt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,7 @@ fib6_rte_to_nh_extended(struct rtentry *rte, const struct in6_addr *dst,
|
||||
* interface "ix0" pointer to "ix0" interface will be returned instead
|
||||
* of "lo0")
|
||||
* - howewer mtu from "transmit" interface will be returned.
|
||||
* - scope will be embedded in nh_addr
|
||||
*/
|
||||
int
|
||||
fib6_lookup_nh_basic(uint32_t fibnum, const struct in6_addr *dst, uint32_t scopeid,
|
||||
@ -182,6 +183,7 @@ fib6_lookup_nh_basic(uint32_t fibnum, const struct in6_addr *dst, uint32_t scope
|
||||
/* Prepare lookup key */
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_addr = *dst;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
/* Assume scopeid is valid and embed it directly */
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(dst))
|
||||
sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
|
||||
@ -192,7 +194,7 @@ fib6_lookup_nh_basic(uint32_t fibnum, const struct in6_addr *dst, uint32_t scope
|
||||
rte = RNTORT(rn);
|
||||
/* Ensure route & ifp is UP */
|
||||
if (RT_LINK_IS_UP(rte->rt_ifp)) {
|
||||
fib6_rte_to_nh_basic(rte, dst, flags, pnh6);
|
||||
fib6_rte_to_nh_basic(rte, &sin6.sin6_addr, flags, pnh6);
|
||||
RADIX_NODE_HEAD_RUNLOCK(rh);
|
||||
return (0);
|
||||
}
|
||||
@ -211,6 +213,7 @@ fib6_lookup_nh_basic(uint32_t fibnum, const struct in6_addr *dst, uint32_t scope
|
||||
* - nh_ifp represents logical transmit interface (rt_ifp) by default
|
||||
* - nh_ifp represents "address" interface if NHR_IFAIF flag is passed
|
||||
* - mtu from logical transmit interface will be returned.
|
||||
* - scope will be embedded in nh_addr
|
||||
*/
|
||||
int
|
||||
fib6_lookup_nh_ext(uint32_t fibnum, const struct in6_addr *dst,uint32_t scopeid,
|
||||
@ -240,7 +243,8 @@ fib6_lookup_nh_ext(uint32_t fibnum, const struct in6_addr *dst,uint32_t scopeid,
|
||||
rte = RNTORT(rn);
|
||||
/* Ensure route & ifp is UP */
|
||||
if (RT_LINK_IS_UP(rte->rt_ifp)) {
|
||||
fib6_rte_to_nh_extended(rte, dst, flags, pnh6);
|
||||
fib6_rte_to_nh_extended(rte, &sin6.sin6_addr, flags,
|
||||
pnh6);
|
||||
if ((flags & NHR_REF) != 0) {
|
||||
/* TODO: Do lwref on egress ifp's */
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet6/in6_fib.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
@ -1772,26 +1773,22 @@ static struct ifnet *
|
||||
in6p_lookup_mcast_ifp(const struct inpcb *in6p,
|
||||
const struct sockaddr_in6 *gsin6)
|
||||
{
|
||||
struct route_in6 ro6;
|
||||
struct ifnet *ifp;
|
||||
struct nhop6_basic nh6;
|
||||
struct in6_addr dst;
|
||||
uint32_t scopeid;
|
||||
uint32_t fibnum;
|
||||
|
||||
KASSERT(in6p->inp_vflag & INP_IPV6,
|
||||
("%s: not INP_IPV6 inpcb", __func__));
|
||||
KASSERT(gsin6->sin6_family == AF_INET6,
|
||||
("%s: not AF_INET6 group", __func__));
|
||||
|
||||
ifp = NULL;
|
||||
memset(&ro6, 0, sizeof(struct route_in6));
|
||||
memcpy(&ro6.ro_dst, gsin6, sizeof(struct sockaddr_in6));
|
||||
rtalloc_ign_fib((struct route *)&ro6, 0,
|
||||
in6p ? in6p->inp_inc.inc_fibnum : RT_DEFAULT_FIB);
|
||||
if (ro6.ro_rt != NULL) {
|
||||
ifp = ro6.ro_rt->rt_ifp;
|
||||
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
|
||||
RTFREE(ro6.ro_rt);
|
||||
}
|
||||
in6_splitscope(&gsin6->sin6_addr, &dst, &scopeid);
|
||||
fibnum = in6p ? in6p->inp_inc.inc_fibnum : RT_DEFAULT_FIB;
|
||||
if (fib6_lookup_nh_basic(fibnum, &dst, scopeid, 0, 0, &nh6) != 0)
|
||||
return (NULL);
|
||||
|
||||
return (ifp);
|
||||
return (nh6.nh_ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -105,6 +105,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet6/in6_fib.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
@ -860,19 +861,16 @@ in6_selecthlim(struct inpcb *in6p, struct ifnet *ifp)
|
||||
else if (ifp)
|
||||
return (ND_IFINFO(ifp)->chlim);
|
||||
else if (in6p && !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
|
||||
struct route_in6 ro6;
|
||||
struct ifnet *lifp;
|
||||
struct nhop6_basic nh6;
|
||||
struct in6_addr dst;
|
||||
uint32_t fibnum, scopeid;
|
||||
int hlim;
|
||||
|
||||
bzero(&ro6, sizeof(ro6));
|
||||
ro6.ro_dst.sin6_family = AF_INET6;
|
||||
ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ro6.ro_dst.sin6_addr = in6p->in6p_faddr;
|
||||
in6_rtalloc(&ro6, in6p->inp_inc.inc_fibnum);
|
||||
if (ro6.ro_rt) {
|
||||
lifp = ro6.ro_rt->rt_ifp;
|
||||
RTFREE(ro6.ro_rt);
|
||||
if (lifp)
|
||||
return (ND_IFINFO(lifp)->chlim);
|
||||
fibnum = in6p->inp_inc.inc_fibnum;
|
||||
in6_splitscope(&in6p->in6p_faddr, &dst, &scopeid);
|
||||
if (fib6_lookup_nh_basic(fibnum, &dst, scopeid, 0, 0, &nh6)==0){
|
||||
hlim = ND_IFINFO(nh6.nh_ifp)->chlim;
|
||||
return (hlim);
|
||||
}
|
||||
}
|
||||
return (V_ip6_defhlim);
|
||||
|
Loading…
Reference in New Issue
Block a user