diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 50c3ccf433e..c0ead1624f0 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 3811f9944fe..b085855437f 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. @@ -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). diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 9c8079996b9..c7ac7c11a48 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 */