Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Oct 2015 12:26:25 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r289501 - head/sys/netinet
Message-ID:  <201510181226.t9ICQPC6055010@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Sun Oct 18 12:26:25 2015
New Revision: 289501
URL: https://svnweb.freebsd.org/changeset/base/289501

Log:
  Fix deletion of ifaddr lle entries when deleting prefix from interface in
    down state.
  
  Regression appeared in r287789, where the "prefix has no corresponding
    installed route" case was forgotten. Additionally, lltable_delete_addr()
    was called with incorrect byte order (default is network for lltable code).
  While here, improve comments on given cases and byte order.
  
  PR:		203573
  Submitted by:	phk

Modified:
  head/sys/netinet/in.c

Modified: head/sys/netinet/in.c
==============================================================================
--- head/sys/netinet/in.c	Sun Oct 18 11:44:31 2015	(r289500)
+++ head/sys/netinet/in.c	Sun Oct 18 12:26:25 2015	(r289501)
@@ -734,14 +734,10 @@ in_scrubprefixlle(struct in_ifaddr *ia, 
 	struct sockaddr *saddr, *smask;
 	struct ifnet *ifp;
 
-	/*
-	 * remove all L2 entries on the given prefix
-	 */
 	saddr = (struct sockaddr *)&addr;
 	bzero(&addr, sizeof(addr));
 	addr.sin_len = sizeof(addr);
 	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = ntohl(ia->ia_addr.sin_addr.s_addr);
 	smask = (struct sockaddr *)&mask;
 	bzero(&mask, sizeof(mask));
 	mask.sin_len = sizeof(mask);
@@ -749,10 +745,21 @@ in_scrubprefixlle(struct in_ifaddr *ia, 
 	mask.sin_addr.s_addr = ia->ia_subnetmask;
 	ifp = ia->ia_ifp;
 
-	if (all)
+	if (all) {
+
+		/*
+		 * Remove all L2 entries matching given prefix.
+		 * Convert address to host representation to avoid
+		 * doing this on every callback. ia_subnetmask is already
+		 * stored in host representation.
+		 */
+		addr.sin_addr.s_addr = ntohl(ia->ia_addr.sin_addr.s_addr);
 		lltable_prefix_free(AF_INET, saddr, smask, flags);
-	else
+	} else {
+		/* Remove interface address only */
+		addr.sin_addr.s_addr = ia->ia_addr.sin_addr.s_addr;
 		lltable_delete_addr(LLTABLE(ifp), LLE_IFADDR, saddr);
+	}
 }
 
 /*
@@ -808,6 +815,14 @@ in_scrubprefix(struct in_ifaddr *target,
 		fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
 			target->ia_ifp->if_fib;
 		rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum);
+	
+		/*
+		 * Removing address from !IFF_UP interface or
+		 * prefix which exists on other interface (along with route).
+		 * No entries should exist here except target addr.
+		 * Given that, delete this entry only.
+		 */
+		in_scrubprefixlle(target, 0, flags);
 		return (0);
 	}
 



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