aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2016-01-04 15:03:20 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2016-01-04 15:03:20 +0000
commit9a1b64d5a0224188da8a84a7803ab12cb07c694a (patch)
tree97043b0fe5b60ef63af4661bdd61f9c954d3bf5b /sys/netinet/in.c
parentdb61e6ef45353e2cd30bcdacad3cfaf635cba591 (diff)
downloadsrc-9a1b64d5a0224188da8a84a7803ab12cb07c694a.tar.gz
src-9a1b64d5a0224188da8a84a7803ab12cb07c694a.zip
Add rib_lookup_info() to provide API for retrieving individual route
entries data in unified format. There are control plane functions that require information other than just next-hop data (e.g. individual rtentry fields like flags or prefix/mask). Given that the goal is to avoid rte reference/refcounting, re-use rt_addrinfo structure to store most rte fields. If caller wants to retrieve key/mask or gateway (which are sockaddrs and are allocated separately), it needs to provide sufficient-sized sockaddrs structures w/ ther pointers saved in passed rt_addrinfo. Convert: * lltable new records checks (in_lltable_rtcheck(), nd6_is_new_addr_neighbor(). * rtsock pre-add/change route check. * IPv6 NS ND-proxy check (RADIX_MPATH code was eliminated because 1) we don't support RTF_ANNOUNCE ND-proxy for networks and there should not be multiple host routes for such hosts 2) if we have multiple routes we should inspect them (which is not done). 3) the entire idea of abusing KRT as storage for ND proxy seems odd. Userland programs should be used for that purpose).
Notes
Notes: svn path=/head/; revision=293159
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index c30c1f3fdf88..80b14483654a 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1106,34 +1106,48 @@ in_lltable_free_entry(struct lltable *llt, struct llentry *lle)
static int
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
{
- struct rtentry *rt;
+ struct rt_addrinfo info;
+ struct sockaddr_in rt_key, rt_mask;
+ struct sockaddr rt_gateway;
+ int rt_flags;
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);
+ bzero(&rt_key, sizeof(rt_key));
+ rt_key.sin_len = sizeof(rt_key);
+ bzero(&rt_mask, sizeof(rt_mask));
+ rt_mask.sin_len = sizeof(rt_mask);
+ bzero(&rt_gateway, sizeof(rt_gateway));
+ rt_gateway.sa_len = sizeof(rt_gateway);
- if (rt == NULL)
+ bzero(&info, sizeof(info));
+ info.rti_info[RTAX_DST] = (struct sockaddr *)&rt_key;
+ info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&rt_mask;
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
+
+ if (rib_lookup_info(ifp->if_fib, l3addr, NHR_REF, 0, &info) != 0)
return (EINVAL);
+ rt_flags = info.rti_flags;
+
/*
* If the gateway for an existing host route matches the target L3
* 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.
*/
- 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,
+ if (rt_flags & RTF_GATEWAY) {
+ if (!(rt_flags & RTF_HOST) || !info.rti_ifp ||
+ info.rti_ifp->if_type != IFT_ETHER ||
+ (info.rti_ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0 ||
+ memcmp(rt_gateway.sa_data, l3addr->sa_data,
sizeof(in_addr_t)) != 0) {
- RTFREE_LOCKED(rt);
+ rib_free_info(&info);
return (EINVAL);
}
}
+ rib_free_info(&info);
/*
* Make sure that at least the destination address is covered
@@ -1142,21 +1156,19 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
* on one interface and the corresponding outgoing packet leaves
* another interface.
*/
- if (!(rt->rt_flags & RTF_HOST) && rt->rt_ifp != ifp) {
+ if (!(rt_flags & RTF_HOST) && info.rti_ifp != ifp) {
const char *sa, *mask, *addr, *lim;
int len;
- mask = (const char *)rt_mask(rt);
+ mask = (const char *)&rt_mask;
/*
* Just being extra cautious to avoid some custom
* code getting into trouble.
*/
- if (mask == NULL) {
- RTFREE_LOCKED(rt);
+ if ((info.rti_addrs & RTA_NETMASK) == 0)
return (EINVAL);
- }
- sa = (const char *)rt_key(rt);
+ sa = (const char *)&rt_key;
addr = (const char *)l3addr;
len = ((const struct sockaddr_in *)l3addr)->sin_len;
lim = addr + len;
@@ -1167,13 +1179,11 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
#endif
- RTFREE_LOCKED(rt);
return (EINVAL);
}
}
}
- RTFREE_LOCKED(rt);
return (0);
}