Convert lle rtchecks to use new routing API.

For inet/ case, this involves reverting r225947
which seem to be pretty strange commit and should
be reverted in HEAD ad well.
This commit is contained in:
Alexander V. Chernikov 2014-11-06 23:35:22 +00:00
parent 69b74805d5
commit 064b1bdb2d
4 changed files with 87 additions and 59 deletions

View File

@ -498,6 +498,42 @@ fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
return (ENOENT);
}
int
fib4_lookup_nh_ifp(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
struct nhop4_basic *pnh4)
{
struct radix_node_head *rnh;
struct radix_node *rn;
struct sockaddr_in sin;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ifp: bad fibnum"));
rnh = rt_tables_get_rnh(fibnum, AF_INET);
if (rnh == NULL)
return (ENOENT);
/* Prepare lookup key */
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr = dst;
RADIX_NODE_HEAD_RLOCK(rnh);
rn = rnh->rnh_matchaddr((void *)&sin, rnh);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
/* Ensure route & ifp is UP */
if (RT_LINK_IS_UP(rte->rt_ifp)) {
fib4_rte_to_nh_basic(rte, dst, pnh4);
RADIX_NODE_HEAD_RUNLOCK(rnh);
pnh4->nh_ifp = rte->rt_ifp;
return (0);
}
}
RADIX_NODE_HEAD_RUNLOCK(rnh);
return (ENOENT);
}
/*
* Performs IPv4 route table lookup on @dst. Returns 0 on success.
* Stores extende nexthop info provided @pnh4 structure.

View File

@ -169,6 +169,7 @@ struct nhop4_extended {
uint64_t spare2[2];
};
/* Does not differ from nhop6_basic */
struct nhop6_extended {
struct ifnet *nh_ifp; /* Logical egress interface */
uint16_t nh_mtu; /* nexthop mtu */
@ -178,6 +179,27 @@ struct nhop6_extended {
uint64_t spare2[2];
};
/* route info used for control plane purposes */
struct rt4_basic {
struct in_addr rt_addr; /* route prefix */
struct in_addr rt_gateway; /* GW used */
int rt_flags; /* Copy of rte flags */
uint16_t rt_mtu;
uint16_t rt_nhop; /* nexthop id (might bi mpath) */
struct in_addr rt_mask; /* route mask */
uint16_t spare[2];
};
struct rt6_basic {
struct in6_addr rt_addr;
struct in6_addr rt_gateway;
int rt_flags;
uint16_t rt_mtu;
uint16_t rt_nhop;
uint8_t rt_mask;
uint8_t spare[7];
};
struct nhopu_extended {
union {
struct nhop4_extended nh4;
@ -200,6 +222,8 @@ struct route_compat {
int ro_flags;
};
int fib4_lookup_nh_ifp(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
struct nhop4_basic *pnh4);
int fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
struct nhop4_basic *pnh4);
int fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst,

View File

@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/route_internal.h>
#include <net/vnet.h>
#include <netinet/if_ether.h>
@ -69,6 +68,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <net/rt_nhops.h>
static int in_aifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *);
static int in_difaddr_ioctl(caddr_t, struct ifnet *, struct thread *);
@ -1007,16 +1008,14 @@ in_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
static int
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
{
struct rtentry *rt;
struct nhop4_basic nh4;
struct in_addr dst;
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
/* XXX rtalloc1_fib should take a const param */
rt = rtalloc1_fib(__DECONST(struct sockaddr *, l3addr), 0, 0,
ifp->if_fib);
if (rt == NULL)
dst = ((struct sockaddr_in *)l3addr)->sin_addr;
if (fib4_lookup_nh_ifp(ifp->if_fib, dst, 0, &nh4) != 0)
return (EINVAL);
/*
@ -1024,57 +1023,26 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
* address, which is a special route inserted by some implementation
* such as MANET, and the interface is of the correct type, then
* allow for ARP to proceed.
* XXX: !RTF_HOST condition (temporarily) skipped.
*/
if (rt->rt_flags & RTF_GATEWAY) {
if (!(rt->rt_flags & RTF_HOST) || !rt->rt_ifp ||
rt->rt_ifp->if_type != IFT_ETHER ||
(rt->rt_ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0 ||
memcmp(rt->rt_gateway->sa_data, l3addr->sa_data,
sizeof(in_addr_t)) != 0) {
RTFREE_LOCKED(rt);
if (nh4.nh_flags & NHF_GATEWAY) {
if (nh4.nh_ifp->if_type != IFT_ETHER ||
(nh4.nh_ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0 ||
nh4.nh_addr.s_addr != dst.s_addr) {
return (EINVAL);
}
return (0);
}
/*
* Make sure that at least the destination address is covered
* by the route. This is for handling the case where 2 or more
* interfaces have the same prefix. An incoming packet arrives
* on one interface and the corresponding outgoing packet leaves
* another interface.
*/
if (!(rt->rt_flags & RTF_HOST) && rt->rt_ifp != ifp) {
const char *sa, *mask, *addr, *lim;
int len;
mask = (const char *)rt_mask(rt);
/*
* Just being extra cautious to avoid some custom
* code getting into trouble.
*/
if (mask == NULL) {
RTFREE_LOCKED(rt);
return (EINVAL);
}
sa = (const char *)rt_key(rt);
addr = (const char *)l3addr;
len = ((const struct sockaddr_in *)l3addr)->sin_len;
lim = addr + len;
for ( ; addr < lim; sa++, mask++, addr++) {
if ((*sa ^ *addr) & *mask) {
if (((nh4.nh_flags & NHF_GATEWAY) != 0) || nh4.nh_ifp != ifp) {
#ifdef DIAGNOSTIC
log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
inet_ntoa(dst));
#endif
RTFREE_LOCKED(rt);
return (EINVAL);
}
}
return (EINVAL);
}
RTFREE_LOCKED(rt);
return (0);
}

View File

@ -108,6 +108,8 @@ __FBSDID("$FreeBSD$");
#include <netinet6/scope6_var.h>
#include <netinet6/in6_pcb.h>
#include <net/rt_nhops.h>
VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix);
#define V_icmp6_nodeinfo_oldmcprefix VNET(icmp6_nodeinfo_oldmcprefix)
@ -2166,17 +2168,20 @@ in6_lltable_rtcheck(struct ifnet *ifp,
u_int flags,
const struct sockaddr *l3addr)
{
struct rtentry *rt;
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) {
in6_splitscope(&((struct sockaddr_in6 *)l3addr)->sin6_addr, &dst, &scopeid);
error = fib6_lookup_nh_ifp(RT_DEFAULT_FIB, &dst, scopeid, 0, &nh6);
if (error != 0 || ((nh6.nh_flags & NHF_GATEWAY) != 0) || nh6.nh_ifp != ifp) {
struct ifaddr *ifa;
/*
* Create an ND6 cache for an IPv6 neighbor
@ -2186,17 +2191,12 @@ in6_lltable_rtcheck(struct ifnet *ifp,
ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, 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);
return EINVAL;
}
RTFREE_LOCKED(rt);
return 0;
}