4e88dd966c38a415cb56c541e7616e83ee70592c
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_input.c
1 /*-
2  * Copyright (c) 2001 Atsushi Onoe
3  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_wlan.h"
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/mbuf.h>   
35 #include <sys/malloc.h>
36 #include <sys/endian.h>
37 #include <sys/kernel.h>
38  
39 #include <sys/socket.h>
40  
41 #include <net/ethernet.h>
42 #include <net/if.h>
43 #include <net/if_var.h>
44 #include <net/if_llc.h>
45 #include <net/if_media.h>
46 #if defined(__DragonFly__)
47 #include <net/vlan/if_vlan_var.h>
48 #else
49 #include <net/if_vlan_var.h>
50 #endif
51
52 #include <netproto/802_11/ieee80211_var.h>
53 #include <netproto/802_11/ieee80211_input.h>
54 #ifdef IEEE80211_SUPPORT_MESH
55 #include <netproto/802_11/ieee80211_mesh.h>
56 #endif
57
58 #include <net/bpf.h>
59
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <net/ethernet.h>
63 #endif
64
65 static void
66 ieee80211_process_mimo(struct ieee80211_node *ni, struct ieee80211_rx_stats *rx)
67 {
68         int i;
69
70         /* Verify the required MIMO bits are set */
71         if ((rx->r_flags & (IEEE80211_R_C_CHAIN | IEEE80211_R_C_NF | IEEE80211_R_C_RSSI)) !=
72             (IEEE80211_R_C_CHAIN | IEEE80211_R_C_NF | IEEE80211_R_C_RSSI))
73                 return;
74
75         /* XXX This assumes the MIMO radios have both ctl and ext chains */
76         for (i = 0; i < MIN(rx->c_chain, IEEE80211_MAX_CHAINS); i++) {
77                 IEEE80211_RSSI_LPF(ni->ni_mimo_rssi_ctl[i], rx->c_rssi_ctl[i]);
78                 IEEE80211_RSSI_LPF(ni->ni_mimo_rssi_ext[i], rx->c_rssi_ext[i]);
79         }
80
81         /* XXX This also assumes the MIMO radios have both ctl and ext chains */
82         for(i = 0; i < MIN(rx->c_chain, IEEE80211_MAX_CHAINS); i++) {
83                 ni->ni_mimo_noise_ctl[i] = rx->c_nf_ctl[i];
84                 ni->ni_mimo_noise_ext[i] = rx->c_nf_ext[i];
85         }
86         ni->ni_mimo_chains = rx->c_chain;
87 }
88
89 int
90 ieee80211_input_mimo(struct ieee80211_node *ni, struct mbuf *m,
91     struct ieee80211_rx_stats *rx)
92 {
93         struct ieee80211_rx_stats rxs;
94
95         if (rx) {
96                 memcpy(&rxs, rx, sizeof(*rx));
97         } else {
98                 /* try to read from mbuf */
99                 bzero(&rxs, sizeof(rxs));
100                 ieee80211_get_rx_params(m, &rxs);
101         }
102
103         /* XXX should assert IEEE80211_R_NF and IEEE80211_R_RSSI are set */
104         ieee80211_process_mimo(ni, &rxs);
105
106         //return ieee80211_input(ni, m, rx->rssi, rx->nf);
107         return ni->ni_vap->iv_input(ni, m, &rxs, rxs.rssi, rxs.nf);
108 }
109
110 int
111 ieee80211_input_all(struct ieee80211com *ic, struct mbuf *m, int rssi, int nf)
112 {
113         struct ieee80211_rx_stats rx;
114
115         rx.r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI;
116         rx.nf = nf;
117         rx.rssi = rssi;
118         return ieee80211_input_mimo_all(ic, m, &rx);
119 }
120
121 int
122 ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m,
123     struct ieee80211_rx_stats *rx)
124 {
125         struct ieee80211_rx_stats rxs;
126         struct ieee80211vap *vap;
127         int type = -1;
128
129         m->m_flags |= M_BCAST;          /* NB: mark for bpf tap'ing */
130
131         if (rx) {
132                 memcpy(&rxs, rx, sizeof(*rx));
133         } else {
134                 /* try to read from mbuf */
135                 bzero(&rxs, sizeof(rxs));
136                 ieee80211_get_rx_params(m, &rxs);
137         }
138
139         /* XXX locking */
140         TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
141                 struct ieee80211_node *ni;
142                 struct mbuf *mcopy;
143
144                 /* NB: could check for IFF_UP but this is cheaper */
145                 if (vap->iv_state == IEEE80211_S_INIT)
146                         continue;
147                 /*
148                  * WDS vap's only receive directed traffic from the
149                  * station at the ``far end''.  That traffic should
150                  * be passed through the AP vap the station is associated
151                  * to--so don't spam them with mcast frames.
152                  */
153                 if (vap->iv_opmode == IEEE80211_M_WDS)
154                         continue;
155                 if (TAILQ_NEXT(vap, iv_next) != NULL) {
156                         /*
157                          * Packet contents are changed by ieee80211_decap
158                          * so do a deep copy of the packet.
159                          */
160                         mcopy = m_dup(m, M_NOWAIT);
161                         if (mcopy == NULL) {
162                                 /* XXX stat+msg */
163                                 continue;
164                         }
165                 } else {
166                         mcopy = m;
167                         m = NULL;
168                 }
169                 ni = ieee80211_ref_node(vap->iv_bss);
170                 type = ieee80211_input_mimo(ni, mcopy, &rxs);
171                 ieee80211_free_node(ni);
172         }
173         if (m != NULL)                  /* no vaps, reclaim mbuf */
174                 m_freem(m);
175         return type;
176 }
177
178 /*
179  * This function reassembles fragments.
180  *
181  * XXX should handle 3 concurrent reassemblies per-spec.
182  */
183 struct mbuf *
184 ieee80211_defrag(struct ieee80211_node *ni, struct mbuf *m, int hdrspace)
185 {
186         struct ieee80211vap *vap = ni->ni_vap;
187         struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
188         struct ieee80211_frame *lwh;
189         uint16_t rxseq;
190         uint8_t fragno;
191         uint8_t more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
192         struct mbuf *mfrag;
193
194         KASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1), ("multicast fragm?"));
195
196         rxseq = le16toh(*(uint16_t *)wh->i_seq);
197         fragno = rxseq & IEEE80211_SEQ_FRAG_MASK;
198
199         /* Quick way out, if there's nothing to defragment */
200         if (!more_frag && fragno == 0 && ni->ni_rxfrag[0] == NULL)
201                 return m;
202
203         /*
204          * Remove frag to insure it doesn't get reaped by timer.
205          */
206         if (ni->ni_table == NULL) {
207                 /*
208                  * Should never happen.  If the node is orphaned (not in
209                  * the table) then input packets should not reach here.
210                  * Otherwise, a concurrent request that yanks the table
211                  * should be blocked by other interlocking and/or by first
212                  * shutting the driver down.  Regardless, be defensive
213                  * here and just bail
214                  */
215                 /* XXX need msg+stat */
216                 m_freem(m);
217                 return NULL;
218         }
219         IEEE80211_NODE_LOCK(ni->ni_table);
220         mfrag = ni->ni_rxfrag[0];
221         ni->ni_rxfrag[0] = NULL;
222         IEEE80211_NODE_UNLOCK(ni->ni_table);
223
224         /*
225          * Validate new fragment is in order and
226          * related to the previous ones.
227          */
228         if (mfrag != NULL) {
229                 uint16_t last_rxseq;
230
231                 lwh = mtod(mfrag, struct ieee80211_frame *);
232                 last_rxseq = le16toh(*(uint16_t *)lwh->i_seq);
233                 /* NB: check seq # and frag together */
234                 if (rxseq != last_rxseq+1 ||
235                     !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
236                     !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
237                         /*
238                          * Unrelated fragment or no space for it,
239                          * clear current fragments.
240                          */
241                         m_freem(mfrag);
242                         mfrag = NULL;
243                 }
244         }
245
246         if (mfrag == NULL) {
247                 if (fragno != 0) {              /* !first fragment, discard */
248                         vap->iv_stats.is_rx_defrag++;
249                         IEEE80211_NODE_STAT(ni, rx_defrag);
250                         m_freem(m);
251                         return NULL;
252                 }
253                 mfrag = m;
254         } else {                                /* concatenate */
255                 m_adj(m, hdrspace);             /* strip header */
256 #if defined(__DragonFly__)
257                 m_cat(mfrag, m);
258                 /* NB: m_cat doesn't update the packet header */
259                 mfrag->m_pkthdr.len += m->m_pkthdr.len;
260 #else
261                 m_catpkt(mfrag, m);
262 #endif
263                 /* track last seqnum and fragno */
264                 lwh = mtod(mfrag, struct ieee80211_frame *);
265                 *(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq;
266         }
267         if (more_frag) {                        /* more to come, save */
268                 ni->ni_rxfragstamp = ticks;
269                 ni->ni_rxfrag[0] = mfrag;
270                 mfrag = NULL;
271         }
272         return mfrag;
273 }
274
275 void
276 ieee80211_deliver_data(struct ieee80211vap *vap,
277         struct ieee80211_node *ni, struct mbuf *m)
278 {
279         struct ether_header *eh = mtod(m, struct ether_header *);
280         struct ifnet *ifp = vap->iv_ifp;
281
282         /* clear driver/net80211 flags before passing up */
283         m->m_flags &= ~(M_MCAST | M_BCAST);
284 #if defined(__DragonFly__)
285 #else
286         m_clrprotoflags(m);
287 #endif
288
289         /* NB: see hostap_deliver_data, this path doesn't handle hostap */
290         KASSERT(vap->iv_opmode != IEEE80211_M_HOSTAP, ("gack, hostap"));
291         /*
292          * Do accounting.
293          */
294         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
295         IEEE80211_NODE_STAT(ni, rx_data);
296         IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
297         if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
298                 m->m_flags |= M_MCAST;          /* XXX M_BCAST? */
299                 IEEE80211_NODE_STAT(ni, rx_mcast);
300         } else
301                 IEEE80211_NODE_STAT(ni, rx_ucast);
302         m->m_pkthdr.rcvif = ifp;
303
304         if (ni->ni_vlan != 0) {
305                 /* attach vlan tag */
306 #if defined(__DragonFly__)
307                 m->m_pkthdr.ether_vlantag = ni->ni_vlan;
308 #else
309                 m->m_pkthdr.ether_vtag = ni->ni_vlan;
310 #endif
311                 m->m_flags |= M_VLANTAG;
312         }
313 #if defined(__DragonFly__)
314         ifp->if_input(ifp, m, NULL, -1);
315 #else
316         ifp->if_input(ifp, m);
317 #endif
318 }
319
320 struct mbuf *
321 ieee80211_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen)
322 {
323         struct ieee80211_qosframe_addr4 wh;
324         struct ether_header *eh;
325         struct llc *llc;
326
327         KASSERT(hdrlen <= sizeof(wh),
328             ("hdrlen %d > max %zd", hdrlen, sizeof(wh)));
329
330         if (m->m_len < hdrlen + sizeof(*llc) &&
331             (m = m_pullup(m, hdrlen + sizeof(*llc))) == NULL) {
332                 vap->iv_stats.is_rx_tooshort++;
333                 /* XXX msg */
334                 return NULL;
335         }
336         memcpy(&wh, mtod(m, caddr_t), hdrlen);
337         llc = (struct llc *)(mtod(m, caddr_t) + hdrlen);
338         if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
339             llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
340             llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0 &&
341             /* NB: preserve AppleTalk frames that have a native SNAP hdr */
342             !(llc->llc_snap.ether_type == htons(ETHERTYPE_AARP) ||
343               llc->llc_snap.ether_type == htons(ETHERTYPE_IPX))) {
344                 m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
345                 llc = NULL;
346         } else {
347                 m_adj(m, hdrlen - sizeof(*eh));
348         }
349         eh = mtod(m, struct ether_header *);
350         switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
351         case IEEE80211_FC1_DIR_NODS:
352                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
353                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
354                 break;
355         case IEEE80211_FC1_DIR_TODS:
356                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
357                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
358                 break;
359         case IEEE80211_FC1_DIR_FROMDS:
360                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
361                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
362                 break;
363         case IEEE80211_FC1_DIR_DSTODS:
364                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
365                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr4);
366                 break;
367         }
368 #ifndef __NO_STRICT_ALIGNMENT
369         if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) {
370                 m = ieee80211_realign(vap, m, sizeof(*eh));
371                 if (m == NULL)
372                         return NULL;
373         }
374 #endif /* !__NO_STRICT_ALIGNMENT */
375         if (llc != NULL) {
376                 eh = mtod(m, struct ether_header *);
377                 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
378         }
379         return m;
380 }
381
382 /*
383  * Decap a frame encapsulated in a fast-frame/A-MSDU.
384  */
385 struct mbuf *
386 ieee80211_decap1(struct mbuf *m, int *framelen)
387 {
388 #define FF_LLC_SIZE     (sizeof(struct ether_header) + sizeof(struct llc))
389         struct ether_header *eh;
390         struct llc *llc;
391
392         /*
393          * The frame has an 802.3 header followed by an 802.2
394          * LLC header.  The encapsulated frame length is in the
395          * first header type field; save that and overwrite it 
396          * with the true type field found in the second.  Then
397          * copy the 802.3 header up to where it belongs and
398          * adjust the mbuf contents to remove the void.
399          */
400         if (m->m_len < FF_LLC_SIZE && (m = m_pullup(m, FF_LLC_SIZE)) == NULL)
401                 return NULL;
402         eh = mtod(m, struct ether_header *);    /* 802.3 header is first */
403         llc = (struct llc *)&eh[1];             /* 802.2 header follows */
404         *framelen = ntohs(eh->ether_type)       /* encap'd frame size */
405                   + sizeof(struct ether_header) - sizeof(struct llc);
406         eh->ether_type = llc->llc_un.type_snap.ether_type;
407         ovbcopy(eh, mtod(m, uint8_t *) + sizeof(struct llc),
408                 sizeof(struct ether_header));
409         m_adj(m, sizeof(struct llc));
410         return m;
411 #undef FF_LLC_SIZE
412 }
413
414 /*
415  * Install received rate set information in the node's state block.
416  */
417 int
418 ieee80211_setup_rates(struct ieee80211_node *ni,
419         const uint8_t *rates, const uint8_t *xrates, int flags)
420 {
421         struct ieee80211vap *vap = ni->ni_vap;
422         struct ieee80211_rateset *rs = &ni->ni_rates;
423
424         memset(rs, 0, sizeof(*rs));
425         rs->rs_nrates = rates[1];
426         memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
427         if (xrates != NULL) {
428                 uint8_t nxrates;
429                 /*
430                  * Tack on 11g extended supported rate element.
431                  */
432                 nxrates = xrates[1];
433                 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
434                         nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
435                         IEEE80211_NOTE(vap, IEEE80211_MSG_XRATE, ni,
436                             "extended rate set too large; only using "
437                             "%u of %u rates", nxrates, xrates[1]);
438                         vap->iv_stats.is_rx_rstoobig++;
439                 }
440                 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
441                 rs->rs_nrates += nxrates;
442         }
443         return ieee80211_fix_rate(ni, rs, flags);
444 }
445
446 /*
447  * Send a management frame error response to the specified
448  * station.  If ni is associated with the station then use
449  * it; otherwise allocate a temporary node suitable for
450  * transmitting the frame and then free the reference so
451  * it will go away as soon as the frame has been transmitted.
452  */
453 void
454 ieee80211_send_error(struct ieee80211_node *ni,
455         const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg)
456 {
457         struct ieee80211vap *vap = ni->ni_vap;
458         int istmp;
459
460         if (ni == vap->iv_bss) {
461                 if (vap->iv_state != IEEE80211_S_RUN) {
462                         /*
463                          * XXX hack until we get rid of this routine.
464                          * We can be called prior to the vap reaching
465                          * run state under certain conditions in which
466                          * case iv_bss->ni_chan will not be setup.
467                          * Check for this explicitly and and just ignore
468                          * the request.
469                          */
470                         return;
471                 }
472                 ni = ieee80211_tmp_node(vap, mac);
473                 if (ni == NULL) {
474                         /* XXX msg */
475                         return;
476                 }
477                 istmp = 1;
478         } else
479                 istmp = 0;
480         IEEE80211_SEND_MGMT(ni, subtype, arg);
481         if (istmp)
482                 ieee80211_free_node(ni);
483 }
484
485 int
486 ieee80211_alloc_challenge(struct ieee80211_node *ni)
487 {
488         if (ni->ni_challenge == NULL)
489 #if defined(__DragonFly__)
490                 ni->ni_challenge = (uint32_t *) kmalloc(IEEE80211_CHALLENGE_LEN,
491                     M_80211_NODE, M_INTWAIT);
492 #else
493                 ni->ni_challenge = (uint32_t *)
494                     IEEE80211_MALLOC(IEEE80211_CHALLENGE_LEN,
495                         M_80211_NODE, IEEE80211_M_NOWAIT);
496 #endif
497         if (ni->ni_challenge == NULL) {
498                 IEEE80211_NOTE(ni->ni_vap,
499                     IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni,
500                     "%s", "shared key challenge alloc failed");
501                 /* XXX statistic */
502         }
503         return (ni->ni_challenge != NULL);
504 }
505
506 /*
507  * Parse a Beacon or ProbeResponse frame and return the
508  * useful information in an ieee80211_scanparams structure.
509  * Status is set to 0 if no problems were found; otherwise
510  * a bitmask of IEEE80211_BPARSE_* items is returned that
511  * describes the problems detected.
512  */
513 int
514 ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
515         struct ieee80211_channel *rxchan, struct ieee80211_scanparams *scan)
516 {
517         struct ieee80211vap *vap = ni->ni_vap;
518         struct ieee80211com *ic = ni->ni_ic;
519         struct ieee80211_frame *wh;
520         uint8_t *frm, *efrm;
521
522         wh = mtod(m, struct ieee80211_frame *);
523         frm = (uint8_t *)&wh[1];
524         efrm = mtod(m, uint8_t *) + m->m_len;
525         scan->status = 0;
526         /*
527          * beacon/probe response frame format
528          *      [8] time stamp
529          *      [2] beacon interval
530          *      [2] capability information
531          *      [tlv] ssid
532          *      [tlv] supported rates
533          *      [tlv] country information
534          *      [tlv] channel switch announcement (CSA)
535          *      [tlv] parameter set (FH/DS)
536          *      [tlv] erp information
537          *      [tlv] extended supported rates
538          *      [tlv] WME
539          *      [tlv] WPA or RSN
540          *      [tlv] HT capabilities
541          *      [tlv] HT information
542          *      [tlv] Atheros capabilities
543          *      [tlv] Mesh ID
544          *      [tlv] Mesh Configuration
545          */
546         IEEE80211_VERIFY_LENGTH(efrm - frm, 12,
547             return (scan->status = IEEE80211_BPARSE_BADIELEN));
548         memset(scan, 0, sizeof(*scan));
549         scan->tstamp  = frm;                            frm += 8;
550         scan->bintval = le16toh(*(uint16_t *)frm);      frm += 2;
551         scan->capinfo = le16toh(*(uint16_t *)frm);      frm += 2;
552         scan->bchan = ieee80211_chan2ieee(ic, rxchan);
553         scan->chan = scan->bchan;
554         scan->ies = frm;
555         scan->ies_len = efrm - frm;
556
557         while (efrm - frm > 1) {
558                 IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2,
559                     return (scan->status = IEEE80211_BPARSE_BADIELEN));
560                 switch (*frm) {
561                 case IEEE80211_ELEMID_SSID:
562                         scan->ssid = frm;
563                         break;
564                 case IEEE80211_ELEMID_RATES:
565                         scan->rates = frm;
566                         break;
567                 case IEEE80211_ELEMID_COUNTRY:
568                         scan->country = frm;
569                         break;
570                 case IEEE80211_ELEMID_CSA:
571                         scan->csa = frm;
572                         break;
573                 case IEEE80211_ELEMID_QUIET:
574                         scan->quiet = frm;
575                         break;
576                 case IEEE80211_ELEMID_FHPARMS:
577                         if (ic->ic_phytype == IEEE80211_T_FH) {
578                                 scan->fhdwell = le16dec(&frm[2]);
579                                 scan->chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
580                                 scan->fhindex = frm[6];
581                         }
582                         break;
583                 case IEEE80211_ELEMID_DSPARMS:
584                         /*
585                          * XXX hack this since depending on phytype
586                          * is problematic for multi-mode devices.
587                          */
588                         if (ic->ic_phytype != IEEE80211_T_FH)
589                                 scan->chan = frm[2];
590                         break;
591                 case IEEE80211_ELEMID_TIM:
592                         /* XXX ATIM? */
593                         scan->tim = frm;
594                         scan->timoff = frm - mtod(m, uint8_t *);
595                         break;
596                 case IEEE80211_ELEMID_IBSSPARMS:
597                 case IEEE80211_ELEMID_CFPARMS:
598                 case IEEE80211_ELEMID_PWRCNSTR:
599                 case IEEE80211_ELEMID_BSSLOAD:
600                 case IEEE80211_ELEMID_APCHANREP:
601                         /* NB: avoid debugging complaints */
602                         break;
603                 case IEEE80211_ELEMID_XRATES:
604                         scan->xrates = frm;
605                         break;
606                 case IEEE80211_ELEMID_ERP:
607                         if (frm[1] != 1) {
608                                 IEEE80211_DISCARD_IE(vap,
609                                     IEEE80211_MSG_ELEMID, wh, "ERP",
610                                     "bad len %u", frm[1]);
611                                 vap->iv_stats.is_rx_elem_toobig++;
612                                 break;
613                         }
614                         scan->erp = frm[2] | 0x100;
615                         break;
616                 case IEEE80211_ELEMID_HTCAP:
617                         scan->htcap = frm;
618                         break;
619                 case IEEE80211_ELEMID_RSN:
620                         scan->rsn = frm;
621                         break;
622                 case IEEE80211_ELEMID_HTINFO:
623                         scan->htinfo = frm;
624                         break;
625 #ifdef IEEE80211_SUPPORT_MESH
626                 case IEEE80211_ELEMID_MESHID:
627                         scan->meshid = frm;
628                         break;
629                 case IEEE80211_ELEMID_MESHCONF:
630                         scan->meshconf = frm;
631                         break;
632 #endif
633                 /* Extended capabilities; nothing handles it for now */
634                 case IEEE80211_ELEMID_EXTCAP:
635                         break;
636                 case IEEE80211_ELEMID_VENDOR:
637                         if (iswpaoui(frm))
638                                 scan->wpa = frm;
639                         else if (iswmeparam(frm) || iswmeinfo(frm))
640                                 scan->wme = frm;
641 #ifdef IEEE80211_SUPPORT_SUPERG
642                         else if (isatherosoui(frm))
643                                 scan->ath = frm;
644 #endif
645 #ifdef IEEE80211_SUPPORT_TDMA
646                         else if (istdmaoui(frm))
647                                 scan->tdma = frm;
648 #endif
649                         else if (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT) {
650                                 /*
651                                  * Accept pre-draft HT ie's if the
652                                  * standard ones have not been seen.
653                                  */
654                                 if (ishtcapoui(frm)) {
655                                         if (scan->htcap == NULL)
656                                                 scan->htcap = frm;
657                                 } else if (ishtinfooui(frm)) {
658                                         if (scan->htinfo == NULL)
659                                                 scan->htcap = frm;
660                                 }
661                         }
662                         break;
663                 default:
664                         IEEE80211_DISCARD_IE(vap, IEEE80211_MSG_ELEMID,
665                             wh, "unhandled",
666                             "id %u, len %u", *frm, frm[1]);
667                         vap->iv_stats.is_rx_elem_unknown++;
668                         break;
669                 }
670                 frm += frm[1] + 2;
671         }
672         IEEE80211_VERIFY_ELEMENT(scan->rates, IEEE80211_RATE_MAXSIZE,
673             scan->status |= IEEE80211_BPARSE_RATES_INVALID);
674         if (scan->rates != NULL && scan->xrates != NULL) {
675                 /*
676                  * NB: don't process XRATES if RATES is missing.  This
677                  * avoids a potential null ptr deref and should be ok
678                  * as the return code will already note RATES is missing
679                  * (so callers shouldn't otherwise process the frame).
680                  */
681                 IEEE80211_VERIFY_ELEMENT(scan->xrates,
682                     IEEE80211_RATE_MAXSIZE - scan->rates[1],
683                     scan->status |= IEEE80211_BPARSE_XRATES_INVALID);
684         }
685         IEEE80211_VERIFY_ELEMENT(scan->ssid, IEEE80211_NWID_LEN,
686             scan->status |= IEEE80211_BPARSE_SSID_INVALID);
687         if (scan->chan != scan->bchan && ic->ic_phytype != IEEE80211_T_FH) {
688                 /*
689                  * Frame was received on a channel different from the
690                  * one indicated in the DS params element id;
691                  * silently discard it.
692                  *
693                  * NB: this can happen due to signal leakage.
694                  *     But we should take it for FH phy because
695                  *     the rssi value should be correct even for
696                  *     different hop pattern in FH.
697                  */
698                 IEEE80211_DISCARD(vap,
699                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
700                     wh, NULL, "for off-channel %u (bchan=%u)",
701                     scan->chan, scan->bchan);
702                 vap->iv_stats.is_rx_chanmismatch++;
703                 scan->status |= IEEE80211_BPARSE_OFFCHAN;
704         }
705         if (!(IEEE80211_BINTVAL_MIN <= scan->bintval &&
706               scan->bintval <= IEEE80211_BINTVAL_MAX)) {
707                 IEEE80211_DISCARD(vap,
708                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
709                     wh, NULL, "bogus beacon interval (%d TU)",
710                     (int) scan->bintval);
711                 vap->iv_stats.is_rx_badbintval++;
712                 scan->status |= IEEE80211_BPARSE_BINTVAL_INVALID;
713         }
714         if (scan->country != NULL) {
715                 /*
716                  * Validate we have at least enough data to extract
717                  * the country code.  Not sure if we should return an
718                  * error instead of discarding the IE; consider this
719                  * being lenient as we don't depend on the data for
720                  * correct operation.
721                  */
722                 IEEE80211_VERIFY_LENGTH(scan->country[1], 3 * sizeof(uint8_t),
723                     scan->country = NULL);
724         }
725         if (scan->csa != NULL) {
726                 /*
727                  * Validate Channel Switch Announcement; this must
728                  * be the correct length or we toss the frame.
729                  */
730                 IEEE80211_VERIFY_LENGTH(scan->csa[1], 3 * sizeof(uint8_t),
731                     scan->status |= IEEE80211_BPARSE_CSA_INVALID);
732         }
733         /*
734          * Process HT ie's.  This is complicated by our
735          * accepting both the standard ie's and the pre-draft
736          * vendor OUI ie's that some vendors still use/require.
737          */
738         if (scan->htcap != NULL) {
739                 IEEE80211_VERIFY_LENGTH(scan->htcap[1],
740                      scan->htcap[0] == IEEE80211_ELEMID_VENDOR ?
741                          4 + sizeof(struct ieee80211_ie_htcap)-2 :
742                          sizeof(struct ieee80211_ie_htcap)-2,
743                      scan->htcap = NULL);
744         }
745         if (scan->htinfo != NULL) {
746                 IEEE80211_VERIFY_LENGTH(scan->htinfo[1],
747                      scan->htinfo[0] == IEEE80211_ELEMID_VENDOR ?
748                          4 + sizeof(struct ieee80211_ie_htinfo)-2 :
749                          sizeof(struct ieee80211_ie_htinfo)-2,
750                      scan->htinfo = NULL);
751         }
752         return scan->status;
753 }
754
755 /*
756  * Parse an Action frame.  Return 0 on success, non-zero on failure.
757  */
758 int
759 ieee80211_parse_action(struct ieee80211_node *ni, struct mbuf *m)
760 {
761         struct ieee80211vap *vap = ni->ni_vap;
762         const struct ieee80211_action *ia;
763         struct ieee80211_frame *wh;
764         uint8_t *frm, *efrm;
765
766         /*
767          * action frame format:
768          *      [1] category
769          *      [1] action
770          *      [tlv] parameters
771          */
772         wh = mtod(m, struct ieee80211_frame *);
773         frm = (u_int8_t *)&wh[1];
774         efrm = mtod(m, u_int8_t *) + m->m_len;
775         IEEE80211_VERIFY_LENGTH(efrm - frm,
776                 sizeof(struct ieee80211_action), return EINVAL);
777         ia = (const struct ieee80211_action *) frm;
778
779         vap->iv_stats.is_rx_action++;
780         IEEE80211_NODE_STAT(ni, rx_action);
781
782         /* verify frame payloads but defer processing */
783         switch (ia->ia_category) {
784         case IEEE80211_ACTION_CAT_BA:
785                 switch (ia->ia_action) {
786                 case IEEE80211_ACTION_BA_ADDBA_REQUEST:
787                         IEEE80211_VERIFY_LENGTH(efrm - frm,
788                             sizeof(struct ieee80211_action_ba_addbarequest),
789                             return EINVAL);
790                         break;
791                 case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
792                         IEEE80211_VERIFY_LENGTH(efrm - frm,
793                             sizeof(struct ieee80211_action_ba_addbaresponse),
794                             return EINVAL);
795                         break;
796                 case IEEE80211_ACTION_BA_DELBA:
797                         IEEE80211_VERIFY_LENGTH(efrm - frm,
798                             sizeof(struct ieee80211_action_ba_delba),
799                             return EINVAL);
800                         break;
801                 }
802                 break;
803         case IEEE80211_ACTION_CAT_HT:
804                 switch (ia->ia_action) {
805                 case IEEE80211_ACTION_HT_TXCHWIDTH:
806                         IEEE80211_VERIFY_LENGTH(efrm - frm,
807                             sizeof(struct ieee80211_action_ht_txchwidth),
808                             return EINVAL);
809                         break;
810                 case IEEE80211_ACTION_HT_MIMOPWRSAVE:
811                         IEEE80211_VERIFY_LENGTH(efrm - frm,
812                             sizeof(struct ieee80211_action_ht_mimopowersave),
813                             return EINVAL);
814                         break;
815                 }
816                 break;
817 #ifdef IEEE80211_SUPPORT_MESH
818         case IEEE80211_ACTION_CAT_MESH:
819                 switch (ia->ia_action) {
820                 case IEEE80211_ACTION_MESH_LMETRIC:
821                         /*
822                          * XXX: verification is true only if we are using
823                          * Airtime link metric (default)
824                          */
825                         IEEE80211_VERIFY_LENGTH(efrm - frm,
826                             sizeof(struct ieee80211_meshlmetric_ie),
827                             return EINVAL);
828                         break;
829                 case IEEE80211_ACTION_MESH_HWMP:
830                         /* verify something */
831                         break;
832                 case IEEE80211_ACTION_MESH_GANN:
833                         IEEE80211_VERIFY_LENGTH(efrm - frm,
834                             sizeof(struct ieee80211_meshgann_ie),
835                             return EINVAL);
836                         break;
837                 case IEEE80211_ACTION_MESH_CC:
838                 case IEEE80211_ACTION_MESH_MCCA_SREQ:
839                 case IEEE80211_ACTION_MESH_MCCA_SREP:
840                 case IEEE80211_ACTION_MESH_MCCA_AREQ:
841                 case IEEE80211_ACTION_MESH_MCCA_ADVER:
842                 case IEEE80211_ACTION_MESH_MCCA_TRDOWN:
843                 case IEEE80211_ACTION_MESH_TBTT_REQ:
844                 case IEEE80211_ACTION_MESH_TBTT_RES:
845                         /* reject these early on, not implemented */
846                         IEEE80211_DISCARD(vap,
847                             IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
848                             wh, NULL, "not implemented yet, act=0x%02X",
849                             ia->ia_action);
850                         return EINVAL;
851                 }
852                 break;
853         case IEEE80211_ACTION_CAT_SELF_PROT:
854                 /* If TA or RA group address discard silently */
855                 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
856                         IEEE80211_IS_MULTICAST(wh->i_addr2))
857                         return EINVAL;
858                 /*
859                  * XXX: Should we verify complete length now or it is
860                  * to varying in sizes?
861                  */
862                 switch (ia->ia_action) {
863                 case IEEE80211_ACTION_MESHPEERING_CONFIRM:
864                 case IEEE80211_ACTION_MESHPEERING_CLOSE:
865                         /* is not a peering candidate (yet) */
866                         if (ni == vap->iv_bss)
867                                 return EINVAL;
868                         break;
869                 }
870                 break;
871 #endif
872         }
873         return 0;
874 }
875
876 #ifdef IEEE80211_DEBUG
877 /*
878  * Debugging support.
879  */
880 void
881 ieee80211_ssid_mismatch(struct ieee80211vap *vap, const char *tag,
882         uint8_t mac[IEEE80211_ADDR_LEN], uint8_t *ssid)
883 {
884         kprintf("[%s] discard %s frame, ssid mismatch: ",
885                 ether_sprintf(mac), tag);
886         ieee80211_print_essid(ssid + 2, ssid[1]);
887         kprintf("\n");
888 }
889
890 /*
891  * Return the bssid of a frame.
892  */
893 static const uint8_t *
894 ieee80211_getbssid(const struct ieee80211vap *vap,
895         const struct ieee80211_frame *wh)
896 {
897         if (vap->iv_opmode == IEEE80211_M_STA)
898                 return wh->i_addr2;
899         if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != IEEE80211_FC1_DIR_NODS)
900                 return wh->i_addr1;
901         if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
902                 return wh->i_addr1;
903         return wh->i_addr3;
904 }
905
906 #include <machine/stdarg.h>
907
908 void
909 ieee80211_note(const struct ieee80211vap *vap, const char *fmt, ...)
910 {
911         char buf[128];          /* XXX */
912 #if defined(__DragonFly__)
913         osdep_va_list ap;
914
915         osdep_va_start(ap, fmt);
916         kvsnprintf(buf, sizeof(buf), fmt, ap);
917         osdep_va_end(ap);
918 #else
919         va_list ap;
920
921         va_start(ap, fmt);
922         vsnprintf(buf, sizeof(buf), fmt, ap);
923         va_end(ap);
924 #endif
925
926         if_printf(vap->iv_ifp, "%s", buf);      /* NB: no \n */
927 }
928
929 void
930 ieee80211_note_frame(const struct ieee80211vap *vap,
931         const struct ieee80211_frame *wh,
932         const char *fmt, ...)
933 {
934         char buf[128];          /* XXX */
935 #if defined(__DragonFly__)
936         osdep_va_list ap;
937
938         osdep_va_start(ap, fmt);
939         kvsnprintf(buf, sizeof(buf), fmt, ap);
940         osdep_va_end(ap);
941 #else
942         va_list ap;
943
944         va_start(ap, fmt);
945         vsnprintf(buf, sizeof(buf), fmt, ap);
946         va_end(ap);
947 #endif
948         if_printf(vap->iv_ifp, "[%s] %s\n",
949                 ether_sprintf(ieee80211_getbssid(vap, wh)), buf);
950 }
951
952 void
953 ieee80211_note_mac(const struct ieee80211vap *vap,
954         const uint8_t mac[IEEE80211_ADDR_LEN],
955         const char *fmt, ...)
956 {
957         char buf[128];          /* XXX */
958 #if defined(__DragonFly__)
959         osdep_va_list ap;
960
961         osdep_va_start(ap, fmt);
962         kvsnprintf(buf, sizeof(buf), fmt, ap);
963         osdep_va_end(ap);
964 #else
965         va_list ap;
966
967         va_start(ap, fmt);
968         vsnprintf(buf, sizeof(buf), fmt, ap);
969         va_end(ap);
970 #endif
971         if_printf(vap->iv_ifp, "[%s] %s\n", ether_sprintf(mac), buf);
972 }
973
974 void
975 ieee80211_discard_frame(const struct ieee80211vap *vap,
976         const struct ieee80211_frame *wh,
977         const char *type, const char *fmt, ...)
978 {
979 #if defined(__DragonFly__)
980         osdep_va_list ap;
981
982         if_printf(vap->iv_ifp, "[%s] discard ",
983                 ether_sprintf(ieee80211_getbssid(vap, wh)));
984         kprintf("%s frame, ", type != NULL ? type :
985             ieee80211_mgt_subtype_name(wh->i_fc[0]));
986         osdep_va_start(ap, fmt);
987         kvprintf(fmt, ap);
988         osdep_va_end(ap);
989 #else
990         va_list ap;
991
992         if_printf(vap->iv_ifp, "[%s] discard ",
993                 ether_sprintf(ieee80211_getbssid(vap, wh)));
994         printf("%s frame, ", type != NULL ? type :
995             ieee80211_mgt_subtype_name(wh->i_fc[0]));
996         va_start(ap, fmt);
997         vprintf(fmt, ap);
998         va_end(ap);
999 #endif
1000         kprintf("\n");
1001 }
1002
1003 void
1004 ieee80211_discard_ie(const struct ieee80211vap *vap,
1005         const struct ieee80211_frame *wh,
1006         const char *type, const char *fmt, ...)
1007 {
1008         osdep_va_list ap;
1009
1010 #if defined(__DragonFly__)
1011         if_printf(vap->iv_ifp, "[%s] discard ",
1012                 ether_sprintf(ieee80211_getbssid(vap, wh)));
1013         if (type != NULL)
1014                 kprintf("%s information element, ", type);
1015         else
1016                 kprintf("information element, ");
1017         osdep_va_start(ap, fmt);
1018         kvprintf(fmt, ap);
1019         osdep_va_end(ap);
1020         kprintf("\n");
1021 #else
1022         if_printf(vap->iv_ifp, "[%s] discard ",
1023                 ether_sprintf(ieee80211_getbssid(vap, wh)));
1024         if (type != NULL)
1025                 printf("%s information element, ", type);
1026         else
1027                 printf("information element, ");
1028         va_start(ap, fmt);
1029         vprintf(fmt, ap);
1030         va_end(ap);
1031         printf("\n");
1032 #endif
1033 }
1034
1035 void
1036 ieee80211_discard_mac(const struct ieee80211vap *vap,
1037         const uint8_t mac[IEEE80211_ADDR_LEN],
1038         const char *type, const char *fmt, ...)
1039 {
1040 #if defined(__DragonFly__)
1041         osdep_va_list ap;
1042
1043         if_printf(vap->iv_ifp, "[%s] discard ", ether_sprintf(mac));
1044         if (type != NULL)
1045                 kprintf("%s frame, ", type);
1046         else
1047                 kprintf("frame, ");
1048         osdep_va_start(ap, fmt);
1049         kvprintf(fmt, ap);
1050         osdep_va_end(ap);
1051 #else
1052         va_list ap;
1053
1054         if_printf(vap->iv_ifp, "[%s] discard ", ether_sprintf(mac));
1055         if (type != NULL)
1056                 printf("%s frame, ", type);
1057         else
1058                 printf("frame, ");
1059         va_start(ap, fmt);
1060         vprintf(fmt, ap);
1061         va_end(ap);
1062 #endif
1063         kprintf("\n");
1064 }
1065 #endif /* IEEE80211_DEBUG */