diff options
author | sam <sam@FreeBSD.org> | 2005-07-06 01:51:44 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2005-07-06 01:51:44 +0000 |
commit | 42be4e8353aebfc3cf73c7001101f6addf2df279 (patch) | |
tree | 8fb1a3a6f93825235c6f6e42b500f71674b41489 | |
parent | 9fb6cc8fde85360ec292c60cb811ea4c9bbd701f (diff) | |
download | FreeBSD-src-42be4e8353aebfc3cf73c7001101f6addf2df279.zip FreeBSD-src-42be4e8353aebfc3cf73c7001101f6addf2df279.tar.gz |
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)
-rw-r--r-- | sys/net80211/ieee80211_input.c | 18 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.c | 15 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 1 |
3 files changed, 32 insertions, 2 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 50c3ccf..c0ead16 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -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)) { diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 3811f99..b085855 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -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. @@ -1397,6 +1404,14 @@ restart: 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). * XXX doesn't belong here diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 9c80799..c7ac7c1 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -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 */ |