summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/net80211/ieee80211_input.c2
-rw-r--r--sys/net80211/ieee80211_node.c8
-rw-r--r--sys/net80211/ieee80211_output.c7
3 files changed, 15 insertions, 2 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 38e3db2..e0c4879 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -2711,7 +2711,7 @@ ieee80211_recv_pspoll(struct ieee80211com *ic,
IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
"[%s] recv ps-poll, but queue empty\n",
ether_sprintf(wh->i_addr2));
- ieee80211_send_nulldata(ni);
+ ieee80211_send_nulldata(ieee80211_ref_node(ni));
ic->ic_stats.is_ps_qempty++; /* XXX node stat */
if (ic->ic_set_tim != NULL)
ic->ic_set_tim(ni, 0); /* just in case */
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 81f6138..72884f0 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -1474,6 +1474,14 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, "[%s] discard frame, age %u\n", ether
IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,
ni, "%s",
"probe station due to inactivity");
+ /*
+ * Grab a reference before unlocking the table
+ * so the node cannot be reclaimed before we
+ * send the frame. ieee80211_send_nulldata
+ * understands we've done this and reclaims the
+ * ref for us as needed.
+ */
+ ieee80211_ref_node(ni);
IEEE80211_NODE_UNLOCK(nt);
ieee80211_send_nulldata(ni);
/* XXX stat? */
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index eb558a5..78b62d0 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -199,6 +199,10 @@ ieee80211_mgmt_output(struct ieee80211com *ic, struct ieee80211_node *ni,
/*
* Send a null data frame to the specified node.
+ *
+ * NB: the caller is assumed to have setup a node reference
+ * for use; this is necessary to deal with a race condition
+ * when probing for inactive stations.
*/
int
ieee80211_send_nulldata(struct ieee80211_node *ni)
@@ -212,9 +216,10 @@ ieee80211_send_nulldata(struct ieee80211_node *ni)
if (m == NULL) {
/* XXX debug msg */
ic->ic_stats.is_tx_nobuf++;
+ ieee80211_unref_node(&ni);
return ENOMEM;
}
- m->m_pkthdr.rcvif = (void *) ieee80211_ref_node(ni);
+ m->m_pkthdr.rcvif = (void *) ni;
wh = mtod(m, struct ieee80211_frame *);
ieee80211_send_setup(ic, ni, wh,
OpenPOWER on IntegriCloud