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