summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2011-10-03 19:51:18 +0000
committerqingli <qingli@FreeBSD.org>2011-10-03 19:51:18 +0000
commitad1a755394fe964557e221bb8167258557383a9d (patch)
tree5a332798fc6b0493c125d1cbd0b675f330d5cffc /sys/netinet/in.c
parentf48490efae16713c890edce5fb2544d9847beaf3 (diff)
downloadFreeBSD-src-ad1a755394fe964557e221bb8167258557383a9d.zip
FreeBSD-src-ad1a755394fe964557e221bb8167258557383a9d.tar.gz
A system may have multiple physical interfaces, all of which are on the
same prefix. Since a single route entry is installed for the prefix (without RADIX_MPATH), incoming packets on the interfaces that are not associated with the prefix route may trigger an error message about unable to allocation LLE entry, and fails L2. This patch makes sure a valid route is present in the system, and allow the aforementioned condition to exist and treats as valid. Reviewed by: bz MFC after: 5 days
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index c2e43cc..da4e8a0 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1439,14 +1439,43 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
if (memcmp(rt->rt_gateway->sa_data, l3addr->sa_data,
sizeof(in_addr_t)) != 0)
error = EINVAL;
- } else if (!(flags & LLE_PUB) && ((rt->rt_flags & RTF_GATEWAY) ||
- (rt->rt_ifp != ifp))) {
+ }
+
+ if (rt->rt_flags & RTF_GATEWAY) {
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
+
+ /*
+ * 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_ifp != ifp) {
+ char *sa, *mask, *addr, *lim;
+ int len;
+
+ sa = (char *)rt_key(rt);
+ mask = (char *)rt_mask(rt);
+ addr = (char *)__DECONST(struct sockaddr *, l3addr);
+ len = ((struct sockaddr_in *)__DECONST(struct sockaddr *, l3addr))->sin_len;
+ lim = addr + len;
+
+ for ( ; addr < lim; sa++, mask++, addr++) {
+ if ((*sa ^ *addr) & *mask) {
+ error = EINVAL;
#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(((const struct sockaddr_in *)l3addr)->sin_addr));
#endif
- error = EINVAL;
+ break;
+ }
+ }
}
+
RTFREE_LOCKED(rt);
return (error);
}
OpenPOWER on IntegriCloud