Complete conversions from fib<4|6>_lookup_nh_<basic|ext> to fib<4|6>_lookup().
fib[46]_lookup_nh_ represents pre-epoch generation of fib api, providing less guarantees over pointer validness and requiring on-stack data copying. With no callers remaining, remove fib[46]_lookup_nh_ functions. Submitted by: Neel Chauhan <neel AT neelc DOT org> Differential Revision: https://reviews.freebsd.org/D25445
This commit is contained in:
parent
f60b4812d8
commit
6ad7446c6f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=362900
@ -97,6 +97,7 @@
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_clone.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/vnet.h>
|
||||
@ -568,12 +569,14 @@ stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp)
|
||||
* perform ingress filter
|
||||
*/
|
||||
if (sc && (STF2IFP(sc)->if_flags & IFF_LINK2) == 0 && inifp) {
|
||||
struct nhop4_basic nh4;
|
||||
struct nhop_object *nh;
|
||||
|
||||
if (fib4_lookup_nh_basic(sc->sc_fibnum, *in, 0, 0, &nh4) != 0)
|
||||
NET_EPOCH_ASSERT();
|
||||
nh = fib4_lookup(sc->sc_fibnum, *in, 0, 0, 0);
|
||||
if (nh == NULL)
|
||||
return (-1);
|
||||
|
||||
if (nh4.nh_ifp != inifp)
|
||||
if (nh->nh_ifp != inifp)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/netisr.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
@ -804,7 +805,7 @@ in_arpinput(struct mbuf *m)
|
||||
int carped;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr *dst;
|
||||
struct nhop4_basic nh4;
|
||||
struct nhop_object *nh;
|
||||
uint8_t linkhdr[LLE_MAX_LINKHDR];
|
||||
struct route ro;
|
||||
size_t linkhdrsize;
|
||||
@ -1065,8 +1066,9 @@ in_arpinput(struct mbuf *m)
|
||||
if (!V_arp_proxyall)
|
||||
goto drop;
|
||||
|
||||
if (fib4_lookup_nh_basic(ifp->if_fib, itaddr, 0, 0,
|
||||
&nh4) != 0)
|
||||
NET_EPOCH_ASSERT();
|
||||
nh = fib4_lookup(ifp->if_fib, itaddr, 0, 0, 0);
|
||||
if (nh == NULL)
|
||||
goto drop;
|
||||
|
||||
/*
|
||||
@ -1074,7 +1076,7 @@ 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 (nh4.nh_ifp == ifp)
|
||||
if (nh->nh_ifp == ifp)
|
||||
goto drop;
|
||||
|
||||
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
|
||||
@ -1087,10 +1089,10 @@ in_arpinput(struct mbuf *m)
|
||||
* wrong network.
|
||||
*/
|
||||
|
||||
if (fib4_lookup_nh_basic(ifp->if_fib, isaddr, 0, 0,
|
||||
&nh4) != 0)
|
||||
nh = fib4_lookup(ifp->if_fib, isaddr, 0, 0, 0);
|
||||
if (nh == NULL)
|
||||
goto drop;
|
||||
if (nh4.nh_ifp != ifp) {
|
||||
if (nh->nh_ifp != ifp) {
|
||||
ARP_LOG(LOG_INFO, "proxy: ignoring request"
|
||||
" from %s via %s\n",
|
||||
inet_ntoa_r(isaddr, addrbuf),
|
||||
|
@ -66,165 +66,6 @@ __FBSDID("$FreeBSD$");
|
||||
/* Verify struct route compatiblity */
|
||||
/* Assert 'struct route_in' is compatible with 'struct route' */
|
||||
CHK_STRUCT_ROUTE_COMPAT(struct route_in, ro_dst4);
|
||||
static void fib4_rte_to_nh_basic(struct nhop_object *nh, struct in_addr dst,
|
||||
uint32_t flags, struct nhop4_basic *pnh4);
|
||||
static void fib4_rte_to_nh_extended(struct nhop_object *nh, struct in_addr dst,
|
||||
uint32_t flags, struct nhop4_extended *pnh4);
|
||||
|
||||
|
||||
static void
|
||||
fib4_rte_to_nh_basic(struct nhop_object *nh, struct in_addr dst,
|
||||
uint32_t flags, struct nhop4_basic *pnh4)
|
||||
{
|
||||
|
||||
if ((flags & NHR_IFAIF) != 0)
|
||||
pnh4->nh_ifp = nh->nh_ifa->ifa_ifp;
|
||||
else
|
||||
pnh4->nh_ifp = nh->nh_ifp;
|
||||
pnh4->nh_mtu = nh->nh_mtu;
|
||||
if (nh->nh_flags & NHF_GATEWAY)
|
||||
pnh4->nh_addr = nh->gw4_sa.sin_addr;
|
||||
else
|
||||
pnh4->nh_addr = dst;
|
||||
/* Set flags */
|
||||
pnh4->nh_flags = nh->nh_flags;
|
||||
/* TODO: Handle RTF_BROADCAST here */
|
||||
}
|
||||
|
||||
static void
|
||||
fib4_rte_to_nh_extended(struct nhop_object *nh, struct in_addr dst,
|
||||
uint32_t flags, struct nhop4_extended *pnh4)
|
||||
{
|
||||
|
||||
if ((flags & NHR_IFAIF) != 0)
|
||||
pnh4->nh_ifp = nh->nh_ifa->ifa_ifp;
|
||||
else
|
||||
pnh4->nh_ifp = nh->nh_ifp;
|
||||
pnh4->nh_mtu = nh->nh_mtu;
|
||||
if (nh->nh_flags & NHF_GATEWAY)
|
||||
pnh4->nh_addr = nh->gw4_sa.sin_addr;
|
||||
else
|
||||
pnh4->nh_addr = dst;
|
||||
/* Set flags */
|
||||
pnh4->nh_flags = nh->nh_flags;
|
||||
pnh4->nh_ia = ifatoia(nh->nh_ifa);
|
||||
pnh4->nh_src = IA_SIN(pnh4->nh_ia)->sin_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs IPv4 route table lookup on @dst. Returns 0 on success.
|
||||
* Stores nexthop info provided @pnh4 structure.
|
||||
* Note that
|
||||
* - nh_ifp cannot be safely dereferenced
|
||||
* - nh_ifp represents logical transmit interface (rt_ifp) (e.g. if
|
||||
* looking up address on interface "ix0" pointer to "lo0" interface
|
||||
* will be returned instead of "ix0")
|
||||
* - nh_ifp represents "address" interface if NHR_IFAIF flag is passed
|
||||
* - howewer mtu from "transmit" interface will be returned.
|
||||
*/
|
||||
int
|
||||
fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flags,
|
||||
uint32_t flowid, struct nhop4_basic *pnh4)
|
||||
{
|
||||
RIB_RLOCK_TRACKER;
|
||||
struct rib_head *rh;
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in sin;
|
||||
struct nhop_object *nh;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_basic: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
if (rh == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
/* Prepare lookup key */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_addr = dst;
|
||||
|
||||
RIB_RLOCK(rh);
|
||||
rn = rh->rnh_matchaddr((void *)&sin, &rh->head);
|
||||
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
|
||||
nh = RNTORT(rn)->rt_nhop;
|
||||
/* Ensure route & ifp is UP */
|
||||
if (RT_LINK_IS_UP(nh->nh_ifp)) {
|
||||
fib4_rte_to_nh_basic(nh, dst, flags, pnh4);
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs IPv4 route table lookup on @dst. Returns 0 on success.
|
||||
* Stores extende nexthop info provided @pnh4 structure.
|
||||
* Note that
|
||||
* - nh_ifp cannot be safely dereferenced unless NHR_REF is specified.
|
||||
* - in that case you need to call fib4_free_nh_ext()
|
||||
* - nh_ifp represents logical transmit interface (rt_ifp) (e.g. if
|
||||
* looking up address of interface "ix0" pointer to "lo0" interface
|
||||
* will be returned instead of "ix0")
|
||||
* - nh_ifp represents "address" interface if NHR_IFAIF flag is passed
|
||||
* - howewer mtu from "transmit" interface will be returned.
|
||||
*/
|
||||
int
|
||||
fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flags,
|
||||
uint32_t flowid, struct nhop4_extended *pnh4)
|
||||
{
|
||||
RIB_RLOCK_TRACKER;
|
||||
struct rib_head *rh;
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in sin;
|
||||
struct rtentry *rte;
|
||||
struct nhop_object *nh;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ext: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
if (rh == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
/* Prepare lookup key */
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_addr = dst;
|
||||
|
||||
RIB_RLOCK(rh);
|
||||
rn = rh->rnh_matchaddr((void *)&sin, &rh->head);
|
||||
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
|
||||
rte = RNTORT(rn);
|
||||
#ifdef RADIX_MPATH
|
||||
rte = rt_mpath_select(rte, flowid);
|
||||
if (rte == NULL) {
|
||||
RIB_RUNLOCK(rh);
|
||||
return (ENOENT);
|
||||
}
|
||||
#endif
|
||||
nh = rte->rt_nhop;
|
||||
/* Ensure route & ifp is UP */
|
||||
if (RT_LINK_IS_UP(nh->nh_ifp)) {
|
||||
fib4_rte_to_nh_extended(nh, dst, flags, pnh4);
|
||||
if ((flags & NHR_REF) != 0) {
|
||||
/* TODO: lwref on egress ifp's ? */
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
void
|
||||
fib4_free_nh_ext(uint32_t fibnum, struct nhop4_extended *pnh4)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks up path in fib @fibnum specified by @dst.
|
||||
|
@ -45,32 +45,6 @@ struct route_in {
|
||||
struct sockaddr_in ro_dst4;
|
||||
};
|
||||
|
||||
/* Basic nexthop info used for uRPF/mtu checks */
|
||||
struct nhop4_basic {
|
||||
struct ifnet *nh_ifp; /* Logical egress interface */
|
||||
uint16_t nh_mtu; /* nexthop mtu */
|
||||
uint16_t nh_flags; /* nhop flags */
|
||||
struct in_addr nh_addr; /* GW/DST IPv4 address */
|
||||
};
|
||||
|
||||
/* Extended nexthop info used for control protocols */
|
||||
struct nhop4_extended {
|
||||
struct ifnet *nh_ifp; /* Logical egress interface */
|
||||
struct in_ifaddr *nh_ia; /* Associated address */
|
||||
uint16_t nh_mtu; /* nexthop mtu */
|
||||
uint16_t nh_flags; /* nhop flags */
|
||||
uint8_t spare[4];
|
||||
struct in_addr nh_addr; /* GW/DST IPv4 address */
|
||||
struct in_addr nh_src; /* default source IPv4 address */
|
||||
uint64_t spare2;
|
||||
};
|
||||
|
||||
int fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flags,
|
||||
uint32_t flowid, struct nhop4_basic *pnh4);
|
||||
int fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flags,
|
||||
uint32_t flowid, struct nhop4_extended *pnh4);
|
||||
void fib4_free_nh_ext(uint32_t fibnum, struct nhop4_extended *pnh4);
|
||||
|
||||
struct nhop_object *fib4_lookup(uint32_t fibnum, struct in_addr dst,
|
||||
uint32_t scopeid, uint32_t flags, uint32_t flowid);
|
||||
int fib4_check_urpf(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
|
||||
|
@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
@ -1902,7 +1903,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
{
|
||||
struct rm_priotracker in_ifa_tracker;
|
||||
struct ifnet *ifp;
|
||||
struct nhop4_basic nh4;
|
||||
struct nhop_object *nh;
|
||||
uint32_t fibnum;
|
||||
|
||||
KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
|
||||
@ -1916,8 +1917,9 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
|
||||
} 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;
|
||||
nh = fib4_lookup(fibnum, gsin->sin_addr, 0, 0, 0);
|
||||
if (nh != NULL)
|
||||
ifp = nh->nh_ifp;
|
||||
else {
|
||||
struct in_ifaddr *ia;
|
||||
struct ifnet *mifp;
|
||||
@ -2726,6 +2728,7 @@ inp_setmoptions(struct inpcb *inp, struct sockopt *sopt)
|
||||
{
|
||||
struct ip_moptions *imo;
|
||||
int error;
|
||||
struct epoch_tracker et;
|
||||
|
||||
error = 0;
|
||||
|
||||
@ -2832,7 +2835,9 @@ inp_setmoptions(struct inpcb *inp, struct sockopt *sopt)
|
||||
case IP_ADD_SOURCE_MEMBERSHIP:
|
||||
case MCAST_JOIN_GROUP:
|
||||
case MCAST_JOIN_SOURCE_GROUP:
|
||||
NET_EPOCH_ENTER(et);
|
||||
error = inp_join_group(inp, sopt);
|
||||
NET_EPOCH_EXIT(et);
|
||||
break;
|
||||
|
||||
case IP_DROP_MEMBERSHIP:
|
||||
|
@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
@ -107,7 +108,7 @@ ip_dooptions(struct mbuf *m, int pass)
|
||||
int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
|
||||
struct in_addr *sin, dst;
|
||||
uint32_t ntime;
|
||||
struct nhop4_extended nh_ext;
|
||||
struct nhop_object *nh;
|
||||
struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
@ -254,11 +255,12 @@ ip_dooptions(struct mbuf *m, int pass)
|
||||
sizeof(struct in_addr));
|
||||
} else {
|
||||
/* XXX MRT 0 for routing */
|
||||
if (fib4_lookup_nh_ext(M_GETFIB(m),
|
||||
ipaddr.sin_addr, 0, 0, &nh_ext) != 0)
|
||||
nh = fib4_lookup(M_GETFIB(m), ipaddr.sin_addr,
|
||||
0, NHR_NONE, 0);
|
||||
if (nh == NULL)
|
||||
goto bad;
|
||||
|
||||
memcpy(cp + off, &nh_ext.nh_src,
|
||||
memcpy(cp + off, &(IA_SIN(nh->nh_ifa)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
@ -299,9 +301,9 @@ ip_dooptions(struct mbuf *m, int pass)
|
||||
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) != NULL) {
|
||||
memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
} else if (fib4_lookup_nh_ext(M_GETFIB(m),
|
||||
ipaddr.sin_addr, 0, 0, &nh_ext) == 0) {
|
||||
memcpy(cp + off, &nh_ext.nh_src,
|
||||
} else if ((nh = fib4_lookup(M_GETFIB(m),
|
||||
ipaddr.sin_addr, 0, NHR_NONE, 0)) != NULL) {
|
||||
memcpy(cp + off, &(IA_SIN(nh->nh_ifa)->sin_addr),
|
||||
sizeof(struct in_addr));
|
||||
} else {
|
||||
type = ICMP_UNREACH;
|
||||
|
@ -2270,13 +2270,17 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
||||
}
|
||||
{
|
||||
/* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
|
||||
struct nhop6_basic nh6;
|
||||
struct nhop_object *nh;
|
||||
struct in6_addr kdst;
|
||||
uint32_t scopeid;
|
||||
|
||||
in6_splitscope(&reddst6, &kdst, &scopeid);
|
||||
if (fib6_lookup_nh_basic(ifp->if_fib, &kdst, scopeid, 0, 0,&nh6)==0){
|
||||
if ((nh6.nh_flags & NHF_GATEWAY) == 0) {
|
||||
NET_EPOCH_ASSERT();
|
||||
nh = fib6_lookup(ifp->if_fib, &kdst, scopeid, 0, 0);
|
||||
if (nh == NULL) {
|
||||
struct in6_addr nh_addr;
|
||||
nh_addr = ifatoia6(nh->nh_ifa)->ia_addr.sin6_addr;
|
||||
if ((nh->nh_flags & NHF_GATEWAY) == 0) {
|
||||
nd6log((LOG_ERR,
|
||||
"ICMP6 redirect rejected; no route "
|
||||
"with inet6 gateway found for redirect dst: %s\n",
|
||||
@ -2285,19 +2289,16 @@ icmp6_redirect_input(struct mbuf *m, int off)
|
||||
}
|
||||
|
||||
/*
|
||||
* Embed scope zone id into next hop address, since
|
||||
* fib6_lookup_nh_basic() returns address without embedded
|
||||
* scope zone id.
|
||||
* Embed scope zone id into next hop address.
|
||||
*/
|
||||
if (in6_setscope(&nh6.nh_addr, m->m_pkthdr.rcvif, NULL))
|
||||
goto freeit;
|
||||
nh_addr = nh->gw6_sa.sin6_addr;
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(&src6, &nh6.nh_addr) == 0) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&src6, &nh_addr) == 0) {
|
||||
nd6log((LOG_ERR,
|
||||
"ICMP6 redirect rejected; "
|
||||
"not equal to gw-for-src=%s (must be same): "
|
||||
"%s\n",
|
||||
ip6_sprintf(ip6buf, &nh6.nh_addr),
|
||||
ip6_sprintf(ip6buf, &nh_addr),
|
||||
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
|
||||
goto bad;
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
@ -2141,10 +2142,9 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
const struct sockaddr *l3addr)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6;
|
||||
struct nhop6_basic nh6;
|
||||
struct nhop_object *nh;
|
||||
struct in6_addr dst;
|
||||
uint32_t scopeid;
|
||||
int error;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
int fibnum;
|
||||
|
||||
@ -2155,8 +2155,8 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
sin6 = (const struct sockaddr_in6 *)l3addr;
|
||||
in6_splitscope(&sin6->sin6_addr, &dst, &scopeid);
|
||||
fibnum = V_rt_add_addr_allfibs ? RT_DEFAULT_FIB : ifp->if_fib;
|
||||
error = fib6_lookup_nh_basic(fibnum, &dst, scopeid, 0, 0, &nh6);
|
||||
if (error != 0 || (nh6.nh_flags & NHF_GATEWAY) || nh6.nh_ifp != ifp) {
|
||||
nh = fib6_lookup(fibnum, &dst, scopeid, NHR_NONE, 0);
|
||||
if (nh && ((nh->nh_flags & NHF_GATEWAY) || nh->nh_ifp != ifp)) {
|
||||
struct ifaddr *ifa;
|
||||
/*
|
||||
* Create an ND6 cache for an IPv6 neighbor
|
||||
|
@ -70,187 +70,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_types.h>
|
||||
|
||||
#ifdef INET6
|
||||
static void fib6_rte_to_nh_extended(const struct nhop_object *nh,
|
||||
const struct in6_addr *dst, uint32_t flags, struct nhop6_extended *pnh6);
|
||||
static void fib6_rte_to_nh_basic(const struct nhop_object *nh, const struct in6_addr *dst,
|
||||
uint32_t flags, struct nhop6_basic *pnh6);
|
||||
|
||||
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
|
||||
CHK_STRUCT_ROUTE_COMPAT(struct route_in6, ro_dst);
|
||||
|
||||
|
||||
|
||||
static void
|
||||
fib6_rte_to_nh_basic(const struct nhop_object *nh, const struct in6_addr *dst,
|
||||
uint32_t flags, struct nhop6_basic *pnh6)
|
||||
{
|
||||
|
||||
/* Do explicit nexthop zero unless we're copying it */
|
||||
memset(pnh6, 0, sizeof(*pnh6));
|
||||
|
||||
if ((flags & NHR_IFAIF) != 0)
|
||||
pnh6->nh_ifp = nh->nh_aifp;
|
||||
else
|
||||
pnh6->nh_ifp = nh->nh_ifp;
|
||||
|
||||
pnh6->nh_mtu = nh->nh_mtu;
|
||||
if (nh->nh_flags & NHF_GATEWAY) {
|
||||
/* Return address with embedded scope. */
|
||||
pnh6->nh_addr = nh->gw6_sa.sin6_addr;
|
||||
} else
|
||||
pnh6->nh_addr = *dst;
|
||||
/* Set flags */
|
||||
pnh6->nh_flags = nh->nh_flags;
|
||||
}
|
||||
|
||||
static void
|
||||
fib6_rte_to_nh_extended(const struct nhop_object *nh, const struct in6_addr *dst,
|
||||
uint32_t flags, struct nhop6_extended *pnh6)
|
||||
{
|
||||
|
||||
/* Do explicit nexthop zero unless we're copying it */
|
||||
memset(pnh6, 0, sizeof(*pnh6));
|
||||
|
||||
if ((flags & NHR_IFAIF) != 0)
|
||||
pnh6->nh_ifp = nh->nh_aifp;
|
||||
else
|
||||
pnh6->nh_ifp = nh->nh_ifp;
|
||||
|
||||
pnh6->nh_mtu = nh->nh_mtu;
|
||||
if (nh->nh_flags & NHF_GATEWAY) {
|
||||
/* Return address with embedded scope. */
|
||||
pnh6->nh_addr = nh->gw6_sa.sin6_addr;
|
||||
} else
|
||||
pnh6->nh_addr = *dst;
|
||||
/* Set flags */
|
||||
pnh6->nh_flags = nh->nh_flags;
|
||||
pnh6->nh_ia = ifatoia6(nh->nh_ifa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs IPv6 route table lookup on @dst. Returns 0 on success.
|
||||
* Stores basic nexthop info into provided @pnh6 structure.
|
||||
* Note that
|
||||
* - 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.
|
||||
* - nh_ifp cannot be safely dereferenced
|
||||
* - nh_ifp represents rt_ifp (e.g. if looking up address on
|
||||
* 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,
|
||||
uint32_t flags, uint32_t flowid, struct nhop6_basic *pnh6)
|
||||
{
|
||||
RIB_RLOCK_TRACKER;
|
||||
struct rib_head *rh;
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct nhop_object *nh;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_basic: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET6);
|
||||
if (rh == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
/* 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);
|
||||
|
||||
RIB_RLOCK(rh);
|
||||
rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
|
||||
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
|
||||
nh = RNTORT(rn)->rt_nhop;
|
||||
/* Ensure route & ifp is UP */
|
||||
if (RT_LINK_IS_UP(nh->nh_ifp)) {
|
||||
fib6_rte_to_nh_basic(nh, &sin6.sin6_addr, flags, pnh6);
|
||||
RIB_RUNLOCK(rh);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs IPv6 route table lookup on @dst. Returns 0 on success.
|
||||
* Stores extended nexthop info into provided @pnh6 structure.
|
||||
* Note that
|
||||
* - nh_ifp cannot be safely dereferenced unless NHR_REF is specified.
|
||||
* - in that case you need to call fib6_free_nh_ext()
|
||||
* - 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,
|
||||
uint32_t flags, uint32_t flowid, struct nhop6_extended *pnh6)
|
||||
{
|
||||
RIB_RLOCK_TRACKER;
|
||||
struct rib_head *rh;
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct rtentry *rte;
|
||||
struct nhop_object *nh;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_ext: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET6);
|
||||
if (rh == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
/* Prepare lookup key */
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_addr = *dst;
|
||||
/* Assume scopeid is valid and embed it directly */
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(dst))
|
||||
sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
|
||||
|
||||
RIB_RLOCK(rh);
|
||||
rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
|
||||
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
|
||||
rte = RNTORT(rn);
|
||||
#ifdef RADIX_MPATH
|
||||
rte = rt_mpath_select(rte, flowid);
|
||||
if (rte == NULL) {
|
||||
RIB_RUNLOCK(rh);
|
||||
return (ENOENT);
|
||||
}
|
||||
#endif
|
||||
nh = rte->rt_nhop;
|
||||
/* Ensure route & ifp is UP */
|
||||
if (RT_LINK_IS_UP(nh->nh_ifp)) {
|
||||
fib6_rte_to_nh_extended(nh, &sin6.sin6_addr, flags,
|
||||
pnh6);
|
||||
if ((flags & NHR_REF) != 0) {
|
||||
/* TODO: Do lwref on egress ifp's */
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
void
|
||||
fib6_free_nh_ext(uint32_t fibnum, struct nhop6_extended *pnh6)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks up path in fib @fibnum specified by @dst.
|
||||
* Assumes scope is deembedded and provided in @scopeid.
|
||||
|
@ -32,33 +32,6 @@
|
||||
#ifndef _NETINET6_IN6_FIB_H_
|
||||
#define _NETINET6_IN6_FIB_H_
|
||||
|
||||
/* Basic nexthop info used for uRPF/mtu checks */
|
||||
struct nhop6_basic {
|
||||
struct ifnet *nh_ifp; /* Logical egress interface */
|
||||
uint16_t nh_mtu; /* nexthop mtu */
|
||||
uint16_t nh_flags; /* nhop flags */
|
||||
uint8_t spare[4];
|
||||
struct in6_addr nh_addr; /* GW/DST IPv4 address */
|
||||
};
|
||||
|
||||
/* Extended nexthop info used for control protocols. */
|
||||
struct nhop6_extended {
|
||||
struct ifnet *nh_ifp; /* Logical egress interface */
|
||||
struct in6_ifaddr *nh_ia; /* Associated address. */
|
||||
uint16_t nh_mtu; /* nexthop mtu */
|
||||
uint16_t nh_flags; /* nhop flags */
|
||||
uint8_t spare[4];
|
||||
struct in6_addr nh_addr; /* GW/DST IPv6 address */
|
||||
uint64_t spare2[1];
|
||||
};
|
||||
|
||||
int fib6_lookup_nh_basic(uint32_t fibnum, const struct in6_addr *dst,
|
||||
uint32_t scopeid, uint32_t flags, uint32_t flowid,struct nhop6_basic *pnh6);
|
||||
int fib6_lookup_nh_ext(uint32_t fibnum, const struct in6_addr *dst,
|
||||
uint32_t scopeid, uint32_t flags, uint32_t flowid,
|
||||
struct nhop6_extended *pnh6);
|
||||
void fib6_free_nh_ext(uint32_t fibnum, struct nhop6_extended *pnh6);
|
||||
|
||||
struct nhop_object *fib6_lookup(uint32_t fibnum,
|
||||
const struct in6_addr *dst6, uint32_t scopeid, uint32_t flags,
|
||||
uint32_t flowid);
|
||||
|
@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
@ -1829,7 +1830,7 @@ static struct ifnet *
|
||||
in6p_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
const struct sockaddr_in6 *gsin6)
|
||||
{
|
||||
struct nhop6_basic nh6;
|
||||
struct nhop_object *nh;
|
||||
struct in6_addr dst;
|
||||
uint32_t scopeid;
|
||||
uint32_t fibnum;
|
||||
@ -1841,10 +1842,9 @@ in6p_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
|
||||
in6_splitscope(&gsin6->sin6_addr, &dst, &scopeid);
|
||||
fibnum = inp ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB;
|
||||
if (fib6_lookup_nh_basic(fibnum, &dst, scopeid, 0, 0, &nh6) != 0)
|
||||
return (NULL);
|
||||
nh = fib6_lookup(fibnum, &dst, scopeid, 0, 0);
|
||||
|
||||
return (nh6.nh_ifp);
|
||||
return (nh ? nh->nh_ifp : NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -916,15 +916,16 @@ in6_selecthlim(struct inpcb *inp, struct ifnet *ifp)
|
||||
else if (ifp)
|
||||
return (ND_IFINFO(ifp)->chlim);
|
||||
else if (inp && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
|
||||
struct nhop6_basic nh6;
|
||||
struct nhop_object *nh;
|
||||
struct in6_addr dst;
|
||||
uint32_t fibnum, scopeid;
|
||||
int hlim;
|
||||
|
||||
fibnum = inp->inp_inc.inc_fibnum;
|
||||
in6_splitscope(&inp->in6p_faddr, &dst, &scopeid);
|
||||
if (fib6_lookup_nh_basic(fibnum, &dst, scopeid, 0, 0, &nh6)==0){
|
||||
hlim = ND_IFINFO(nh6.nh_ifp)->chlim;
|
||||
nh = fib6_lookup(fibnum, &dst, scopeid, 0, 0);
|
||||
if (nh != NULL) {
|
||||
hlim = ND_IFINFO(nh->nh_ifp)->chlim;
|
||||
return (hlim);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/pfil.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
@ -466,9 +467,10 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
|
||||
#if defined(USERSPACE) || !defined(__FreeBSD__)
|
||||
return 0;
|
||||
#else
|
||||
struct nhop4_basic nh4;
|
||||
struct nhop_object *nh;
|
||||
|
||||
if (fib4_lookup_nh_basic(fib, src, NHR_IFAIF, 0, &nh4) != 0)
|
||||
nh = fib4_lookup(fib, src, 0, NHR_NONE, 0);
|
||||
if (nh == NULL)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
@ -478,15 +480,15 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
|
||||
* routing entry (via lo0) for our own address
|
||||
* may exist, so we need to handle routing assymetry.
|
||||
*/
|
||||
if (ifp != NULL && ifp != nh4.nh_ifp)
|
||||
if (ifp != NULL && ifp != nh->nh_aifp)
|
||||
return (0);
|
||||
|
||||
/* if no ifp provided, check if rtentry is not default route */
|
||||
if (ifp == NULL && (nh4.nh_flags & NHF_DEFAULT) != 0)
|
||||
if (ifp == NULL && (nh->nh_flags & NHF_DEFAULT) != 0)
|
||||
return (0);
|
||||
|
||||
/* or if this is a blackhole/reject route */
|
||||
if (ifp == NULL && (nh4.nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
|
||||
if (ifp == NULL && (nh->nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
|
||||
return (0);
|
||||
|
||||
/* found valid route */
|
||||
@ -805,24 +807,25 @@ ipfw_localip6(struct in6_addr *in6)
|
||||
static int
|
||||
verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib)
|
||||
{
|
||||
struct nhop6_basic nh6;
|
||||
struct nhop_object *nh;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(src))
|
||||
return (1);
|
||||
|
||||
if (fib6_lookup_nh_basic(fib, src, 0, NHR_IFAIF, 0, &nh6) != 0)
|
||||
nh = fib6_lookup(fib, src, 0, NHR_NONE, 0);
|
||||
if (nh == NULL)
|
||||
return (0);
|
||||
|
||||
/* If ifp is provided, check for equality with route table. */
|
||||
if (ifp != NULL && ifp != nh6.nh_ifp)
|
||||
if (ifp != NULL && ifp != nh->nh_aifp)
|
||||
return (0);
|
||||
|
||||
/* if no ifp provided, check if rtentry is not default route */
|
||||
if (ifp == NULL && (nh6.nh_flags & NHF_DEFAULT) != 0)
|
||||
if (ifp == NULL && (nh->nh_flags & NHF_DEFAULT) != 0)
|
||||
return (0);
|
||||
|
||||
/* or if this is a blackhole/reject route */
|
||||
if (ifp == NULL && (nh6.nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
|
||||
if (ifp == NULL && (nh->nh_flags & (NHF_REJECT|NHF_BLACKHOLE)) != 0)
|
||||
return (0);
|
||||
|
||||
/* found valid route */
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
|
||||
#include <net/radix.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
#include <net/route/route_var.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
@ -3811,11 +3812,7 @@ ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
|
||||
uint32_t *val)
|
||||
{
|
||||
#ifdef INET
|
||||
struct nhop4_basic nh4;
|
||||
struct in_addr in;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct nhop6_basic nh6;
|
||||
#endif
|
||||
int error;
|
||||
|
||||
@ -3823,14 +3820,14 @@ ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
|
||||
#ifdef INET
|
||||
if (keylen == 4) {
|
||||
in.s_addr = *(in_addr_t *)key;
|
||||
error = fib4_lookup_nh_basic(ti->data,
|
||||
in, 0, 0, &nh4);
|
||||
NET_EPOCH_ASSERT();
|
||||
error = fib4_lookup(ti->data, in, 0, NHR_NONE, 0) != NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (keylen == 6)
|
||||
error = fib6_lookup_nh_basic(ti->data,
|
||||
(struct in6_addr *)key, 0, 0, 0, &nh6);
|
||||
error = fib6_lookup(ti->data, (struct in6_addr *)key,
|
||||
0, NHR_NONE, 0) != NULL;
|
||||
#endif
|
||||
|
||||
if (error != 0)
|
||||
|
@ -50,9 +50,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/pfil.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/route.h>
|
||||
#include <net/route/nhop.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_fib.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_fw.h>
|
||||
@ -79,9 +81,9 @@ typedef int (*nat64_output_t)(struct ifnet *, struct mbuf *,
|
||||
typedef int (*nat64_output_one_t)(struct mbuf *, struct nat64_counters *,
|
||||
void *);
|
||||
|
||||
static int nat64_find_route4(struct nhop4_basic *, struct sockaddr_in *,
|
||||
static struct nhop_object *nat64_find_route4(struct sockaddr_in *,
|
||||
struct mbuf *);
|
||||
static int nat64_find_route6(struct nhop6_basic *, struct sockaddr_in6 *,
|
||||
static struct nhop_object *nat64_find_route6(struct sockaddr_in6 *,
|
||||
struct mbuf *);
|
||||
static int nat64_output_one(struct mbuf *, struct nat64_counters *, void *);
|
||||
static int nat64_output(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
@ -172,8 +174,8 @@ static int
|
||||
nat64_direct_output_one(struct mbuf *m, struct nat64_counters *stats,
|
||||
void *logdata)
|
||||
{
|
||||
struct nhop6_basic nh6;
|
||||
struct nhop4_basic nh4;
|
||||
struct nhop_object *nh4 = NULL;
|
||||
struct nhop_object *nh6 = NULL;
|
||||
struct sockaddr_in6 dst6;
|
||||
struct sockaddr_in dst4;
|
||||
struct sockaddr *dst;
|
||||
@ -183,25 +185,28 @@ nat64_direct_output_one(struct mbuf *m, struct nat64_counters *stats,
|
||||
int error;
|
||||
|
||||
ip4 = mtod(m, struct ip *);
|
||||
error = 0;
|
||||
switch (ip4->ip_v) {
|
||||
case IPVERSION:
|
||||
dst4.sin_addr = ip4->ip_dst;
|
||||
error = nat64_find_route4(&nh4, &dst4, m);
|
||||
if (error != 0)
|
||||
nh4 = nat64_find_route4(&dst4, m);
|
||||
if (nh4 == NULL) {
|
||||
NAT64STAT_INC(stats, noroute4);
|
||||
else {
|
||||
ifp = nh4.nh_ifp;
|
||||
error = EHOSTUNREACH;
|
||||
} else {
|
||||
ifp = nh4->nh_ifp;
|
||||
dst = (struct sockaddr *)&dst4;
|
||||
}
|
||||
break;
|
||||
case (IPV6_VERSION >> 4):
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
dst6.sin6_addr = ip6->ip6_dst;
|
||||
error = nat64_find_route6(&nh6, &dst6, m);
|
||||
if (error != 0)
|
||||
nh6 = nat64_find_route6(&dst6, m);
|
||||
if (nh6 == NULL) {
|
||||
NAT64STAT_INC(stats, noroute6);
|
||||
else {
|
||||
ifp = nh6.nh_ifp;
|
||||
error = EHOSTUNREACH;
|
||||
} else {
|
||||
ifp = nh6->nh_ifp;
|
||||
dst = (struct sockaddr *)&dst6;
|
||||
}
|
||||
break;
|
||||
@ -614,31 +619,31 @@ nat64_fragment6(struct nat64_counters *stats, struct ip6_hdr *ip6,
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
static NAT64NOINLINE int
|
||||
nat64_find_route6(struct nhop6_basic *pnh, struct sockaddr_in6 *dst,
|
||||
struct mbuf *m)
|
||||
static struct nhop_object *
|
||||
nat64_find_route6(struct sockaddr_in6 *dst, struct mbuf *m)
|
||||
{
|
||||
|
||||
if (fib6_lookup_nh_basic(M_GETFIB(m), &dst->sin6_addr, 0, 0, 0,
|
||||
pnh) != 0)
|
||||
return (EHOSTUNREACH);
|
||||
if (pnh->nh_flags & (NHF_BLACKHOLE | NHF_REJECT))
|
||||
return (EHOSTUNREACH);
|
||||
struct nhop_object *nh;
|
||||
NET_EPOCH_ASSERT();
|
||||
nh = fib6_lookup(M_GETFIB(m), &dst->sin6_addr, 0, 0, 0);
|
||||
if (nh == NULL)
|
||||
return NULL;
|
||||
if (nh->nh_flags & (NHF_BLACKHOLE | NHF_REJECT))
|
||||
return NULL;
|
||||
/*
|
||||
* XXX: we need to use destination address with embedded scope
|
||||
* zone id, because LLTABLE uses such form of addresses for lookup.
|
||||
*/
|
||||
dst->sin6_family = AF_INET6;
|
||||
dst->sin6_len = sizeof(*dst);
|
||||
dst->sin6_addr = pnh->nh_addr;
|
||||
dst->sin6_addr = ifatoia6(nh->nh_ifa)->ia_addr.sin6_addr;
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
|
||||
dst->sin6_addr.s6_addr16[1] =
|
||||
htons(pnh->nh_ifp->if_index & 0xffff);
|
||||
htons(nh->nh_ifp->if_index & 0xffff);
|
||||
dst->sin6_port = 0;
|
||||
dst->sin6_scope_id = 0;
|
||||
dst->sin6_flowinfo = 0;
|
||||
|
||||
return (0);
|
||||
return nh;
|
||||
}
|
||||
|
||||
#define NAT64_ICMP6_PLEN 64
|
||||
@ -766,21 +771,23 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint8_t code, uint32_t mtu,
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
static NAT64NOINLINE int
|
||||
nat64_find_route4(struct nhop4_basic *pnh, struct sockaddr_in *dst,
|
||||
struct mbuf *m)
|
||||
static struct nhop_object *
|
||||
nat64_find_route4(struct sockaddr_in *dst, struct mbuf *m)
|
||||
{
|
||||
struct nhop_object *nh;
|
||||
|
||||
if (fib4_lookup_nh_basic(M_GETFIB(m), dst->sin_addr, 0, 0, pnh) != 0)
|
||||
return (EHOSTUNREACH);
|
||||
if (pnh->nh_flags & (NHF_BLACKHOLE | NHF_BROADCAST | NHF_REJECT))
|
||||
return (EHOSTUNREACH);
|
||||
NET_EPOCH_ASSERT();
|
||||
nh = fib4_lookup(M_GETFIB(m), dst->sin_addr, 0, 0, 0);
|
||||
if (nh == NULL)
|
||||
return NULL;
|
||||
if (nh->nh_flags & (NHF_BLACKHOLE | NHF_BROADCAST | NHF_REJECT))
|
||||
return NULL;
|
||||
|
||||
dst->sin_family = AF_INET;
|
||||
dst->sin_len = sizeof(*dst);
|
||||
dst->sin_addr = pnh->nh_addr;
|
||||
dst->sin_addr = IA_SIN(nh->nh_ifa)->sin_addr;
|
||||
dst->sin_port = 0;
|
||||
return (0);
|
||||
return nh;
|
||||
}
|
||||
|
||||
#define NAT64_ICMP_PLEN 64
|
||||
@ -1223,7 +1230,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr,
|
||||
struct in6_addr *daddr, uint16_t lport, struct nat64_config *cfg,
|
||||
void *logdata)
|
||||
{
|
||||
struct nhop6_basic nh;
|
||||
struct nhop_object *nh;
|
||||
struct ip6_hdr ip6;
|
||||
struct sockaddr_in6 dst;
|
||||
struct ip *ip;
|
||||
@ -1266,16 +1273,17 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr,
|
||||
}
|
||||
|
||||
dst.sin6_addr = ip6.ip6_dst;
|
||||
if (nat64_find_route6(&nh, &dst, m) != 0) {
|
||||
nh = nat64_find_route6(&dst, m);
|
||||
if (nh == NULL) {
|
||||
NAT64STAT_INC(&cfg->stats, noroute6);
|
||||
nat64_icmp_reflect(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0,
|
||||
&cfg->stats, logdata);
|
||||
return (NAT64RETURN);
|
||||
}
|
||||
if (nh.nh_mtu < plen + sizeof(ip6) &&
|
||||
if (nh->nh_mtu < plen + sizeof(ip6) &&
|
||||
(ip->ip_off & htons(IP_DF)) != 0) {
|
||||
nat64_icmp_reflect(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
|
||||
FRAGSZ(nh.nh_mtu) + sizeof(struct ip), &cfg->stats, logdata);
|
||||
FRAGSZ(nh->nh_mtu) + sizeof(struct ip), &cfg->stats, logdata);
|
||||
return (NAT64RETURN);
|
||||
}
|
||||
|
||||
@ -1314,9 +1322,9 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr,
|
||||
|
||||
m_adj(m, hlen);
|
||||
mbufq_init(&mq, 255);
|
||||
nat64_fragment6(&cfg->stats, &ip6, &mq, m, nh.nh_mtu, ip_id, ip_off);
|
||||
nat64_fragment6(&cfg->stats, &ip6, &mq, m, nh->nh_mtu, ip_id, ip_off);
|
||||
while ((m = mbufq_dequeue(&mq)) != NULL) {
|
||||
if (V_nat64out->output(nh.nh_ifp, m, (struct sockaddr *)&dst,
|
||||
if (V_nat64out->output(nh->nh_ifp, m, (struct sockaddr *)&dst,
|
||||
&cfg->stats, logdata) != 0)
|
||||
break;
|
||||
NAT64STAT_INC(&cfg->stats, opcnt46);
|
||||
@ -1551,7 +1559,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, uint16_t aport,
|
||||
struct nat64_config *cfg, void *logdata)
|
||||
{
|
||||
struct ip ip;
|
||||
struct nhop4_basic nh;
|
||||
struct nhop_object *nh;
|
||||
struct sockaddr_in dst;
|
||||
struct ip6_frag *frag;
|
||||
struct ip6_hdr *ip6;
|
||||
@ -1644,14 +1652,15 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, uint16_t aport,
|
||||
cfg, logdata));
|
||||
}
|
||||
dst.sin_addr.s_addr = ip.ip_dst.s_addr;
|
||||
if (nat64_find_route4(&nh, &dst, m) != 0) {
|
||||
nh = nat64_find_route4(&dst, m);
|
||||
if (nh == NULL) {
|
||||
NAT64STAT_INC(&cfg->stats, noroute4);
|
||||
nat64_icmp6_reflect(m, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_NOROUTE, 0, &cfg->stats, logdata);
|
||||
return (NAT64RETURN);
|
||||
}
|
||||
if (nh.nh_mtu < plen + sizeof(ip)) {
|
||||
nat64_icmp6_reflect(m, ICMP6_PACKET_TOO_BIG, 0, nh.nh_mtu,
|
||||
if (nh->nh_mtu < plen + sizeof(ip)) {
|
||||
nat64_icmp6_reflect(m, ICMP6_PACKET_TOO_BIG, 0, nh->nh_mtu,
|
||||
&cfg->stats, logdata);
|
||||
return (NAT64RETURN);
|
||||
}
|
||||
@ -1699,7 +1708,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, uint16_t aport,
|
||||
|
||||
m_adj(m, hlen - sizeof(ip));
|
||||
bcopy(&ip, mtod(m, void *), sizeof(ip));
|
||||
if (V_nat64out->output(nh.nh_ifp, m, (struct sockaddr *)&dst,
|
||||
if (V_nat64out->output(nh->nh_ifp, m, (struct sockaddr *)&dst,
|
||||
&cfg->stats, logdata) == 0)
|
||||
NAT64STAT_INC(&cfg->stats, opcnt64);
|
||||
return (NAT64RETURN);
|
||||
|
Loading…
Reference in New Issue
Block a user