1 --- a/net80211/ieee80211_node.c
2 +++ b/net80211/ieee80211_node.c
3 @@ -123,6 +123,9 @@ static void ieee80211_node_table_cleanup
4 static void ieee80211_node_table_reset(struct ieee80211_node_table *,
5 struct ieee80211vap *);
7 +static struct ieee80211_node *
8 +lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, const u_int8_t *addr);
10 MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
13 @@ -697,7 +700,7 @@ ieee80211_sta_join(struct ieee80211vap *
14 struct ieee80211com *ic = vap->iv_ic;
15 struct ieee80211_node *ni;
17 - ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);
18 + ni = lookup_rxnode(ic, vap, se->se_macaddr);
20 ni = ieee80211_alloc_node_table(vap, se->se_macaddr);
21 IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
22 @@ -1394,6 +1397,53 @@ ieee80211_add_neighbor(struct ieee80211v
26 +struct ieee80211vap *
27 +ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac)
29 + struct ieee80211vap *vap;
31 + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
32 + if (IEEE80211_ADDR_EQ(vap->iv_myaddr, mac))
37 +EXPORT_SYMBOL(ieee80211_find_rxvap);
39 +static struct ieee80211_node *
40 +lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
41 + const u_int8_t *addr)
43 + struct ieee80211_node_table *nt;
44 + struct ieee80211_node *ni = NULL;
49 + IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
50 + hash = IEEE80211_NODE_HASH(addr);
51 + LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
52 + if (IEEE80211_ADDR_EQ(ni->ni_macaddr, addr)) {
53 + /* allow multiple nodes on different vaps */
54 + if (vap && (ni->ni_vap != vap))
57 + ieee80211_ref_node(ni);
62 + /* no match found */
66 + IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
74 * Return the node for the sender of a frame; if the sender is unknown return
75 * NULL. The caller is expected to deal with this. (The frame is sent to all
76 @@ -1403,10 +1453,10 @@ ieee80211_add_neighbor(struct ieee80211v
78 struct ieee80211_node *
79 #ifdef IEEE80211_DEBUG_REFCNT
80 -ieee80211_find_rxnode_debug(struct ieee80211com *ic,
81 +ieee80211_find_rxnode_debug(struct ieee80211com *ic, struct ieee80211vap *vap,
82 const struct ieee80211_frame_min *wh, const char *func, int line)
84 -ieee80211_find_rxnode(struct ieee80211com *ic,
85 +ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
86 const struct ieee80211_frame_min *wh)
89 @@ -1414,9 +1464,8 @@ ieee80211_find_rxnode(struct ieee80211co
90 ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
91 #define IS_PSPOLL(wh) \
92 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
93 - struct ieee80211_node_table *nt;
94 - struct ieee80211_node *ni;
95 - struct ieee80211vap *vap, *avp;
96 + struct ieee80211_node *ni = NULL;
97 + struct ieee80211vap *avp;
100 if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
101 @@ -1429,32 +1478,25 @@ ieee80211_find_rxnode(struct ieee80211co
103 /* XXX check ic_bss first in station mode */
104 /* XXX 4-address frames? */
106 - IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
107 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) {
108 - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
109 + if (vap) { /* assume unicast if vap is set, mcast not supported for wds */
110 TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
111 - if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac))
112 + if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac) ||
113 + !IEEE80211_ADDR_EQ(wh->i_addr1, avp->iv_myaddr))
117 - return ieee80211_ref_node(avp->iv_wdsnode);
120 + ni = ieee80211_ref_node(avp->iv_wdsnode);
123 + if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS))
130 -#ifdef IEEE80211_DEBUG_REFCNT
131 - ni = ieee80211_find_node_locked_debug(nt, addr, func, line);
133 - ni = ieee80211_find_node_locked(nt, addr);
135 - IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
140 + return lookup_rxnode(ic, vap, addr);
142 #ifdef IEEE80211_DEBUG_REFCNT
143 EXPORT_SYMBOL(ieee80211_find_rxnode_debug);
144 @@ -1479,15 +1521,14 @@ ieee80211_find_txnode(struct ieee80211va
145 struct ieee80211com *ic = vap->iv_ic;
146 struct ieee80211_node_table *nt;
147 struct ieee80211_node *ni = NULL;
150 - IEEE80211_LOCK_IRQ(ic);
151 if (vap->iv_opmode == IEEE80211_M_WDS) {
152 if (vap->iv_wdsnode && (vap->iv_state == IEEE80211_S_RUN))
153 return ieee80211_ref_node(vap->iv_wdsnode);
157 - IEEE80211_UNLOCK_IRQ(ic);
160 * The destination address should be in the node table
161 @@ -1505,11 +1546,22 @@ ieee80211_find_txnode(struct ieee80211va
162 /* XXX: Can't hold lock across dup_bss due to recursive locking. */
163 nt = &vap->iv_ic->ic_sta;
164 IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
165 + hash = IEEE80211_NODE_HASH(mac);
166 + LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
167 + if (ni->ni_vap != vap)
170 + if (IEEE80211_ADDR_EQ(ni->ni_macaddr, mac)) {
171 #ifdef IEEE80211_DEBUG_REFCNT
172 - ni = ieee80211_find_node_locked_debug(nt, mac, func, line);
173 + ieee80211_ref_node_debug(ni, func, line);
175 - ni = ieee80211_find_node_locked(nt, mac);
176 + ieee80211_ref_node(ni);
183 IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
186 @@ -1964,13 +2016,32 @@ remove_worse_nodes(void *arg, struct iee
191 +remove_duplicate_nodes(void *arg, struct ieee80211_node *ni)
193 + struct ieee80211_node *rni = arg;
198 + if (ni->ni_vap == rni->ni_vap)
201 + if (!IEEE80211_ADDR_EQ(rni->ni_macaddr, ni->ni_macaddr))
204 + ieee80211_node_leave(ni);
208 ieee80211_node_join(struct ieee80211_node *ni, int resp)
210 struct ieee80211com *ic = ni->ni_ic;
211 struct ieee80211vap *vap = ni->ni_vap;
212 + struct ieee80211_node *tni;
215 + ieee80211_iterate_nodes(&ic->ic_sta, remove_duplicate_nodes, ni);
216 if (ni->ni_associd == 0) {
219 --- a/net80211/ieee80211_input.c
220 +++ b/net80211/ieee80211_input.c
221 @@ -216,16 +216,14 @@ ieee80211_input(struct ieee80211vap * va
223 type = -1; /* undefined */
227 + if (!vap || !vap->iv_bss || !vap->iv_dev || !vap->iv_ic)
238 + if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
241 /* initialize ni as in the previous API */
242 if (ni_or_null == NULL) {
243 @@ -233,9 +231,10 @@ ieee80211_input(struct ieee80211vap * va
244 * guarantee its existence during the following call, hence
245 * briefly grab our own reference. */
246 ni = ieee80211_ref_node(vap->iv_bss);
247 + KASSERT(ni != NULL, ("null node"));
249 + ni->ni_inact = ni->ni_inact_reload;
251 - KASSERT(ni != NULL, ("null node"));
252 - ni->ni_inact = ni->ni_inact_reload;
254 KASSERT(skb->len >= sizeof(struct ieee80211_frame_min),
255 ("frame length too short: %u", skb->len));
256 @@ -844,10 +843,11 @@ ieee80211_input(struct ieee80211vap * va
258 vap->iv_devstats.rx_errors++;
261 - ieee80211_dev_kfree_skb(&skb);
262 if (ni_or_null == NULL)
263 ieee80211_unref_node(&ni);
266 + ieee80211_dev_kfree_skb(&skb);
270 @@ -929,16 +929,23 @@ int
271 ieee80211_input_all(struct ieee80211com *ic,
272 struct sk_buff *skb, int rssi, u_int64_t rtsf)
274 + struct ieee80211_frame_min *wh = (struct ieee80211_frame_min *) skb->data;
275 struct ieee80211vap *vap;
279 TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
280 + struct ieee80211_node *ni = NULL;
281 struct sk_buff *skb1;
283 if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
286 + if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
287 + !IEEE80211_IS_MULTICAST(wh->i_addr1))
290 + ni = ieee80211_find_rxnode(ic, vap, wh);
291 if (TAILQ_NEXT(vap, iv_next) != NULL) {
292 skb1 = skb_copy(skb, GFP_ATOMIC);
294 @@ -950,8 +957,12 @@ ieee80211_input_all(struct ieee80211com
298 - type = ieee80211_input(vap, NULL, skb1, rssi, rtsf);
299 + type = ieee80211_input(vap, ni, skb1, rssi, rtsf);
301 + ieee80211_unref_node(&ni);
305 if (skb != NULL) /* no vaps, reclaim skb */
306 ieee80211_dev_kfree_skb(&skb);
308 @@ -1147,11 +1158,9 @@ ieee80211_deliver_data(struct ieee80211_
309 * sending it will not work; just let it be
310 * delivered normally.
312 - struct ieee80211_node *ni1 = ieee80211_find_node(
313 - &vap->iv_ic->ic_sta, eh->ether_dhost);
314 + struct ieee80211_node *ni1 = ieee80211_find_txnode(vap, eh->ether_dhost);
316 - if (ni1->ni_vap == vap &&
317 - ieee80211_node_is_authorized(ni1) &&
318 + if (ieee80211_node_is_authorized(ni1) &&
320 ni1 != vap->iv_bss) {
322 @@ -3520,6 +3529,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
323 (vap->iv_opmode == IEEE80211_M_WDS)) &&
324 (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
325 struct ieee80211vap *avp = NULL;
329 IEEE80211_LOCK_IRQ(vap->iv_ic);
330 @@ -3553,10 +3563,12 @@ ieee80211_recv_mgmt(struct ieee80211vap
331 ni->ni_associd |= 0xc000;
332 avp->iv_wdsnode = ieee80211_ref_node(ni);
333 IEEE80211_UNLOCK_IRQ(ic);
334 - } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
335 + } else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
336 + IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
337 /* Create a new entry in the neighbor table. */
338 ni = ieee80211_add_neighbor(vap, wh, &scan);
343 * Copy data from beacon to neighbor table.
344 @@ -3595,6 +3607,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
347 ni->ni_last_rx = jiffies;
349 + ieee80211_unref_node(&ni);
355 @@ -6589,9 +6589,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
357 sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
360 /* Lookup the new node if any (this grabs a reference to it) */
361 - ni = ieee80211_find_rxnode(vap->iv_ic,
362 + ni = ieee80211_find_rxnode(vap->iv_ic, vap,
363 (const struct ieee80211_frame_min *)skb->data);
365 DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
366 @@ -6746,7 +6745,9 @@ ath_rx_poll(struct net_device *dev, int
368 struct ath_rx_status *rs;
369 struct sk_buff *skb = NULL;
370 + struct ieee80211vap *vap;
371 struct ieee80211_node *ni;
372 + const struct ieee80211_frame_min *wh;
376 @@ -6901,12 +6902,15 @@ rx_accept:
377 skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
380 + wh = (const struct ieee80211_frame_min *) skb->data;
382 /* Ignore control frames which are reported with mic error */
383 - if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
385 IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
388 - ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
389 + vap = ieee80211_find_rxvap(ic, wh->i_addr1);
390 + ni = ieee80211_find_rxnode(ic, vap, wh);
392 if (ni && ni->ni_table) {
393 ieee80211_check_mic(ni, skb);
394 @@ -6968,11 +6972,24 @@ drop_micfail:
395 * for its use. If the sender is unknown spam the
396 * frame; it'll be dropped where it's not wanted.
398 - if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
399 + wh = (const struct ieee80211_frame_min *) skb->data;
400 + if ((rs->rs_keyix != HAL_RXKEYIX_INVALID) &&
401 (ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
402 /* Fast path: node is present in the key map;
403 * grab a reference for processing the frame. */
404 - ni = ieee80211_ref_node(ni);
405 + ieee80211_ref_node(ni);
406 + if ((ATH_GET_VAP_ID(wh->i_addr1) !=
407 + ATH_GET_VAP_ID(ni->ni_vap->iv_myaddr)) ||
408 + ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
409 + IEEE80211_FC1_DIR_DSTODS)) {
410 + /* key cache node lookup is fast, but it can
411 + * lead to problems in multi-bss (foreign vap
412 + * node reference) or wds (wdsap node ref instead
413 + * of base ap node ref).
414 + * use slowpath lookup in both cases
416 + goto lookup_slowpath;
418 ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
419 type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
420 ieee80211_unref_node(&ni);
421 @@ -6981,24 +6998,39 @@ drop_micfail:
422 * No key index or no entry, do a lookup and
423 * add the node to the mapping table if possible.
425 - ni = ieee80211_find_rxnode(ic,
426 - (const struct ieee80211_frame_min *)skb->data);
429 + if (IEEE80211_IS_MULTICAST(wh->i_addr1))
432 + vap = ieee80211_find_rxvap(ic, wh->i_addr1);
435 + ni = ieee80211_find_rxnode(ic, vap, wh);
440 ieee80211_keyix_t keyix;
442 ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
443 - type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
444 + type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
446 * If the station has a key cache slot assigned
447 * update the key->node mapping table.
449 keyix = ni->ni_ucastkey.wk_keyix;
450 if (keyix != IEEE80211_KEYIX_NONE &&
451 - sc->sc_keyixmap[keyix] == NULL)
452 + sc->sc_keyixmap[keyix] == NULL) {
453 sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
455 ieee80211_unref_node(&ni);
457 - type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
460 + type = ieee80211_input(vap, NULL, skb, rs->rs_rssi, bf->bf_tsf);
462 + type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
466 if (sc->sc_diversity) {
467 --- a/net80211/ieee80211_node.h
468 +++ b/net80211/ieee80211_node.h
469 @@ -286,15 +286,18 @@ struct ieee80211_node *ieee80211_find_no
471 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
473 +struct ieee80211vap *
474 +ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac);
476 /* Returns a ieee80211_node* with refcount incremented, if found */
477 #ifdef IEEE80211_DEBUG_REFCNT
478 -#define ieee80211_find_rxnode(_nt, _wh) \
479 - ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__)
480 +#define ieee80211_find_rxnode(_nt, _vap, _wh) \
481 + ieee80211_find_rxnode_debug(_nt, _vap, _wh, __func__, __LINE__)
482 struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *,
483 - const struct ieee80211_frame_min *, const char *, int);
484 + struct ieee80211vap *, const struct ieee80211_frame_min *, const char *, int);
486 struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,
487 - const struct ieee80211_frame_min *);
488 + struct ieee80211vap *, const struct ieee80211_frame_min *);
489 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
491 /* Returns a ieee80211_node* with refcount incremented, if found */