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:
sam 2005-07-06 01:51:44 +00:00
parent 9fb6cc8fde
commit 42be4e8353
3 changed files with 32 additions and 2 deletions

View File

@ -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)) {

View File

@ -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).

View File

@ -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 */