Fix potential node refcnt leak. If mbufs are q'd on ic_mgtq when
the state machine clocks to INIT, node references are not reclaimed. Add a new routine ieee80211_drain_ifq that does this and use it instead of IF_DRAIN. Submitted by: Sepherosa Ziehau Obtained from: DragonFly MFC after: 1 month
This commit is contained in:
parent
70bff0d9b1
commit
915f1482a9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=165894
@ -150,6 +150,26 @@ ieee80211_node_dectestref(struct ieee80211_node *ni)
|
||||
return atomic_cmpset_int(&ni->ni_refcnt, 0, 1);
|
||||
}
|
||||
|
||||
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, ("frame w/o node"));
|
||||
ieee80211_free_node(ni);
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
m_freem(m);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and setup a management frame of the specified
|
||||
* size. We return the mbuf and a pointer to the start
|
||||
|
@ -148,6 +148,8 @@ struct ieee80211_node;
|
||||
int ieee80211_node_dectestref(struct ieee80211_node *ni);
|
||||
#define ieee80211_node_refcnt(_ni) (_ni)->ni_refcnt
|
||||
|
||||
void ieee80211_drain_ifq(struct ifqueue *);
|
||||
|
||||
struct mbuf *ieee80211_getmgtframe(u_int8_t **frm, u_int pktlen);
|
||||
#define M_LINK0 M_PROTO1 /* WEP requested */
|
||||
#define M_PWR_SAV M_PROTO4 /* bypass PS handling */
|
||||
|
@ -129,7 +129,7 @@ ieee80211_proto_detach(struct ieee80211com *ic)
|
||||
if (ic->ic_auth->ia_detach)
|
||||
ic->ic_auth->ia_detach(ic);
|
||||
|
||||
IF_DRAIN(&ic->ic_mgtq);
|
||||
ieee80211_drain_ifq(&ic->ic_mgtq);
|
||||
mtx_destroy(&ic->ic_mgtq.ifq_mtx);
|
||||
|
||||
/*
|
||||
@ -932,7 +932,7 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
|
||||
default:
|
||||
break;
|
||||
}
|
||||
goto reset;
|
||||
break;
|
||||
case IEEE80211_S_ASSOC:
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
@ -947,16 +947,18 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
|
||||
default:
|
||||
break;
|
||||
}
|
||||
goto reset;
|
||||
break;
|
||||
case IEEE80211_S_SCAN:
|
||||
ieee80211_cancel_scan(ic);
|
||||
goto reset;
|
||||
case IEEE80211_S_AUTH:
|
||||
reset:
|
||||
ic->ic_mgt_timer = 0;
|
||||
IF_DRAIN(&ic->ic_mgtq);
|
||||
ieee80211_reset_bss(ic);
|
||||
break;
|
||||
case IEEE80211_S_AUTH:
|
||||
break;
|
||||
}
|
||||
if (ostate != IEEE80211_S_INIT) {
|
||||
/* NB: optimize INIT -> INIT case */
|
||||
ic->ic_mgt_timer = 0;
|
||||
ieee80211_drain_ifq(&ic->ic_mgtq);
|
||||
ieee80211_reset_bss(ic);
|
||||
}
|
||||
if (ic->ic_auth->ia_detach != NULL)
|
||||
ic->ic_auth->ia_detach(ic);
|
||||
|
Loading…
Reference in New Issue
Block a user