wlan - Rip out all wlan locks part 1/2
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_wds.c
1 /*-
2  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * $FreeBSD: head/sys/net80211/ieee80211_wds.c 203422 2010-02-03 10:07:43Z rpaulo $
26  * $DragonFly$
27  */
28
29 /*
30  * IEEE 802.11 WDS mode support.
31  */
32 #include "opt_inet.h"
33 #include "opt_wlan.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h> 
37 #include <sys/mbuf.h>   
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
43 #include <sys/endian.h>
44 #include <sys/errno.h>
45 #include <sys/proc.h>
46 #include <sys/sysctl.h>
47
48 #include <net/if.h>
49 #include <net/if_media.h>
50 #include <net/if_llc.h>
51 #include <net/ethernet.h>
52 #include <net/route.h>
53
54 #include <net/bpf.h>
55
56 #include <netproto/802_11/ieee80211_var.h>
57 #include <netproto/802_11/ieee80211_wds.h>
58 #include <netproto/802_11/ieee80211_input.h>
59 #ifdef IEEE80211_SUPPORT_SUPERG
60 #include <netproto/802_11/ieee80211_superg.h>
61 #endif
62
63 static void wds_vattach(struct ieee80211vap *);
64 static int wds_newstate(struct ieee80211vap *, enum ieee80211_state, int);
65 static  int wds_input(struct ieee80211_node *ni, struct mbuf *m, int, int);
66 static void wds_recv_mgmt(struct ieee80211_node *, struct mbuf *,
67             int subtype, int, int);
68
69 void
70 ieee80211_wds_attach(struct ieee80211com *ic)
71 {
72         ic->ic_vattach[IEEE80211_M_WDS] = wds_vattach;
73 }
74
75 void
76 ieee80211_wds_detach(struct ieee80211com *ic)
77 {
78 }
79
80 static void
81 wds_vdetach(struct ieee80211vap *vap)
82 {
83         if (vap->iv_bss != NULL) {
84                 /* XXX locking? */
85                 if (vap->iv_bss->ni_wdsvap == vap)
86                         vap->iv_bss->ni_wdsvap = NULL;
87         }
88 }
89
90 static void
91 wds_vattach(struct ieee80211vap *vap)
92 {
93         vap->iv_newstate = wds_newstate;
94         vap->iv_input = wds_input;
95         vap->iv_recv_mgmt = wds_recv_mgmt;
96         vap->iv_opdetach = wds_vdetach;
97 }
98
99 static void
100 wds_flush(struct ieee80211_node *ni)
101 {
102         struct ieee80211com *ic = ni->ni_ic;
103         struct mbuf *m, *next;
104         int8_t rssi, nf;
105
106         m = ieee80211_ageq_remove(&ic->ic_stageq,
107             (void *)(uintptr_t) ieee80211_mac_hash(ic, ni->ni_macaddr));
108         if (m == NULL)
109                 return;
110
111         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_WDS, ni,
112             "%s", "flush wds queue");
113         ic->ic_node_getsignal(ni, &rssi, &nf);
114         for (; m != NULL; m = next) {
115                 next = m->m_nextpkt;
116                 m->m_nextpkt = NULL;
117                 ieee80211_input(ni, m, rssi, nf);
118         }
119 }
120
121 static int
122 ieee80211_create_wds(struct ieee80211vap *vap, struct ieee80211_channel *chan)
123 {
124         struct ieee80211com *ic = vap->iv_ic;
125 /*      struct ieee80211_node_table *nt = &ic->ic_sta;*/
126         struct ieee80211_node *ni, *obss;
127
128         IEEE80211_DPRINTF(vap, IEEE80211_MSG_WDS,
129              "%s: creating link to %6D on channel %u\n", __func__,
130              vap->iv_des_bssid, ":", ieee80211_chan2ieee(ic, chan));
131
132         /* NB: vap create must specify the bssid for the link */
133         KASSERT(vap->iv_flags & IEEE80211_F_DESBSSID, ("no bssid"));
134         /* NB: we should only be called on RUN transition */
135         KASSERT(vap->iv_state == IEEE80211_S_RUN, ("!RUN state"));
136
137         if ((vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY) == 0) {
138                 /*
139                  * Dynamic/non-legacy WDS.  Reference the associated
140                  * station specified by the desired bssid setup at vap
141                  * create.  Point ni_wdsvap at the WDS vap so 4-address
142                  * frames received through the associated AP vap will
143                  * be dispatched upward (e.g. to a bridge) as though
144                  * they arrived on the WDS vap.
145                  */
146                 obss = NULL;
147                 ni = ieee80211_find_node_locked(&ic->ic_sta, vap->iv_des_bssid);
148                 if (ni == NULL) {
149                         /*
150                          * Node went away before we could hookup.  This
151                          * should be ok; no traffic will flow and a leave
152                          * event will be dispatched that should cause
153                          * the vap to be destroyed.
154                          */
155                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_WDS,
156                             "%s: station %6D went away\n",
157                             __func__, vap->iv_des_bssid, ":");
158                         /* XXX stat? */
159                 } else if (ni->ni_wdsvap != NULL) {
160                         /*
161                          * Node already setup with a WDS vap; we cannot
162                          * allow multiple references so disallow.  If
163                          * ni_wdsvap points at us that's ok; we should
164                          * do nothing anyway.
165                          */
166                         /* XXX printf instead? */
167                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_WDS,
168                             "%s: station %6D in use with %s\n",
169                             __func__, vap->iv_des_bssid, ":",
170                             ni->ni_wdsvap->iv_ifp->if_xname);
171                         /* XXX stat? */
172                 } else {
173                         /*
174                          * Committed to new node, setup state.
175                          */
176                         obss = vap->iv_bss;
177                         vap->iv_bss = ni;
178                         ni->ni_wdsvap = vap;
179                 }
180                 if (obss != NULL) {
181                         /* NB: deferred to avoid recursive lock */
182                         ieee80211_free_node(obss);
183                 }
184         } else {
185                 /*
186                  * Legacy WDS vap setup.
187                  */
188                 /*
189                  * The far end does not associate so we just create
190                  * create a new node and install it as the vap's
191                  * bss node.  We must simulate an association and
192                  * authorize the port for traffic to flow.
193                  * XXX check if node already in sta table?
194                  */
195                 ni = ieee80211_node_create_wds(vap, vap->iv_des_bssid, chan);
196                 if (ni != NULL) {
197                         obss = vap->iv_bss;
198                         vap->iv_bss = ieee80211_ref_node(ni);
199                         ni->ni_flags |= IEEE80211_NODE_AREF;
200                         if (obss != NULL)
201                                 ieee80211_free_node(obss);
202                         /* give driver a chance to setup state like ni_txrate */
203                         if (ic->ic_newassoc != NULL)
204                                 ic->ic_newassoc(ni, 1);
205                         /* tell the authenticator about new station */
206                         if (vap->iv_auth->ia_node_join != NULL)
207                                 vap->iv_auth->ia_node_join(ni);
208                         if (ni->ni_authmode != IEEE80211_AUTH_8021X)
209                                 ieee80211_node_authorize(ni);
210
211                         ieee80211_notify_node_join(ni, 1 /*newassoc*/);
212                         /* XXX inject l2uf frame */
213                 }
214         }
215
216         /*
217          * Flush any pending frames now that were setup.
218          */
219         if (ni != NULL)
220                 wds_flush(ni);
221         return (ni == NULL ? ENOENT : 0);
222 }
223
224 /*
225  * Propagate multicast frames of an ap vap to all DWDS links.
226  * The caller is assumed to have verified this frame is multicast.
227  */
228 void
229 ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
230 {
231         struct ieee80211com *ic = vap0->iv_ic;
232         struct ifnet *parent = ic->ic_ifp;
233         const struct ether_header *eh = mtod(m, const struct ether_header *);
234         struct ieee80211_node *ni;
235         struct ieee80211vap *vap;
236         struct ifnet *ifp;
237         struct mbuf *mcopy;
238         int err;
239
240         KASSERT(ETHER_IS_MULTICAST(eh->ether_dhost),
241             ("%6D not mcast", eh->ether_dhost, ":"));
242
243         /* XXX locking */
244         TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
245                 /* only DWDS vaps are interesting */
246                 if (vap->iv_opmode != IEEE80211_M_WDS ||
247                     (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY))
248                         continue;
249                 /* if it came in this interface, don't send it back out */
250                 ifp = vap->iv_ifp;
251                 if (ifp == m->m_pkthdr.rcvif)
252                         continue;
253                 /*
254                  * Duplicate the frame and send it.
255                  */
256                 mcopy = m_copypacket(m, MB_DONTWAIT);
257                 if (mcopy == NULL) {
258                         ifp->if_oerrors++;
259                         /* XXX stat + msg */
260                         continue;
261                 }
262                 ni = ieee80211_find_txnode(vap, eh->ether_dhost);
263                 if (ni == NULL) {
264                         /* NB: ieee80211_find_txnode does stat+msg */
265                         ifp->if_oerrors++;
266                         m_freem(mcopy);
267                         continue;
268                 }
269                 /* calculate priority so drivers can find the tx queue */
270                 if (ieee80211_classify(ni, mcopy)) {
271                         IEEE80211_DISCARD_MAC(vap,
272                             IEEE80211_MSG_OUTPUT | IEEE80211_MSG_WDS,
273                             eh->ether_dhost, NULL,
274                             "%s", "classification failure");
275                         vap->iv_stats.is_tx_classify++;
276                         ifp->if_oerrors++;
277                         m_freem(mcopy);
278                         ieee80211_free_node(ni);
279                         continue;
280                 }
281
282                 BPF_MTAP(ifp, m);               /* 802.3 tx */
283
284                 /*
285                  * Encapsulate the packet in prep for transmission.
286                  */
287                 mcopy = ieee80211_encap(vap, ni, mcopy);
288                 if (mcopy == NULL) {
289                         /* NB: stat+msg handled in ieee80211_encap */
290                         ieee80211_free_node(ni);
291                         continue;
292                 }
293                 mcopy->m_flags |= M_MCAST;
294                 mcopy->m_pkthdr.rcvif = (void *) ni;
295
296                 err = ieee80211_handoff(parent, mcopy);
297                 if (err) {
298                         /* NB: IFQ_HANDOFF reclaims mbuf */
299                         ifp->if_oerrors++;
300                         ieee80211_free_node(ni);
301                 } else
302                         ifp->if_opackets++;
303         }
304 }
305
306 /*
307  * Handle DWDS discovery on receipt of a 4-address frame in
308  * ap mode.  Queue the frame and post an event for someone
309  * to plumb the necessary WDS vap for this station.  Frames
310  * received prior to the vap set running will then be reprocessed
311  * as if they were just received.
312  */
313 void
314 ieee80211_dwds_discover(struct ieee80211_node *ni, struct mbuf *m)
315 {
316         struct ieee80211com *ic = ni->ni_ic;
317
318         /*
319          * Save the frame with an aging interval 4 times
320          * the listen interval specified by the station. 
321          * Frames that sit around too long are reclaimed
322          * using this information.
323          * XXX handle overflow?
324          * XXX per/vap beacon interval?
325          */
326         m->m_pkthdr.rcvif = (void *)(uintptr_t)
327             ieee80211_mac_hash(ic, ni->ni_macaddr);
328         (void) ieee80211_ageq_append(&ic->ic_stageq, m,
329             ((ni->ni_intval * ic->ic_lintval) << 2) / 1024);
330         ieee80211_notify_wds_discover(ni);
331 }
332
333 /*
334  * IEEE80211_M_WDS vap state machine handler.
335  */
336 static int
337 wds_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
338 {
339         struct ieee80211com *ic = vap->iv_ic;
340         struct ieee80211_node *ni;
341         enum ieee80211_state ostate;
342         int error;
343
344         ostate = vap->iv_state;
345         IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
346                 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
347         vap->iv_state = nstate;                 /* state transition */
348         callout_stop(&vap->iv_mgtsend);         /* XXX callout_drain */
349         if (ostate != IEEE80211_S_SCAN)
350                 ieee80211_cancel_scan(vap);     /* background scan */
351         ni = vap->iv_bss;                       /* NB: no reference held */
352         error = 0;
353         switch (nstate) {
354         case IEEE80211_S_INIT:
355                 switch (ostate) {
356                 case IEEE80211_S_SCAN:
357                         ieee80211_cancel_scan(vap);
358                         break;
359                 default:
360                         break;
361                 }
362                 if (ostate != IEEE80211_S_INIT) {
363                         /* NB: optimize INIT -> INIT case */
364                         ieee80211_reset_bss(vap);
365                 }
366                 break;
367         case IEEE80211_S_SCAN:
368                 switch (ostate) {
369                 case IEEE80211_S_INIT:
370                         ieee80211_check_scan_current(vap);
371                         break;
372                 default:
373                         break;
374                 }
375                 break;
376         case IEEE80211_S_RUN:
377                 if (ostate == IEEE80211_S_INIT) {
378                         /*
379                          * Already have a channel; bypass the scan
380                          * and startup immediately.
381                          */
382                         error = ieee80211_create_wds(vap, ic->ic_curchan);
383                 }
384                 break;
385         default:
386                 break;
387         }
388         return error;
389 }
390
391 /*
392  * Process a received frame.  The node associated with the sender
393  * should be supplied.  If nothing was found in the node table then
394  * the caller is assumed to supply a reference to iv_bss instead.
395  * The RSSI and a timestamp are also supplied.  The RSSI data is used
396  * during AP scanning to select a AP to associate with; it can have
397  * any units so long as values have consistent units and higher values
398  * mean ``better signal''.  The receive timestamp is currently not used
399  * by the 802.11 layer.
400  */
401 static int
402 wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
403 {
404 #define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
405 #define HAS_SEQ(type)   ((type & 0x4) == 0)
406         struct ieee80211vap *vap = ni->ni_vap;
407         struct ieee80211com *ic = ni->ni_ic;
408         struct ifnet *ifp = vap->iv_ifp;
409         struct ieee80211_frame *wh;
410         struct ieee80211_key *key;
411         struct ether_header *eh;
412         int hdrspace, need_tap = 1;     /* mbuf need to be tapped. */
413         uint8_t dir, type, subtype, qos;
414         uint16_t rxseq;
415
416         if (m->m_flags & M_AMPDU_MPDU) {
417                 /*
418                  * Fastpath for A-MPDU reorder q resubmission.  Frames
419                  * w/ M_AMPDU_MPDU marked have already passed through
420                  * here but were received out of order and been held on
421                  * the reorder queue.  When resubmitted they are marked
422                  * with the M_AMPDU_MPDU flag and we can bypass most of
423                  * the normal processing.
424                  */
425                 wh = mtod(m, struct ieee80211_frame *);
426                 type = IEEE80211_FC0_TYPE_DATA;
427                 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
428                 subtype = IEEE80211_FC0_SUBTYPE_QOS;
429                 hdrspace = ieee80211_hdrspace(ic, wh);  /* XXX optimize? */
430                 goto resubmit_ampdu;
431         }
432
433         KASSERT(ni != NULL, ("null node"));
434
435         type = -1;                      /* undefined */
436
437         if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
438                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
439                     ni->ni_macaddr, NULL,
440                     "too short (1): len %u", m->m_pkthdr.len);
441                 vap->iv_stats.is_rx_tooshort++;
442                 goto out;
443         }
444         /*
445          * Bit of a cheat here, we use a pointer for a 3-address
446          * frame format but don't reference fields past outside
447          * ieee80211_frame_min w/o first validating the data is
448          * present.
449          */
450         wh = mtod(m, struct ieee80211_frame *);
451
452         if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
453             IEEE80211_FC0_VERSION_0) {
454                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
455                     ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x",
456                     wh->i_fc[0], wh->i_fc[1]);
457                 vap->iv_stats.is_rx_badversion++;
458                 goto err;
459         }
460
461         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
462         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
463         subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
464
465         /* NB: WDS vap's do not scan */
466         if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_addr4)) {
467                 IEEE80211_DISCARD_MAC(vap,
468                     IEEE80211_MSG_ANY, ni->ni_macaddr, NULL,
469                     "too short (3): len %u", m->m_pkthdr.len);
470                 vap->iv_stats.is_rx_tooshort++;
471                 goto out;
472         }
473         /* NB: the TA is implicitly verified by finding the wds peer node */
474         if (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr) &&
475             !IEEE80211_ADDR_EQ(wh->i_addr1, ifp->if_broadcastaddr)) {
476                 /* not interested in */
477                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
478                     wh->i_addr1, NULL, "%s", "not to bss");
479                 vap->iv_stats.is_rx_wrongbss++;
480                 goto out;
481         }
482         IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
483         ni->ni_noise = nf;
484         if (HAS_SEQ(type)) {
485                 uint8_t tid = ieee80211_gettid(wh);
486                 if (IEEE80211_QOS_HAS_SEQ(wh) &&
487                     TID_TO_WME_AC(tid) >= WME_AC_VI)
488                         ic->ic_wme.wme_hipri_traffic++;
489                 rxseq = le16toh(*(uint16_t *)wh->i_seq);
490                 if ((ni->ni_flags & IEEE80211_NODE_HT) == 0 &&
491                     (wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
492                     SEQ_LEQ(rxseq, ni->ni_rxseqs[tid])) {
493                         /* duplicate, discard */
494                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
495                             wh->i_addr1, "duplicate",
496                             "seqno <%u,%u> fragno <%u,%u> tid %u",
497                             rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
498                             ni->ni_rxseqs[tid] >> IEEE80211_SEQ_SEQ_SHIFT,
499                             rxseq & IEEE80211_SEQ_FRAG_MASK,
500                             ni->ni_rxseqs[tid] & IEEE80211_SEQ_FRAG_MASK,
501                             tid);
502                         vap->iv_stats.is_rx_dup++;
503                         IEEE80211_NODE_STAT(ni, rx_dup);
504                         goto out;
505                 }
506                 ni->ni_rxseqs[tid] = rxseq;
507         }
508         switch (type) {
509         case IEEE80211_FC0_TYPE_DATA:
510                 hdrspace = ieee80211_hdrspace(ic, wh);
511                 if (m->m_len < hdrspace &&
512                     (m = m_pullup(m, hdrspace)) == NULL) {
513                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
514                             ni->ni_macaddr, NULL,
515                             "data too short: expecting %u", hdrspace);
516                         vap->iv_stats.is_rx_tooshort++;
517                         goto out;               /* XXX */
518                 }
519                 if (dir != IEEE80211_FC1_DIR_DSTODS) {
520                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
521                             wh, "data", "incorrect dir 0x%x", dir);
522                         vap->iv_stats.is_rx_wrongdir++;
523                         goto out;
524                 }
525                 /*
526                  * Only legacy WDS traffic should take this path.
527                  */
528                 if ((vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY) == 0) {
529                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
530                             wh, "data", "%s", "not legacy wds");
531                         vap->iv_stats.is_rx_wrongdir++;/*XXX*/
532                         goto out;
533                 }
534                 if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
535                         ni->ni_inact = ni->ni_inact_reload;
536                 /*
537                  * Handle A-MPDU re-ordering.  If the frame is to be
538                  * processed directly then ieee80211_ampdu_reorder
539                  * will return 0; otherwise it has consumed the mbuf
540                  * and we should do nothing more with it.
541                  */
542                 if ((m->m_flags & M_AMPDU) &&
543                     ieee80211_ampdu_reorder(ni, m) != 0) {
544                         m = NULL;
545                         goto out;
546                 }
547         resubmit_ampdu:
548
549                 /*
550                  * Handle privacy requirements.  Note that we
551                  * must not be preempted from here until after
552                  * we (potentially) call ieee80211_crypto_demic;
553                  * otherwise we may violate assumptions in the
554                  * crypto cipher modules used to do delayed update
555                  * of replay sequence numbers.
556                  */
557                 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
558                         if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
559                                 /*
560                                  * Discard encrypted frames when privacy is off.
561                                  */
562                                 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
563                                     wh, "WEP", "%s", "PRIVACY off");
564                                 vap->iv_stats.is_rx_noprivacy++;
565                                 IEEE80211_NODE_STAT(ni, rx_noprivacy);
566                                 goto out;
567                         }
568                         key = ieee80211_crypto_decap(ni, m, hdrspace);
569                         if (key == NULL) {
570                                 /* NB: stats+msgs handled in crypto_decap */
571                                 IEEE80211_NODE_STAT(ni, rx_wepfail);
572                                 goto out;
573                         }
574                         wh = mtod(m, struct ieee80211_frame *);
575                         wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
576                 } else {
577                         /* XXX M_WEP and IEEE80211_F_PRIVACY */
578                         key = NULL;
579                 }
580
581                 /*
582                  * Save QoS bits for use below--before we strip the header.
583                  */
584                 if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
585                         qos = (dir == IEEE80211_FC1_DIR_DSTODS) ?
586                             ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] :
587                             ((struct ieee80211_qosframe *)wh)->i_qos[0];
588                 } else
589                         qos = 0;
590
591                 /*
592                  * Next up, any fragmentation.
593                  */
594                 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
595                         m = ieee80211_defrag(ni, m, hdrspace);
596                         if (m == NULL) {
597                                 /* Fragment dropped or frame not complete yet */
598                                 goto out;
599                         }
600                 }
601                 wh = NULL;              /* no longer valid, catch any uses */
602
603                 /*
604                  * Next strip any MSDU crypto bits.
605                  */
606                 if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
607                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
608                             ni->ni_macaddr, "data", "%s", "demic error");
609                         vap->iv_stats.is_rx_demicfail++;
610                         IEEE80211_NODE_STAT(ni, rx_demicfail);
611                         goto out;
612                 }
613
614                 /* copy to listener after decrypt */
615                 if (ieee80211_radiotap_active_vap(vap))
616                         ieee80211_radiotap_rx(vap, m);
617                 need_tap = 0;
618
619                 /*
620                  * Finally, strip the 802.11 header.
621                  */
622                 m = ieee80211_decap(vap, m, hdrspace);
623                 if (m == NULL) {
624                         /* XXX mask bit to check for both */
625                         /* don't count Null data frames as errors */
626                         if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
627                             subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
628                                 goto out;
629                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
630                             ni->ni_macaddr, "data", "%s", "decap error");
631                         vap->iv_stats.is_rx_decap++;
632                         IEEE80211_NODE_STAT(ni, rx_decap);
633                         goto err;
634                 }
635                 eh = mtod(m, struct ether_header *);
636                 if (!ieee80211_node_is_authorized(ni)) {
637                         /*
638                          * Deny any non-PAE frames received prior to
639                          * authorization.  For open/shared-key
640                          * authentication the port is mark authorized
641                          * after authentication completes.  For 802.1x
642                          * the port is not marked authorized by the
643                          * authenticator until the handshake has completed.
644                          */
645                         if (eh->ether_type != htons(ETHERTYPE_PAE)) {
646                                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
647                                     eh->ether_shost, "data",
648                                     "unauthorized port: ether type 0x%x len %u",
649                                     eh->ether_type, m->m_pkthdr.len);
650                                 vap->iv_stats.is_rx_unauth++;
651                                 IEEE80211_NODE_STAT(ni, rx_unauth);
652                                 goto err;
653                         }
654                 } else {
655                         /*
656                          * When denying unencrypted frames, discard
657                          * any non-PAE frames received without encryption.
658                          */
659                         if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
660                             (key == NULL && (m->m_flags & M_WEP) == 0) &&
661                             eh->ether_type != htons(ETHERTYPE_PAE)) {
662                                 /*
663                                  * Drop unencrypted frames.
664                                  */
665                                 vap->iv_stats.is_rx_unencrypted++;
666                                 IEEE80211_NODE_STAT(ni, rx_unencrypted);
667                                 goto out;
668                         }
669                 }
670                 /* XXX require HT? */
671                 if (qos & IEEE80211_QOS_AMSDU) {
672                         m = ieee80211_decap_amsdu(ni, m);
673                         if (m == NULL)
674                                 return IEEE80211_FC0_TYPE_DATA;
675                 } else {
676 #ifdef IEEE80211_SUPPORT_SUPERG
677                         m = ieee80211_decap_fastframe(vap, ni, m);
678                         if (m == NULL)
679                                 return IEEE80211_FC0_TYPE_DATA;
680 #endif
681                 }
682                 ieee80211_deliver_data(vap, ni, m);
683                 return IEEE80211_FC0_TYPE_DATA;
684
685         case IEEE80211_FC0_TYPE_MGT:
686                 vap->iv_stats.is_rx_mgmt++;
687                 IEEE80211_NODE_STAT(ni, rx_mgmt);
688                 if (dir != IEEE80211_FC1_DIR_NODS) {
689                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
690                             wh, "data", "incorrect dir 0x%x", dir);
691                         vap->iv_stats.is_rx_wrongdir++;
692                         goto err;
693                 }
694                 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
695                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
696                             ni->ni_macaddr, "mgt", "too short: len %u",
697                             m->m_pkthdr.len);
698                         vap->iv_stats.is_rx_tooshort++;
699                         goto out;
700                 }
701 #ifdef IEEE80211_DEBUG
702                 if (ieee80211_msg_debug(vap) || ieee80211_msg_dumppkts(vap)) {
703                         if_printf(ifp, "received %s from %6D rssi %d\n",
704                             ieee80211_mgt_subtype_name[subtype >>
705                                 IEEE80211_FC0_SUBTYPE_SHIFT],
706                             wh->i_addr2, ":", rssi);
707                 }
708 #endif
709                 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
710                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
711                             wh, NULL, "%s", "WEP set but not permitted");
712                         vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
713                         goto out;
714                 }
715                 vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
716                 goto out;
717
718         case IEEE80211_FC0_TYPE_CTL:
719                 vap->iv_stats.is_rx_ctl++;
720                 IEEE80211_NODE_STAT(ni, rx_ctrl);
721                 goto out;
722
723         default:
724                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
725                     wh, "bad", "frame type 0x%x", type);
726                 /* should not come here */
727                 break;
728         }
729 err:
730         ifp->if_ierrors++;
731 out:
732         if (m != NULL) {
733                 if (need_tap && ieee80211_radiotap_active_vap(vap))
734                         ieee80211_radiotap_rx(vap, m);
735                 m_freem(m);
736         }
737         return type;
738 #undef SEQ_LEQ
739 }
740
741 static void
742 wds_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
743         int subtype, int rssi, int nf)
744 {
745         struct ieee80211vap *vap = ni->ni_vap;
746         struct ieee80211com *ic = ni->ni_ic;
747         struct ieee80211_frame *wh;
748         u_int8_t *frm, *efrm;
749
750         wh = mtod(m0, struct ieee80211_frame *);
751         frm = (u_int8_t *)&wh[1];
752         efrm = mtod(m0, u_int8_t *) + m0->m_len;
753         switch (subtype) {
754         case IEEE80211_FC0_SUBTYPE_DEAUTH:
755         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
756         case IEEE80211_FC0_SUBTYPE_BEACON:
757         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
758         case IEEE80211_FC0_SUBTYPE_AUTH:
759         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
760         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
761         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
762         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
763         case IEEE80211_FC0_SUBTYPE_DISASSOC:
764                 vap->iv_stats.is_rx_mgtdiscard++;
765                 break;
766         case IEEE80211_FC0_SUBTYPE_ACTION:
767                 if (vap->iv_state != IEEE80211_S_RUN ||
768                     IEEE80211_IS_MULTICAST(wh->i_addr1)) {
769                         vap->iv_stats.is_rx_mgtdiscard++;
770                         break;
771                 }
772                 ni->ni_inact = ni->ni_inact_reload;
773                 if (ieee80211_parse_action(ni, m0) == 0)
774                         ic->ic_recv_action(ni, wh, frm, efrm);
775                 break;
776         default:
777                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
778                      wh, "mgt", "subtype 0x%x not handled", subtype);
779                 vap->iv_stats.is_rx_badsubtype++;
780                 break;
781         }
782 }