summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2005-07-06 01:51:44 +0000
committersam <sam@FreeBSD.org>2005-07-06 01:51:44 +0000
commit42be4e8353aebfc3cf73c7001101f6addf2df279 (patch)
tree8fb1a3a6f93825235c6f6e42b500f71674b41489 /sys/net80211
parent9fb6cc8fde85360ec292c60cb811ea4c9bbd701f (diff)
downloadFreeBSD-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)
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_input.c18
-rw-r--r--sys/net80211/ieee80211_node.c15
-rw-r--r--sys/net80211/ieee80211_node.h1
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 */
OpenPOWER on IntegriCloud