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);