Fix race condition in handling node reference counts for authenticating
stations in ap mode. Track when a node's first auth frame is received and use this to decide whether or not to bump the refcnt. This insures we only ever bump the refcnt once. Reviewed by: avatar Approved by: re (scottl)
This commit is contained in:
parent
9fb6cc8fde
commit
42be4e8353
@ -866,8 +866,15 @@ ieee80211_auth_open(struct ieee80211com *ic, struct ieee80211_frame *wh,
|
||||
ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
return;
|
||||
} else
|
||||
} else if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
|
||||
(void) ieee80211_ref_node(ni);
|
||||
/*
|
||||
* Mark the node as referenced to reflect that it's
|
||||
* reference count has been bumped to insure it remains
|
||||
* after the transaction completes.
|
||||
*/
|
||||
ni->ni_flags |= IEEE80211_NODE_AREF;
|
||||
|
||||
IEEE80211_SEND_MGMT(ic, ni,
|
||||
IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
|
||||
IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
|
||||
@ -1048,9 +1055,16 @@ ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh,
|
||||
}
|
||||
allocbs = 1;
|
||||
} else {
|
||||
(void) ieee80211_ref_node(ni);
|
||||
if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
|
||||
(void) ieee80211_ref_node(ni);
|
||||
allocbs = 0;
|
||||
}
|
||||
/*
|
||||
* Mark the node as referenced to reflect that it's
|
||||
* reference count has been bumped to insure it remains
|
||||
* after the transaction completes.
|
||||
*/
|
||||
ni->ni_flags |= IEEE80211_NODE_AREF;
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
if (!alloc_challenge(ic, ni)) {
|
||||
|
@ -850,6 +850,13 @@ node_cleanup(struct ieee80211_node *ni)
|
||||
"[%s] power save mode off, %u sta's in ps mode\n",
|
||||
ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
|
||||
}
|
||||
/*
|
||||
* Clear AREF flag that marks the authorization refcnt bump
|
||||
* has happened. This is probably not needed as the node
|
||||
* should always be removed from the table so not found but
|
||||
* do it just in case.
|
||||
*/
|
||||
ni->ni_flags &= ~IEEE80211_NODE_AREF;
|
||||
|
||||
/*
|
||||
* Drain power save queue and, if needed, clear TIM.
|
||||
@ -1396,6 +1403,14 @@ restart:
|
||||
if (ni->ni_scangen == gen) /* previously handled */
|
||||
continue;
|
||||
ni->ni_scangen = gen;
|
||||
/*
|
||||
* Ignore entries for which have yet to receive an
|
||||
* authentication frame. These are transient and
|
||||
* will be reclaimed when the last reference to them
|
||||
* goes away (when frame xmits complete).
|
||||
*/
|
||||
if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
|
||||
continue;
|
||||
/*
|
||||
* Free fragment if not needed anymore
|
||||
* (last fragment older than 1s).
|
||||
|
@ -100,6 +100,7 @@ struct ieee80211_node {
|
||||
#define IEEE80211_NODE_ERP 0x0004 /* ERP enabled */
|
||||
/* NB: this must have the same value as IEEE80211_FC1_PWR_MGT */
|
||||
#define IEEE80211_NODE_PWR_MGT 0x0010 /* power save mode enabled */
|
||||
#define IEEE80211_NODE_AREF 0x0020 /* authentication ref held */
|
||||
u_int16_t ni_associd; /* assoc response */
|
||||
u_int16_t ni_txpower; /* current transmit power */
|
||||
u_int16_t ni_vlan; /* vlan tag */
|
||||
|
Loading…
x
Reference in New Issue
Block a user