Hi,

a bit of cleanup, which does NOT fix the second leak seen as in:

# ifconfig vether0 create 10.0.0.1/24
# ifconfig vether0 destroy

but not seen in

# ifconfig vether0 create 10.0.0.1/24
# ifconfig vether0 -alias
# ifconfig vether0 destroy

And it probably needs more testing, so sorry about the timing.
--
Martin Pelikan


Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.239
diff -u -p -r1.239 if.c
--- net/if.c    9 Jul 2011 00:47:18 -0000       1.239
+++ net/if.c    22 Jul 2011 11:54:30 -0000
@@ -559,6 +559,7 @@ if_detach(struct ifnet *ifp)
 #ifdef MROUTING
        vif_delete(ifp);
 #endif
+       in_ifdetach(ifp);
 #endif
 #ifdef INET6
        in6_ifdetach(ifp);
@@ -600,21 +601,17 @@ do { \
        if (ISSET(ifp->if_xflags, IFXF_TXREADY))
                TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
 
-       /*
-        * Deallocate private resources.
-        */
+       /* Bye bye lladdr */
+       ifa = ifnet_addrs[ifp->if_index];
+       ifa_del(ifp, ifa);
+       if_free_sadl(ifp);
+       ifa->ifa_ifp = NULL; /* in case refcnt > 1, ifp will be gone */
+       IFAFREE(ifa);
+       ifnet_addrs[ifp->if_index] = NULL;
+
+       /* Deallocate if anything is left. */
        while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
                ifa_del(ifp, ifa);
-#ifdef INET
-               if (ifa->ifa_addr->sa_family == AF_INET)
-                       TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
-                           ia_list);
-#endif
-               /* XXX if_free_sadl needs this */
-               if (ifa == ifnet_addrs[ifp->if_index])
-                       continue;
-
-               ifa->ifa_ifp = NULL;
                IFAFREE(ifa);
        }
 
@@ -622,12 +619,6 @@ do { \
            ifg = TAILQ_FIRST(&ifp->if_groups))
                if_delgroup(ifp, ifg->ifgl_group->ifg_group);
 
-       if_free_sadl(ifp);
-
-       ifnet_addrs[ifp->if_index]->ifa_ifp = NULL;
-       IFAFREE(ifnet_addrs[ifp->if_index]);
-       ifnet_addrs[ifp->if_index] = NULL;
-
        free(ifp->if_addrhooks, M_TEMP);
        free(ifp->if_linkstatehooks, M_TEMP);
        free(ifp->if_detachhooks, M_TEMP);
@@ -1211,7 +1202,7 @@ ifioctl(struct socket *so, u_long cmd, c
 {
        struct ifnet *ifp;
        struct ifreq *ifr;
-       struct ifaddr *ifa, *nifa;
+       struct ifaddr *ifa;
        struct sockaddr_dl *sdl;
        struct ifgroupreq *ifgr;
        char ifdescrbuf[IFDESCRSIZE];
@@ -1504,26 +1495,11 @@ ifioctl(struct socket *so, u_long cmd, c
 #ifdef MROUTING
                        vif_delete(ifp);
 #endif
+                       in_ifdetach(ifp);
 #endif
 #ifdef INET6
                        in6_ifdetach(ifp);
                        ifp->if_xflags |= IFXF_NOINET6;
-#endif
-#ifdef INET
-                       for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
-                           ifa = nifa) {
-                               nifa = TAILQ_NEXT(ifa, ifa_list);
-
-                               /* only remove AF_INET */
-                               if (ifa->ifa_addr->sa_family != AF_INET)
-                                       continue;
-
-                               TAILQ_REMOVE(&in_ifaddr,
-                                   (struct in_ifaddr *)ifa, ia_list);
-                               ifa_del(ifp, ifa);
-                               ifa->ifa_ifp = NULL;
-                               IFAFREE(ifa);
-                       }
 #endif
                        splx(s);
                }
Index: netinet/in.c
===================================================================
RCS file: /cvs/src/sys/netinet/in.c,v
retrieving revision 1.68
diff -u -p -r1.68 in.c
--- netinet/in.c        6 Jul 2011 01:57:37 -0000       1.68
+++ netinet/in.c        22 Jul 2011 11:54:30 -0000
@@ -95,6 +95,24 @@ int in_lifaddr_ioctl(struct socket *, u_
 int in_addprefix(struct in_ifaddr *, int);
 int in_scrubprefix(struct in_ifaddr *);
 
+void
+in_ifdetach(struct ifnet *ifp)
+{      
+       struct ifaddr *ifa, *next;
+
+       for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; ifa = next) {
+               next = TAILQ_NEXT(ifa, ifa_list);
+
+               if (ifa->ifa_addr->sa_family != AF_INET)
+                       continue;
+               TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa, ia_list);
+
+               ifa_del(ifp, ifa);
+               ifa->ifa_ifp = NULL; /* in case refcnt > 1, ifp will be gone */
+               IFAFREE(ifa);
+       }
+}
+
 /* Return 1 if an internet address is for a directly connected host */
 int
 in_localaddr(struct in_addr in, u_int rdomain)
Index: netinet/in.h
===================================================================
RCS file: /cvs/src/sys/netinet/in.h,v
retrieving revision 1.90
diff -u -p -r1.90 in.h
--- netinet/in.h        6 Jul 2011 01:57:37 -0000       1.90
+++ netinet/in.h        22 Jul 2011 11:54:31 -0000
@@ -801,6 +801,7 @@ in_cksum_addword(u_int16_t a, u_int16_t 
 
 extern    struct in_addr zeroin_addr;
 
+void      in_ifdetach(struct ifnet *);
 int       in_broadcast(struct in_addr, struct ifnet *, u_int);
 int       in_canforward(struct in_addr);
 int       in_cksum(struct mbuf *, int);

Reply via email to