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