diff options
author | sam <sam@FreeBSD.org> | 2005-08-06 04:56:49 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2005-08-06 04:56:49 +0000 |
commit | 820d1d2e7cf485305dc12b55b60e9cf4588ddcd8 (patch) | |
tree | 3b57c38c8b30eb0f5f43845321a51d8b2b5ae9f8 /sys/net80211 | |
parent | 82b622da6cd66aa1b7defd0cd1597bfca51d6aa3 (diff) | |
download | FreeBSD-src-820d1d2e7cf485305dc12b55b60e9cf4588ddcd8.zip FreeBSD-src-820d1d2e7cf485305dc12b55b60e9cf4588ddcd8.tar.gz |
Fix handling of frames sent prior to a station being authorized
when operating in ap mode. Previously we allocated a node from the
station table, sent the frame (using the node), then released the
reference that "held the frame in the table". But while the frame
was in flight the node might be reclaimed which could lead to
problems. The solution is to add an ieee80211_tmp_node routine
that crafts a node that does exist in a table and so isn't ever
reclaimed; it exists only so long as the associated frame is in flight.
MFC after: 5 days
Diffstat (limited to 'sys/net80211')
-rw-r--r-- | sys/net80211/ieee80211_input.c | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.c | 36 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 2 |
3 files changed, 40 insertions, 2 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index e0c4879..8defa97 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -954,7 +954,7 @@ ieee80211_send_error(struct ieee80211com *ic, struct ieee80211_node *ni, int istmp; if (ni == ic->ic_bss) { - ni = ieee80211_dup_bss(&ic->ic_sta, mac); + ni = ieee80211_tmp_node(ic, mac); if (ni == NULL) { /* XXX msg */ return; @@ -2107,7 +2107,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta, wh->i_addr2); } else - ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2); + ni = ieee80211_tmp_node(ic, wh->i_addr2); if (ni == NULL) return; allocbs = 1; diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 72884f0..12ff342 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -947,6 +947,42 @@ ieee80211_alloc_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr) return ni; } +/* + * Craft a temporary node suitable for sending a management frame + * to the specified station. We craft only as much state as we + * need to do the work since the node will be immediately reclaimed + * once the send completes. + */ +struct ieee80211_node * +ieee80211_tmp_node(struct ieee80211com *ic, const u_int8_t *macaddr) +{ + struct ieee80211_node *ni; + + ni = ic->ic_node_alloc(&ic->ic_sta); + if (ni != NULL) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE, + "%s %p<%s>\n", __func__, ni, ether_sprintf(macaddr)); + + IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); + IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); + ieee80211_node_initref(ni); /* mark referenced */ + ni->ni_txpower = ic->ic_bss->ni_txpower; + /* NB: required by ieee80211_fix_rate */ + ieee80211_set_chan(ic, ni, ic->ic_bss->ni_chan); + ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey, + IEEE80211_KEYIX_NONE); + /* XXX optimize away */ + IEEE80211_NODE_SAVEQ_INIT(ni, "unknown"); + + ni->ni_table = NULL; /* NB: pedantic */ + ni->ni_ic = ic; + } else { + /* XXX msg */ + ic->ic_stats.is_rx_nodealloc++; + } + return ni; +} + struct ieee80211_node * ieee80211_dup_bss(struct ieee80211_node_table *nt, const u_int8_t *macaddr) { diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 96f642d..c2941c4 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -218,6 +218,8 @@ void ieee80211_node_table_reset(struct ieee80211_node_table *); struct ieee80211_node *ieee80211_alloc_node( struct ieee80211_node_table *, const u_int8_t *); +struct ieee80211_node *ieee80211_tmp_node(struct ieee80211com *, + const u_int8_t *macaddr); struct ieee80211_node *ieee80211_dup_bss(struct ieee80211_node_table *, const u_int8_t *); #ifdef IEEE80211_DEBUG_REFCNT |