Root/package/madwifi/patches/393-mbss_vap_auth.patch

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 *);
6 
7+static struct ieee80211_node *
8+lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, const u_int8_t *addr);
9+
10 MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
11 
12 void
13@@ -697,7 +700,7 @@ ieee80211_sta_join(struct ieee80211vap *
14     struct ieee80211com *ic = vap->iv_ic;
15     struct ieee80211_node *ni;
16 
17- ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);
18+ ni = lookup_rxnode(ic, vap, se->se_macaddr);
19     if (ni == NULL) {
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
23     return ni;
24 }
25 
26+struct ieee80211vap *
27+ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac)
28+{
29+ struct ieee80211vap *vap;
30+
31+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
32+ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, mac))
33+ return vap;
34+ }
35+ return NULL;
36+}
37+EXPORT_SYMBOL(ieee80211_find_rxvap);
38+
39+static struct ieee80211_node *
40+lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
41+ const u_int8_t *addr)
42+{
43+ struct ieee80211_node_table *nt;
44+ struct ieee80211_node *ni = NULL;
45+ int use_bss = 0;
46+ int hash;
47+
48+ nt = &ic->ic_sta;
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))
55+ continue;
56+
57+ ieee80211_ref_node(ni);
58+ goto out;
59+ }
60+ }
61+
62+ /* no match found */
63+ ni = NULL;
64+
65+out:
66+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
67+ return ni;
68+#undef IS_PSPOLL
69+#undef IS_CTL
70+}
71+
72+
73 /*
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
77  */
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)
83 #else
84-ieee80211_find_rxnode(struct ieee80211com *ic,
85+ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
86     const struct ieee80211_frame_min *wh)
87 #endif
88 {
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;
98     const u_int8_t *addr;
99 
100     if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
101@@ -1429,32 +1478,25 @@ ieee80211_find_rxnode(struct ieee80211co
102 
103     /* XXX check ic_bss first in station mode */
104     /* XXX 4-address frames? */
105- nt = &ic->ic_sta;
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))
114                     continue;
115 
116                 if (avp->iv_wdsnode)
117- return ieee80211_ref_node(avp->iv_wdsnode);
118- else
119- return NULL;
120+ ni = ieee80211_ref_node(avp->iv_wdsnode);
121+ return ni;
122             }
123+ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS))
124+ return NULL;
125+ } else {
126+ return NULL;
127         }
128     }
129 
130-#ifdef IEEE80211_DEBUG_REFCNT
131- ni = ieee80211_find_node_locked_debug(nt, addr, func, line);
132-#else
133- ni = ieee80211_find_node_locked(nt, addr);
134-#endif
135- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
136-
137- return ni;
138-#undef IS_PSPOLL
139-#undef IS_CTL
140+ return lookup_rxnode(ic, vap, addr);
141 }
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;
148+ int hash;
149 
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);
154         else
155             return NULL;
156     }
157- IEEE80211_UNLOCK_IRQ(ic);
158 
159     /*
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)
168+ continue;
169+
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);
174 #else
175- ni = ieee80211_find_node_locked(nt, mac);
176+ ieee80211_ref_node(ni);
177 #endif
178+ goto found;
179+ }
180+ }
181+ ni = NULL;
182+found:
183     IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
184 
185     if (ni == NULL) {
186@@ -1964,13 +2016,32 @@ remove_worse_nodes(void *arg, struct iee
187         }
188 }
189 
190+static void
191+remove_duplicate_nodes(void *arg, struct ieee80211_node *ni)
192+{
193+ struct ieee80211_node *rni = arg;
194+
195+ if (ni == rni)
196+ return;
197+
198+ if (ni->ni_vap == rni->ni_vap)
199+ return;
200+
201+ if (!IEEE80211_ADDR_EQ(rni->ni_macaddr, ni->ni_macaddr))
202+ return;
203+
204+ ieee80211_node_leave(ni);
205+}
206+
207 void
208 ieee80211_node_join(struct ieee80211_node *ni, int resp)
209 {
210     struct ieee80211com *ic = ni->ni_ic;
211     struct ieee80211vap *vap = ni->ni_vap;
212+ struct ieee80211_node *tni;
213     int newassoc;
214 
215+ ieee80211_iterate_nodes(&ic->ic_sta, remove_duplicate_nodes, ni);
216     if (ni->ni_associd == 0) {
217         u_int16_t aid;
218 
219--- a/net80211/ieee80211_input.c
220+++ b/net80211/ieee80211_input.c
221@@ -216,16 +216,14 @@ ieee80211_input(struct ieee80211vap * va
222 
223     type = -1; /* undefined */
224 
225- if (!vap)
226- goto out;
227+ if (!vap || !vap->iv_bss || !vap->iv_dev || !vap->iv_ic)
228+ goto discard;
229 
230     ic = vap->iv_ic;
231- if (!ic)
232- goto out;
233-
234     dev = vap->iv_dev;
235- if (!dev)
236- goto out;
237+
238+ if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
239+ goto discard;
240 
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"));
248+ } else {
249+ ni->ni_inact = ni->ni_inact_reload;
250     }
251- KASSERT(ni != NULL, ("null node"));
252- ni->ni_inact = ni->ni_inact_reload;
253 
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
257 err:
258     vap->iv_devstats.rx_errors++;
259 out:
260- if (skb != NULL)
261- ieee80211_dev_kfree_skb(&skb);
262     if (ni_or_null == NULL)
263         ieee80211_unref_node(&ni);
264+discard:
265+ if (skb != NULL)
266+ ieee80211_dev_kfree_skb(&skb);
267     return type;
268 #undef HAS_SEQ
269 }
270@@ -929,16 +929,23 @@ int
271 ieee80211_input_all(struct ieee80211com *ic,
272     struct sk_buff *skb, int rssi, u_int64_t rtsf)
273 {
274+ struct ieee80211_frame_min *wh = (struct ieee80211_frame_min *) skb->data;
275     struct ieee80211vap *vap;
276     int type = -1;
277 
278     /* XXX locking */
279     TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
280+ struct ieee80211_node *ni = NULL;
281         struct sk_buff *skb1;
282 
283         if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
284             continue;
285 
286+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
287+ !IEEE80211_IS_MULTICAST(wh->i_addr1))
288+ continue;
289+
290+ ni = ieee80211_find_rxnode(ic, vap, wh);
291         if (TAILQ_NEXT(vap, iv_next) != NULL) {
292             skb1 = skb_copy(skb, GFP_ATOMIC);
293             if (skb1 == NULL) {
294@@ -950,8 +957,12 @@ ieee80211_input_all(struct ieee80211com
295             skb1 = skb;
296             skb = NULL;
297         }
298- type = ieee80211_input(vap, NULL, skb1, rssi, rtsf);
299+ type = ieee80211_input(vap, ni, skb1, rssi, rtsf);
300+ if (ni)
301+ ieee80211_unref_node(&ni);
302     }
303+
304+out:
305     if (skb != NULL) /* no vaps, reclaim skb */
306         ieee80211_dev_kfree_skb(&skb);
307     return type;
308@@ -1147,11 +1158,9 @@ ieee80211_deliver_data(struct ieee80211_
309              * sending it will not work; just let it be
310              * delivered normally.
311              */
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);
315             if (ni1 != NULL) {
316- if (ni1->ni_vap == vap &&
317- ieee80211_node_is_authorized(ni1) &&
318+ if (ieee80211_node_is_authorized(ni1) &&
319                     !ni1->ni_subif &&
320                     ni1 != vap->iv_bss) {
321 
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;
326+ int do_unref = 0;
327             int found = 0;
328 
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);
339                 }
340+ do_unref = 1;
341             } else {
342                 /*
343                  * Copy data from beacon to neighbor table.
344@@ -3595,6 +3607,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
345                 ni->ni_rssi = rssi;
346                 ni->ni_rtsf = rtsf;
347                 ni->ni_last_rx = jiffies;
348+ if (do_unref)
349+ ieee80211_unref_node(&ni);
350             }
351         }
352         break;
353--- a/ath/if_ath.c
354+++ b/ath/if_ath.c
355@@ -6589,9 +6589,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
356 
357     sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
358 
359-
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);
364     if (ni == NULL) {
365         DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
366@@ -6746,7 +6745,9 @@ ath_rx_poll(struct net_device *dev, int
367     struct ath_desc *ds;
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;
373     unsigned int len;
374     int type;
375     u_int phyerr;
376@@ -6901,12 +6902,15 @@ rx_accept:
377         skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
378 
379         if (mic_fail) {
380+ wh = (const struct ieee80211_frame_min *) skb->data;
381+
382             /* Ignore control frames which are reported with mic error */
383- if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
384+ if ((wh->i_fc[0] &
385                     IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
386                 goto drop_micfail;
387 
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);
391 
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.
397          */
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
415+ */
416+ goto lookup_slowpath;
417+ }
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.
424              */
425- ni = ieee80211_find_rxnode(ic,
426- (const struct ieee80211_frame_min *)skb->data);
427+
428+lookup_slowpath:
429+ if (IEEE80211_IS_MULTICAST(wh->i_addr1))
430+ vap = NULL;
431+ else
432+ vap = ieee80211_find_rxvap(ic, wh->i_addr1);
433+
434+ if (vap)
435+ ni = ieee80211_find_rxnode(ic, vap, wh);
436+ else
437+ ni = NULL;
438+
439             if (ni != NULL) {
440                 ieee80211_keyix_t keyix;
441 
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);
445                 /*
446                  * If the station has a key cache slot assigned
447                  * update the key->node mapping table.
448                  */
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);
454+ }
455                 ieee80211_unref_node(&ni);
456- } else
457- type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
458+ } else {
459+ if (vap)
460+ type = ieee80211_input(vap, NULL, skb, rs->rs_rssi, bf->bf_tsf);
461+ else
462+ type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
463+ }
464         }
465 
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
470     const u_int8_t *);
471 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
472 
473+struct ieee80211vap *
474+ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac);
475+
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);
485 #else
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 */
490 
491 /* Returns a ieee80211_node* with refcount incremented, if found */
492

Archive Download this file



interactive