Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Oct 2011 19:41:00 +0000 (UTC)
From:      Qing Li <qingli@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r226230 - stable/8/sys/netinet
Message-ID:  <201110101941.p9AJf0Zv078749@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: qingli
Date: Mon Oct 10 19:41:00 2011
New Revision: 226230
URL: http://svn.freebsd.org/changeset/base/226230

Log:
  MFC 225946
  
  This patch allows ARP to work properly in the presence of
  self-referencing routes. This patch is a rework of r223862.
  
  Reviewed by:	bz, zec

Modified:
  stable/8/sys/netinet/in.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/netinet/in.c
==============================================================================
--- stable/8/sys/netinet/in.c	Mon Oct 10 19:07:55 2011	(r226229)
+++ stable/8/sys/netinet/in.c	Mon Oct 10 19:41:00 2011	(r226230)
@@ -1393,6 +1393,8 @@ static int
 in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
 {
 	struct rtentry *rt;
+	struct ifnet *xifp;
+	int error = 0;
 
 	KASSERT(l3addr->sa_family == AF_INET,
 	    ("sin_family %d", l3addr->sa_family));
@@ -1400,30 +1402,35 @@ in_lltable_rtcheck(struct ifnet *ifp, u_
 	/* XXX rtalloc1 should take a const param */
 	rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
 
+	if (rt == NULL)
+		return (EINVAL);
+
 	/*
 	 * If the gateway for an existing host route matches the target L3
-	 * address, allow for ARP to proceed.
+	 * 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 != NULL && (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) &&
-	    rt->rt_gateway->sa_family == AF_INET &&
-	    memcmp(rt->rt_gateway->sa_data, l3addr->sa_data, 4) == 0) {
-		RTFREE_LOCKED(rt);
-		return (0);
-	}
-
-	if (rt == NULL || (!(flags & LLE_PUB) &&
-			   ((rt->rt_flags & RTF_GATEWAY) || 
-			    (rt->rt_ifp != ifp)))) {
+	if (rt->rt_flags & (RTF_GATEWAY | RTF_HOST)) {
+		xifp = rt->rt_ifp;
+		
+		if (xifp && (xifp->if_type != IFT_ETHER ||
+		     (xifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0))
+			error = EINVAL;
+
+		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))) {
 #ifdef DIAGNOSTIC
 		log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
 		    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
 #endif
-		if (rt != NULL)
-			RTFREE_LOCKED(rt);
-		return (EINVAL);
+		error = EINVAL;
 	}
 	RTFREE_LOCKED(rt);
-	return 0;
+	return (error);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201110101941.p9AJf0Zv078749>