[tools] firmware-utils: link statically
[openwrt.git] / 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 */