Fix ieee80211_node leak

We can't use IF_PURGE here because m_pkthdr.rcvif have here a special meaning :
it holds ieee80211_node to which the management frame should be sent and the
node has its reference count bumped.

Introduce ieee80211_drain_ifq which release the node before freeing the mbuf.
Use it instead of IF_PURGE.

From DragonflyBSD
This commit is contained in:
degroote 2008-01-13 13:01:12 +00:00
parent 1bd2744b54
commit f8d4f721c1
3 changed files with 31 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ieee80211_netbsd.c,v 1.14 2007/03/04 06:03:19 christos Exp $ */
/* $NetBSD: ieee80211_netbsd.c,v 1.15 2008/01/13 13:01:12 degroote Exp $ */
/*-
* Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
* All rights reserved.
@ -30,7 +30,7 @@
#ifdef __FreeBSD__
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_freebsd.c,v 1.8 2005/08/08 18:46:35 sam Exp $");
#else
__KERNEL_RCSID(0, "$NetBSD: ieee80211_netbsd.c,v 1.14 2007/03/04 06:03:19 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ieee80211_netbsd.c,v 1.15 2008/01/13 13:01:12 degroote Exp $");
#endif
/*
@ -501,6 +501,27 @@ ieee80211_node_dectestref(struct ieee80211_node *ni)
return rc;
}
void
ieee80211_drain_ifq(struct ifqueue *ifq)
{
struct ieee80211_node *ni;
struct mbuf *m;
for (;;) {
IF_DEQUEUE(ifq, m);
if (m == NULL)
break;
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
KASSERT(ni != NULL);
ieee80211_free_node(ni);
m->m_pkthdr.rcvif = NULL;
m_freem(m);
}
}
void
if_printf(struct ifnet *ifp, const char *fmt, ...)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: ieee80211_netbsd.h,v 1.11 2007/03/04 06:03:19 christos Exp $ */
/* $NetBSD: ieee80211_netbsd.h,v 1.12 2008/01/13 13:01:12 degroote Exp $ */
/*-
* Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
* All rights reserved.
@ -180,6 +180,9 @@ struct ieee80211_node;
int ieee80211_node_dectestref(struct ieee80211_node *ni);
#define ieee80211_node_refcnt(_ni) (_ni)->ni_refcnt
struct ifqueue;
void ieee80211_drain_ifq(struct ifqueue *);
struct mbuf *ieee80211_getmgtframe(u_int8_t **frm, u_int pktlen);
#define M_PWR_SAV M_PROTO1 /* bypass PS handling */
#define M_MORE_DATA M_LINK3 /* more data frames to follow */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ieee80211_proto.c,v 1.28 2006/11/16 01:33:41 christos Exp $ */
/* $NetBSD: ieee80211_proto.c,v 1.29 2008/01/13 13:01:12 degroote Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
@ -36,7 +36,7 @@
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.23 2005/08/10 16:22:29 sam Exp $");
#endif
#ifdef __NetBSD__
__KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.28 2006/11/16 01:33:41 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.29 2008/01/13 13:01:12 degroote Exp $");
#endif
/*
@ -147,7 +147,7 @@ ieee80211_proto_detach(struct ieee80211com *ic)
if (ic->ic_auth->ia_detach)
ic->ic_auth->ia_detach(ic);
IF_PURGE(&ic->ic_mgtq);
ieee80211_drain_ifq(&ic->ic_mgtq);
/*
* Detach any ACL'ator.
@ -967,7 +967,7 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
case IEEE80211_S_AUTH:
reset:
ic->ic_mgt_timer = 0;
IF_PURGE(&ic->ic_mgtq);
ieee80211_drain_ifq(&ic->ic_mgtq);
ieee80211_reset_bss(ic);
break;
}