From 2bb0e924cc5d81b56b5eba9cae7011c55a7c6215 Mon Sep 17 00:00:00 2001 From: melifaro Date: Wed, 9 Dec 2015 11:14:27 +0000 Subject: 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 --- sys/netinet/if_ether.c | 26 +++++++++----------------- sys/netinet/in_mcast.c | 17 +++++++---------- sys/netinet/ip_icmp.c | 8 ++++---- sys/netinet/ip_input.c | 27 --------------------------- sys/netinet/ip_options.c | 14 +++++++++----- sys/netinet/ip_var.h | 2 -- sys/netinet6/icmp6.c | 29 ++++++++++------------------- sys/netinet6/in6.c | 23 ++++++++++++----------- sys/netinet6/in6_fib.c | 8 ++++++-- sys/netinet6/in6_mcast.c | 23 ++++++++++------------- sys/netinet6/in6_src.c | 24 +++++++++++------------- 11 files changed, 78 insertions(+), 123 deletions(-) diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 1dfa244..72c2a60 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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 @@ reply: 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 @@ reply: * 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 @@ reply: * 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)); diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index 5c65ce0..f2a985b 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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; diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 57553f5..6e6202a 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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); diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index edcafd5..6f25e08 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -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, diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c index 6db9c91..5daf653 100644 --- a/sys/netinet/ip_options.c +++ b/sys/netinet/ip_options.c @@ -290,15 +290,19 @@ dropit: * 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; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 3416805..f4ad4ff 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -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); diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index c918e69..f0c5371 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -100,6 +100,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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; - - 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); + struct nhop6_basic nh6; + struct in6_addr kdst; + uint32_t scopeid; + + 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, diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index cae186d..b168a53 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -107,6 +107,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include 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; } diff --git a/sys/netinet6/in6_fib.c b/sys/netinet6/in6_fib.c index 70bd1772..eba5b7c 100644 --- a/sys/netinet6/in6_fib.c +++ b/sys/netinet6/in6_fib.c @@ -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 */ } diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c index 131130f..9d96cf5 100644 --- a/sys/netinet6/in6_mcast.c +++ b/sys/netinet6/in6_mcast.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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); } /* diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index 020c5cf..c2e26f8f 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -105,6 +105,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -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; - - 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); + struct nhop6_basic nh6; + struct in6_addr dst; + uint32_t fibnum, scopeid; + int hlim; + + 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); -- cgit v1.1