]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Fix deletion of ifaddr lle entries when deleting prefix from interface in
authormelifaro <melifaro@FreeBSD.org>
Sun, 18 Oct 2015 12:26:25 +0000 (12:26 +0000)
committermelifaro <melifaro@FreeBSD.org>
Sun, 18 Oct 2015 12:26:25 +0000 (12:26 +0000)
  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

sys/netinet/in.c

index 1441936c38085555d68737186a91a3da43ed5ad1..2607a1750ffdf54d96216ab0a2006d71e8abda6c 100644 (file)
@@ -734,14 +734,10 @@ in_scrubprefixlle(struct in_ifaddr *ia, int all, u_int flags)
        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, int all, u_int flags)
        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, u_int flags)
                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);
        }