xref: /dragonfly/contrib/tcpdump/print-802_11.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
1 /*
2  * Copyright (c) 2001
3  *        Fortress Technologies, Inc.  All rights reserved.
4  *      Charlie Lenahan (clenahan@fortresstech.com)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that: (1) source code distributions
8  * retain the above copyright notice and this paragraph in its entirety, (2)
9  * distributions including binary code include the above copyright notice and
10  * this paragraph in its entirety in the documentation or other materials
11  * provided with the distribution, and (3) all advertising materials mentioning
12  * features or use of this software display the following acknowledgement:
13  * ``This product includes software developed by the University of California,
14  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15  * the University nor the names of its contributors may be used to endorse
16  * or promote products derived from this software without specific prior
17  * written permission.
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22 
23 /* \summary: IEEE 802.11 printer */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include "netdissect-stdinc.h"
30 
31 #include <string.h>
32 
33 #include "netdissect.h"
34 #include "addrtoname.h"
35 
36 #include "extract.h"
37 
38 #include "cpack.h"
39 
40 
41 /* Lengths of 802.11 header components. */
42 #define   IEEE802_11_FC_LEN             2
43 #define   IEEE802_11_DUR_LEN            2
44 #define   IEEE802_11_DA_LEN             6
45 #define   IEEE802_11_SA_LEN             6
46 #define   IEEE802_11_BSSID_LEN                    6
47 #define   IEEE802_11_RA_LEN             6
48 #define   IEEE802_11_TA_LEN             6
49 #define   IEEE802_11_ADDR1_LEN                    6
50 #define   IEEE802_11_SEQ_LEN            2
51 #define   IEEE802_11_CTL_LEN            2
52 #define   IEEE802_11_CARRIED_FC_LEN     2
53 #define   IEEE802_11_HT_CONTROL_LEN     4
54 #define   IEEE802_11_IV_LEN             3
55 #define   IEEE802_11_KID_LEN            1
56 
57 /* Frame check sequence length. */
58 #define   IEEE802_11_FCS_LEN            4
59 
60 /* Lengths of beacon components. */
61 #define   IEEE802_11_TSTAMP_LEN                   8
62 #define   IEEE802_11_BCNINT_LEN                   2
63 #define   IEEE802_11_CAPINFO_LEN                  2
64 #define   IEEE802_11_LISTENINT_LEN      2
65 
66 #define   IEEE802_11_AID_LEN            2
67 #define   IEEE802_11_STATUS_LEN                   2
68 #define   IEEE802_11_REASON_LEN                   2
69 
70 /* Length of previous AP in reassocation frame */
71 #define   IEEE802_11_AP_LEN             6
72 
73 #define   T_MGMT 0x0  /* management */
74 #define   T_CTRL 0x1  /* control */
75 #define   T_DATA 0x2 /* data */
76 #define   T_RESV 0x3  /* reserved */
77 
78 #define   ST_ASSOC_REQUEST    0x0
79 #define   ST_ASSOC_RESPONSE   0x1
80 #define   ST_REASSOC_REQUEST  0x2
81 #define   ST_REASSOC_RESPONSE 0x3
82 #define   ST_PROBE_REQUEST    0x4
83 #define   ST_PROBE_RESPONSE   0x5
84 /* RESERVED                             0x6  */
85 /* RESERVED                             0x7  */
86 #define   ST_BEACON           0x8
87 #define   ST_ATIM                       0x9
88 #define   ST_DISASSOC                   0xA
89 #define   ST_AUTH                       0xB
90 #define   ST_DEAUTH           0xC
91 #define   ST_ACTION           0xD
92 /* RESERVED                             0xE  */
93 /* RESERVED                             0xF  */
94 
95 static const struct tok st_str[] = {
96           { ST_ASSOC_REQUEST,    "Assoc Request"    },
97           { ST_ASSOC_RESPONSE,   "Assoc Response"   },
98           { ST_REASSOC_REQUEST,  "ReAssoc Request"  },
99           { ST_REASSOC_RESPONSE, "ReAssoc Response" },
100           { ST_PROBE_REQUEST,    "Probe Request"    },
101           { ST_PROBE_RESPONSE,   "Probe Response"   },
102           { ST_BEACON,           "Beacon"           },
103           { ST_ATIM,             "ATIM"             },
104           { ST_DISASSOC,         "Disassociation"   },
105           { ST_AUTH,             "Authentication"   },
106           { ST_DEAUTH,           "DeAuthentication" },
107           { ST_ACTION,           "Action"           },
108           { 0, NULL }
109 };
110 
111 #define CTRL_CONTROL_WRAPPER  0x7
112 #define   CTRL_BAR  0x8
113 #define   CTRL_BA             0x9
114 #define   CTRL_PS_POLL        0xA
115 #define   CTRL_RTS  0xB
116 #define   CTRL_CTS  0xC
117 #define   CTRL_ACK  0xD
118 #define   CTRL_CF_END         0xE
119 #define   CTRL_END_ACK        0xF
120 
121 static const struct tok ctrl_str[] = {
122           { CTRL_CONTROL_WRAPPER, "Control Wrapper" },
123           { CTRL_BAR,             "BAR"             },
124           { CTRL_BA,              "BA"              },
125           { CTRL_PS_POLL,         "Power Save-Poll" },
126           { CTRL_RTS,             "Request-To-Send" },
127           { CTRL_CTS,             "Clear-To-Send"   },
128           { CTRL_ACK,             "Acknowledgment"  },
129           { CTRL_CF_END,          "CF-End"          },
130           { CTRL_END_ACK,         "CF-End+CF-Ack"   },
131           { 0, NULL }
132 };
133 
134 #define   DATA_DATA                     0x0
135 #define   DATA_DATA_CF_ACK              0x1
136 #define   DATA_DATA_CF_POLL             0x2
137 #define   DATA_DATA_CF_ACK_POLL                   0x3
138 #define   DATA_NODATA                             0x4
139 #define   DATA_NODATA_CF_ACK            0x5
140 #define   DATA_NODATA_CF_POLL           0x6
141 #define   DATA_NODATA_CF_ACK_POLL                 0x7
142 
143 #define DATA_QOS_DATA                             0x8
144 #define DATA_QOS_DATA_CF_ACK            0x9
145 #define DATA_QOS_DATA_CF_POLL           0xA
146 #define DATA_QOS_DATA_CF_ACK_POLL       0xB
147 #define DATA_QOS_NODATA                           0xC
148 #define DATA_QOS_CF_POLL_NODATA                   0xE
149 #define DATA_QOS_CF_ACK_POLL_NODATA     0xF
150 
151 /*
152  * The subtype field of a data frame is, in effect, composed of 4 flag
153  * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
154  * any data), and QoS.
155  */
156 #define DATA_FRAME_IS_CF_ACK(x)                   ((x) & 0x01)
157 #define DATA_FRAME_IS_CF_POLL(x)        ((x) & 0x02)
158 #define DATA_FRAME_IS_NULL(x)           ((x) & 0x04)
159 #define DATA_FRAME_IS_QOS(x)            ((x) & 0x08)
160 
161 /*
162  * Bits in the frame control field.
163  */
164 #define   FC_VERSION(fc)                ((fc) & 0x3)
165 #define   FC_TYPE(fc)                   (((fc) >> 2) & 0x3)
166 #define   FC_SUBTYPE(fc)                (((fc) >> 4) & 0xF)
167 #define   FC_TO_DS(fc)                  ((fc) & 0x0100)
168 #define   FC_FROM_DS(fc)                ((fc) & 0x0200)
169 #define   FC_MORE_FLAG(fc)    ((fc) & 0x0400)
170 #define   FC_RETRY(fc)                  ((fc) & 0x0800)
171 #define   FC_POWER_MGMT(fc)   ((fc) & 0x1000)
172 #define   FC_MORE_DATA(fc)    ((fc) & 0x2000)
173 #define   FC_PROTECTED(fc)    ((fc) & 0x4000)
174 #define   FC_ORDER(fc)                  ((fc) & 0x8000)
175 
176 struct mgmt_header_t {
177           nd_uint16_t         fc;
178           nd_uint16_t         duration;
179           nd_mac_addr         da;
180           nd_mac_addr         sa;
181           nd_mac_addr         bssid;
182           nd_uint16_t         seq_ctrl;
183 };
184 
185 #define   MGMT_HDRLEN         (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
186                                IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\
187                                IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN)
188 
189 #define   CAPABILITY_ESS(cap) ((cap) & 0x0001)
190 #define   CAPABILITY_IBSS(cap)          ((cap) & 0x0002)
191 #define   CAPABILITY_CFP(cap) ((cap) & 0x0004)
192 #define   CAPABILITY_CFP_REQ(cap)       ((cap) & 0x0008)
193 #define   CAPABILITY_PRIVACY(cap)       ((cap) & 0x0010)
194 
195 struct ssid_t {
196           uint8_t             element_id;
197           uint8_t             length;
198           u_char              ssid[33];  /* 32 + 1 for null */
199 };
200 
201 struct rates_t {
202           uint8_t             element_id;
203           uint8_t             length;
204           uint8_t             rate[16];
205 };
206 
207 struct challenge_t {
208           uint8_t             element_id;
209           uint8_t             length;
210           uint8_t             text[254]; /* 1-253 + 1 for null */
211 };
212 
213 struct fh_t {
214           uint8_t             element_id;
215           uint8_t             length;
216           uint16_t  dwell_time;
217           uint8_t             hop_set;
218           uint8_t   hop_pattern;
219           uint8_t             hop_index;
220 };
221 
222 struct ds_t {
223           uint8_t             element_id;
224           uint8_t             length;
225           uint8_t             channel;
226 };
227 
228 struct cf_t {
229           uint8_t             element_id;
230           uint8_t             length;
231           uint8_t             count;
232           uint8_t             period;
233           uint16_t  max_duration;
234           uint16_t  dur_remaining;
235 };
236 
237 struct tim_t {
238           uint8_t             element_id;
239           uint8_t             length;
240           uint8_t             count;
241           uint8_t             period;
242           uint8_t             bitmap_control;
243           uint8_t             bitmap[251];
244 };
245 
246 #define   E_SSID              0
247 #define   E_RATES   1
248 #define   E_FH                2
249 #define   E_DS                3
250 #define   E_CF                4
251 #define   E_TIM               5
252 #define   E_IBSS              6
253 /* reserved                   7 */
254 /* reserved                   8 */
255 /* reserved                   9 */
256 /* reserved                   10 */
257 /* reserved                   11 */
258 /* reserved                   12 */
259 /* reserved                   13 */
260 /* reserved                   14 */
261 /* reserved                   15 */
262 /* reserved                   16 */
263 
264 #define   E_CHALLENGE         16
265 /* reserved                   17 */
266 /* reserved                   18 */
267 /* reserved                   19 */
268 /* reserved                   16 */
269 /* reserved                   16 */
270 
271 
272 struct mgmt_body_t {
273           uint8_t             timestamp[IEEE802_11_TSTAMP_LEN];
274           uint16_t  beacon_interval;
275           uint16_t  listen_interval;
276           uint16_t  status_code;
277           uint16_t  aid;
278           u_char              ap[IEEE802_11_AP_LEN];
279           uint16_t  reason_code;
280           uint16_t  auth_alg;
281           uint16_t  auth_trans_seq_num;
282           int                 challenge_present;
283           struct challenge_t  challenge;
284           uint16_t  capability_info;
285           int                 ssid_present;
286           struct ssid_t       ssid;
287           int                 rates_present;
288           struct rates_t      rates;
289           int                 ds_present;
290           struct ds_t         ds;
291           int                 cf_present;
292           struct cf_t         cf;
293           int                 fh_present;
294           struct fh_t         fh;
295           int                 tim_present;
296           struct tim_t        tim;
297 };
298 
299 struct ctrl_control_wrapper_hdr_t {
300           nd_uint16_t         fc;
301           nd_uint16_t         duration;
302           nd_mac_addr         addr1;
303           nd_uint16_t         carried_fc[IEEE802_11_CARRIED_FC_LEN];
304           nd_uint16_t         ht_control[IEEE802_11_HT_CONTROL_LEN];
305 };
306 
307 #define   CTRL_CONTROL_WRAPPER_HDRLEN   (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
308                                                    IEEE802_11_ADDR1_LEN+\
309                                                    IEEE802_11_CARRIED_FC_LEN+\
310                                                    IEEE802_11_HT_CONTROL_LEN)
311 
312 struct ctrl_rts_hdr_t {
313           nd_uint16_t         fc;
314           nd_uint16_t         duration;
315           nd_mac_addr         ra;
316           nd_mac_addr         ta;
317 };
318 
319 #define   CTRL_RTS_HDRLEN     (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
320                                IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
321 
322 struct ctrl_cts_hdr_t {
323           nd_uint16_t         fc;
324           nd_uint16_t         duration;
325           nd_mac_addr         ra;
326 };
327 
328 #define   CTRL_CTS_HDRLEN     (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
329 
330 struct ctrl_ack_hdr_t {
331           nd_uint16_t         fc;
332           nd_uint16_t         duration;
333           nd_mac_addr         ra;
334 };
335 
336 #define   CTRL_ACK_HDRLEN     (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
337 
338 struct ctrl_ps_poll_hdr_t {
339           nd_uint16_t         fc;
340           nd_uint16_t         aid;
341           nd_mac_addr         bssid;
342           nd_mac_addr         ta;
343 };
344 
345 #define   CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
346                                          IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN)
347 
348 struct ctrl_end_hdr_t {
349           nd_uint16_t         fc;
350           nd_uint16_t         duration;
351           nd_mac_addr         ra;
352           nd_mac_addr         bssid;
353 };
354 
355 #define   CTRL_END_HDRLEN     (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
356                                IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
357 
358 struct ctrl_end_ack_hdr_t {
359           nd_uint16_t         fc;
360           nd_uint16_t         duration;
361           nd_mac_addr         ra;
362           nd_mac_addr         bssid;
363 };
364 
365 #define   CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
366                                          IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
367 
368 struct ctrl_ba_hdr_t {
369           nd_uint16_t         fc;
370           nd_uint16_t         duration;
371           nd_mac_addr         ra;
372 };
373 
374 #define   CTRL_BA_HDRLEN      (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
375 
376 struct ctrl_bar_hdr_t {
377           nd_uint16_t         fc;
378           nd_uint16_t         dur;
379           nd_mac_addr         ra;
380           nd_mac_addr         ta;
381           nd_uint16_t         ctl;
382           nd_uint16_t         seq;
383 };
384 
385 #define   CTRL_BAR_HDRLEN               (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
386                                          IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\
387                                          IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN)
388 
389 struct meshcntl_t {
390           nd_uint8_t          flags;
391           nd_uint8_t          ttl;
392           nd_uint32_t         seq;
393           nd_mac_addr         addr4;
394           nd_mac_addr         addr5;
395           nd_mac_addr         addr6;
396 };
397 
398 #define   IV_IV(iv) ((iv) & 0xFFFFFF)
399 #define   IV_PAD(iv)          (((iv) >> 24) & 0x3F)
400 #define   IV_KEYID(iv)        (((iv) >> 30) & 0x03)
401 
402 #define PRINT_SSID(p) \
403           if (p.ssid_present) { \
404                     ND_PRINT(" ("); \
405                     fn_print_str(ndo, p.ssid.ssid); \
406                     ND_PRINT(")"); \
407           }
408 
409 #define PRINT_RATE(_sep, _r, _suf) \
410           ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
411 #define PRINT_RATES(p) \
412           if (p.rates_present) { \
413                     int z; \
414                     const char *sep = " ["; \
415                     for (z = 0; z < p.rates.length ; z++) { \
416                               PRINT_RATE(sep, p.rates.rate[z], \
417                                         (p.rates.rate[z] & 0x80 ? "*" : "")); \
418                               sep = " "; \
419                     } \
420                     if (p.rates.length != 0) \
421                               ND_PRINT(" Mbit]"); \
422           }
423 
424 #define PRINT_DS_CHANNEL(p) \
425           if (p.ds_present) \
426                     ND_PRINT(" CH: %u", p.ds.channel); \
427           ND_PRINT("%s", \
428               CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
429 
430 #define MAX_MCS_INDEX         76
431 
432 /*
433  * Indices are:
434  *
435  *        the MCS index (0-76);
436  *
437  *        0 for 20 MHz, 1 for 40 MHz;
438  *
439  *        0 for a long guard interval, 1 for a short guard interval.
440  */
441 static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
442           /* MCS  0  */
443           {         /* 20 Mhz */ {    6.5f,                 /* SGI */    7.2f, },
444                     /* 40 Mhz */ {   13.5f,                 /* SGI */   15.0f, },
445           },
446 
447           /* MCS  1  */
448           {         /* 20 Mhz */ {   13.0f,                 /* SGI */   14.4f, },
449                     /* 40 Mhz */ {   27.0f,                 /* SGI */   30.0f, },
450           },
451 
452           /* MCS  2  */
453           {         /* 20 Mhz */ {   19.5f,                 /* SGI */   21.7f, },
454                     /* 40 Mhz */ {   40.5f,                 /* SGI */   45.0f, },
455           },
456 
457           /* MCS  3  */
458           {         /* 20 Mhz */ {   26.0f,                 /* SGI */   28.9f, },
459                     /* 40 Mhz */ {   54.0f,                 /* SGI */   60.0f, },
460           },
461 
462           /* MCS  4  */
463           {         /* 20 Mhz */ {   39.0f,                 /* SGI */   43.3f, },
464                     /* 40 Mhz */ {   81.0f,                 /* SGI */   90.0f, },
465           },
466 
467           /* MCS  5  */
468           {         /* 20 Mhz */ {   52.0f,                 /* SGI */   57.8f, },
469                     /* 40 Mhz */ {  108.0f,                 /* SGI */  120.0f, },
470           },
471 
472           /* MCS  6  */
473           {         /* 20 Mhz */ {   58.5f,                 /* SGI */   65.0f, },
474                     /* 40 Mhz */ {  121.5f,                 /* SGI */  135.0f, },
475           },
476 
477           /* MCS  7  */
478           {         /* 20 Mhz */ {   65.0f,                 /* SGI */   72.2f, },
479                     /* 40 Mhz */ {   135.0f,      /* SGI */  150.0f, },
480           },
481 
482           /* MCS  8  */
483           {         /* 20 Mhz */ {   13.0f,                 /* SGI */   14.4f, },
484                     /* 40 Mhz */ {   27.0f,                 /* SGI */   30.0f, },
485           },
486 
487           /* MCS  9  */
488           {         /* 20 Mhz */ {   26.0f,                 /* SGI */   28.9f, },
489                     /* 40 Mhz */ {   54.0f,                 /* SGI */   60.0f, },
490           },
491 
492           /* MCS 10  */
493           {         /* 20 Mhz */ {   39.0f,                 /* SGI */   43.3f, },
494                     /* 40 Mhz */ {   81.0f,                 /* SGI */   90.0f, },
495           },
496 
497           /* MCS 11  */
498           {         /* 20 Mhz */ {   52.0f,                 /* SGI */   57.8f, },
499                     /* 40 Mhz */ {  108.0f,                 /* SGI */  120.0f, },
500           },
501 
502           /* MCS 12  */
503           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
504                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
505           },
506 
507           /* MCS 13  */
508           {         /* 20 Mhz */ {  104.0f,                 /* SGI */  115.6f, },
509                     /* 40 Mhz */ {  216.0f,                 /* SGI */  240.0f, },
510           },
511 
512           /* MCS 14  */
513           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
514                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
515           },
516 
517           /* MCS 15  */
518           {         /* 20 Mhz */ {  130.0f,                 /* SGI */  144.4f, },
519                     /* 40 Mhz */ {  270.0f,                 /* SGI */  300.0f, },
520           },
521 
522           /* MCS 16  */
523           {         /* 20 Mhz */ {   19.5f,                 /* SGI */   21.7f, },
524                     /* 40 Mhz */ {   40.5f,                 /* SGI */   45.0f, },
525           },
526 
527           /* MCS 17  */
528           {         /* 20 Mhz */ {   39.0f,                 /* SGI */   43.3f, },
529                     /* 40 Mhz */ {   81.0f,                 /* SGI */   90.0f, },
530           },
531 
532           /* MCS 18  */
533           {         /* 20 Mhz */ {   58.5f,                 /* SGI */   65.0f, },
534                     /* 40 Mhz */ {  121.5f,                 /* SGI */  135.0f, },
535           },
536 
537           /* MCS 19  */
538           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
539                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
540           },
541 
542           /* MCS 20  */
543           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
544                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
545           },
546 
547           /* MCS 21  */
548           {         /* 20 Mhz */ {  156.0f,                 /* SGI */  173.3f, },
549                     /* 40 Mhz */ {  324.0f,                 /* SGI */  360.0f, },
550           },
551 
552           /* MCS 22  */
553           {         /* 20 Mhz */ {  175.5f,                 /* SGI */  195.0f, },
554                     /* 40 Mhz */ {  364.5f,                 /* SGI */  405.0f, },
555           },
556 
557           /* MCS 23  */
558           {         /* 20 Mhz */ {  195.0f,                 /* SGI */  216.7f, },
559                     /* 40 Mhz */ {  405.0f,                 /* SGI */  450.0f, },
560           },
561 
562           /* MCS 24  */
563           {         /* 20 Mhz */ {   26.0f,                 /* SGI */   28.9f, },
564                     /* 40 Mhz */ {   54.0f,                 /* SGI */   60.0f, },
565           },
566 
567           /* MCS 25  */
568           {         /* 20 Mhz */ {   52.0f,                 /* SGI */   57.8f, },
569                     /* 40 Mhz */ {  108.0f,                 /* SGI */  120.0f, },
570           },
571 
572           /* MCS 26  */
573           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
574                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
575           },
576 
577           /* MCS 27  */
578           {         /* 20 Mhz */ {  104.0f,                 /* SGI */  115.6f, },
579                     /* 40 Mhz */ {  216.0f,                 /* SGI */  240.0f, },
580           },
581 
582           /* MCS 28  */
583           {         /* 20 Mhz */ {  156.0f,                 /* SGI */  173.3f, },
584                     /* 40 Mhz */ {  324.0f,                 /* SGI */  360.0f, },
585           },
586 
587           /* MCS 29  */
588           {         /* 20 Mhz */ {  208.0f,                 /* SGI */  231.1f, },
589                     /* 40 Mhz */ {  432.0f,                 /* SGI */  480.0f, },
590           },
591 
592           /* MCS 30  */
593           {         /* 20 Mhz */ {  234.0f,                 /* SGI */  260.0f, },
594                     /* 40 Mhz */ {  486.0f,                 /* SGI */  540.0f, },
595           },
596 
597           /* MCS 31  */
598           {         /* 20 Mhz */ {  260.0f,                 /* SGI */  288.9f, },
599                     /* 40 Mhz */ {  540.0f,                 /* SGI */  600.0f, },
600           },
601 
602           /* MCS 32  */
603           {         /* 20 Mhz */ {    0.0f,                 /* SGI */    0.0f, }, /* not valid */
604                     /* 40 Mhz */ {    6.0f,                 /* SGI */    6.7f, },
605           },
606 
607           /* MCS 33  */
608           {         /* 20 Mhz */ {   39.0f,                 /* SGI */   43.3f, },
609                     /* 40 Mhz */ {   81.0f,                 /* SGI */   90.0f, },
610           },
611 
612           /* MCS 34  */
613           {         /* 20 Mhz */ {   52.0f,                 /* SGI */   57.8f, },
614                     /* 40 Mhz */ {  108.0f,                 /* SGI */  120.0f, },
615           },
616 
617           /* MCS 35  */
618           {         /* 20 Mhz */ {   65.0f,                 /* SGI */   72.2f, },
619                     /* 40 Mhz */ {  135.0f,                 /* SGI */  150.0f, },
620           },
621 
622           /* MCS 36  */
623           {         /* 20 Mhz */ {   58.5f,                 /* SGI */   65.0f, },
624                     /* 40 Mhz */ {  121.5f,                 /* SGI */  135.0f, },
625           },
626 
627           /* MCS 37  */
628           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
629                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
630           },
631 
632           /* MCS 38  */
633           {         /* 20 Mhz */ {   97.5f,                 /* SGI */  108.3f, },
634                     /* 40 Mhz */ {  202.5f,                 /* SGI */  225.0f, },
635           },
636 
637           /* MCS 39  */
638           {         /* 20 Mhz */ {   52.0f,                 /* SGI */   57.8f, },
639                     /* 40 Mhz */ {  108.0f,                 /* SGI */  120.0f, },
640           },
641 
642           /* MCS 40  */
643           {         /* 20 Mhz */ {   65.0f,                 /* SGI */   72.2f, },
644                     /* 40 Mhz */ {  135.0f,                 /* SGI */  150.0f, },
645           },
646 
647           /* MCS 41  */
648           {         /* 20 Mhz */ {   65.0f,                 /* SGI */   72.2f, },
649                     /* 40 Mhz */ {  135.0f,                 /* SGI */  150.0f, },
650           },
651 
652           /* MCS 42  */
653           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
654                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
655           },
656 
657           /* MCS 43  */
658           {         /* 20 Mhz */ {   91.0f,                 /* SGI */  101.1f, },
659                     /* 40 Mhz */ {  189.0f,                 /* SGI */  210.0f, },
660           },
661 
662           /* MCS 44  */
663           {         /* 20 Mhz */ {   91.0f,                 /* SGI */  101.1f, },
664                     /* 40 Mhz */ {  189.0f,                 /* SGI */  210.0f, },
665           },
666 
667           /* MCS 45  */
668           {         /* 20 Mhz */ {  104.0f,                 /* SGI */  115.6f, },
669                     /* 40 Mhz */ {  216.0f,                 /* SGI */  240.0f, },
670           },
671 
672           /* MCS 46  */
673           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
674                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
675           },
676 
677           /* MCS 47  */
678           {         /* 20 Mhz */ {   97.5f,                 /* SGI */  108.3f, },
679                     /* 40 Mhz */ {  202.5f,                 /* SGI */  225.0f, },
680           },
681 
682           /* MCS 48  */
683           {         /* 20 Mhz */ {   97.5f,                 /* SGI */  108.3f, },
684                     /* 40 Mhz */ {  202.5f,                 /* SGI */  225.0f, },
685           },
686 
687           /* MCS 49  */
688           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
689                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
690           },
691 
692           /* MCS 50  */
693           {         /* 20 Mhz */ {  136.5f,                 /* SGI */  151.7f, },
694                     /* 40 Mhz */ {  283.5f,                 /* SGI */  315.0f, },
695           },
696 
697           /* MCS 51  */
698           {         /* 20 Mhz */ {  136.5f,                 /* SGI */  151.7f, },
699                     /* 40 Mhz */ {  283.5f,                 /* SGI */  315.0f, },
700           },
701 
702           /* MCS 52  */
703           {         /* 20 Mhz */ {  156.0f,                 /* SGI */  173.3f, },
704                     /* 40 Mhz */ {  324.0f,                 /* SGI */  360.0f, },
705           },
706 
707           /* MCS 53  */
708           {         /* 20 Mhz */ {   65.0f,                 /* SGI */   72.2f, },
709                     /* 40 Mhz */ {  135.0f,                 /* SGI */  150.0f, },
710           },
711 
712           /* MCS 54  */
713           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
714                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
715           },
716 
717           /* MCS 55  */
718           {         /* 20 Mhz */ {   91.0f,                 /* SGI */  101.1f, },
719                     /* 40 Mhz */ {  189.0f,                 /* SGI */  210.0f, },
720           },
721 
722           /* MCS 56  */
723           {         /* 20 Mhz */ {   78.0f,                 /* SGI */   86.7f, },
724                     /* 40 Mhz */ {  162.0f,                 /* SGI */  180.0f, },
725           },
726 
727           /* MCS 57  */
728           {         /* 20 Mhz */ {   91.0f,                 /* SGI */  101.1f, },
729                     /* 40 Mhz */ {  189.0f,                 /* SGI */  210.0f, },
730           },
731 
732           /* MCS 58  */
733           {         /* 20 Mhz */ {  104.0f,                 /* SGI */  115.6f, },
734                     /* 40 Mhz */ {  216.0f,                 /* SGI */  240.0f, },
735           },
736 
737           /* MCS 59  */
738           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
739                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
740           },
741 
742           /* MCS 60  */
743           {         /* 20 Mhz */ {  104.0f,                 /* SGI */  115.6f, },
744                     /* 40 Mhz */ {  216.0f,                 /* SGI */  240.0f, },
745           },
746 
747           /* MCS 61  */
748           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
749                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
750           },
751 
752           /* MCS 62  */
753           {         /* 20 Mhz */ {  130.0f,                 /* SGI */  144.4f, },
754                     /* 40 Mhz */ {  270.0f,                 /* SGI */  300.0f, },
755           },
756 
757           /* MCS 63  */
758           {         /* 20 Mhz */ {  130.0f,                 /* SGI */  144.4f, },
759                     /* 40 Mhz */ {  270.0f,                 /* SGI */  300.0f, },
760           },
761 
762           /* MCS 64  */
763           {         /* 20 Mhz */ {  143.0f,                 /* SGI */  158.9f, },
764                     /* 40 Mhz */ {  297.0f,                 /* SGI */  330.0f, },
765           },
766 
767           /* MCS 65  */
768           {         /* 20 Mhz */ {   97.5f,                 /* SGI */  108.3f, },
769                     /* 40 Mhz */ {  202.5f,                 /* SGI */  225.0f, },
770           },
771 
772           /* MCS 66  */
773           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
774                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
775           },
776 
777           /* MCS 67  */
778           {         /* 20 Mhz */ {  136.5f,                 /* SGI */  151.7f, },
779                     /* 40 Mhz */ {  283.5f,                 /* SGI */  315.0f, },
780           },
781 
782           /* MCS 68  */
783           {         /* 20 Mhz */ {  117.0f,                 /* SGI */  130.0f, },
784                     /* 40 Mhz */ {  243.0f,                 /* SGI */  270.0f, },
785           },
786 
787           /* MCS 69  */
788           {         /* 20 Mhz */ {  136.5f,                 /* SGI */  151.7f, },
789                     /* 40 Mhz */ {  283.5f,                 /* SGI */  315.0f, },
790           },
791 
792           /* MCS 70  */
793           {         /* 20 Mhz */ {  156.0f,                 /* SGI */  173.3f, },
794                     /* 40 Mhz */ {  324.0f,                 /* SGI */  360.0f, },
795           },
796 
797           /* MCS 71  */
798           {         /* 20 Mhz */ {  175.5f,                 /* SGI */  195.0f, },
799                     /* 40 Mhz */ {  364.5f,                 /* SGI */  405.0f, },
800           },
801 
802           /* MCS 72  */
803           {         /* 20 Mhz */ {  156.0f,                 /* SGI */  173.3f, },
804                     /* 40 Mhz */ {  324.0f,                 /* SGI */  360.0f, },
805           },
806 
807           /* MCS 73  */
808           {         /* 20 Mhz */ {  175.5f,                 /* SGI */  195.0f, },
809                     /* 40 Mhz */ {  364.5f,                 /* SGI */  405.0f, },
810           },
811 
812           /* MCS 74  */
813           {         /* 20 Mhz */ {  195.0f,                 /* SGI */  216.7f, },
814                     /* 40 Mhz */ {  405.0f,                 /* SGI */  450.0f, },
815           },
816 
817           /* MCS 75  */
818           {         /* 20 Mhz */ {  195.0f,                 /* SGI */  216.7f, },
819                     /* 40 Mhz */ {  405.0f,                 /* SGI */  450.0f, },
820           },
821 
822           /* MCS 76  */
823           {         /* 20 Mhz */ {  214.5f,                 /* SGI */  238.3f, },
824                     /* 40 Mhz */ {  445.5f,                 /* SGI */  495.0f, },
825           },
826 };
827 
828 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
829 #define NUM_AUTH_ALGS         (sizeof(auth_alg_text) / sizeof(auth_alg_text[0]))
830 
831 static const char *status_text[] = {
832           "Successful",                                                         /*  0 */
833           "Unspecified failure",                                                /*  1 */
834           "TDLS wakeup schedule rejected but alternative schedule "
835             "provided",                                               /*  2 */
836           "TDLS wakeup schedule rejected",/*  3 */
837           "Reserved",                                                           /*  4 */
838           "Security disabled",                              /*  5 */
839           "Unacceptable lifetime",                /*  6 */
840           "Not in same BSS",                                /*  7 */
841           "Reserved",                                                           /*  8 */
842           "Reserved",                                                           /*  9 */
843           "Cannot Support all requested capabilities in the Capability "
844             "Information field",                                                /* 10 */
845           "Reassociation denied due to inability to confirm that association "
846             "exists",                                                           /* 11 */
847           "Association denied due to reason outside the scope of this "
848             "standard",                                                         /* 12 */
849           "Responding STA does not support the specified authentication "
850             "algorithm",                                                        /* 13 */
851           "Received an Authentication frame with authentication transaction "
852             "sequence number out of expected sequence",               /* 14 */
853           "Authentication rejected because of challenge failure",     /* 15 */
854           "Authentication rejected due to timeout waiting for next frame in "
855             "sequence",                                                         /* 16 */
856           "Association denied because AP is unable to handle "
857             "additional associated STAs",                                       /* 17 */
858           "Association denied due to requesting STA not supporting "
859             "all of the data rates in the BSSBasicRateSet parameter, "
860             "the Basic HT-MCS Set field of the HT Operation "
861             "parameter, or the Basic VHT-MCS and NSS Set field in "
862             "the VHT Operation parameter",        /* 18 */
863           "Association denied due to requesting STA not supporting "
864             "the short preamble option",                                        /* 19 */
865           "Reserved",                                                 /* 20 */
866           "Reserved",                                                 /* 21 */
867           "Association request rejected because Spectrum Management "
868             "capability is required",                                 /* 22 */
869           "Association request rejected because the information in the "
870             "Power Capability element is unacceptable",               /* 23 */
871           "Association request rejected because the information in the "
872             "Supported Channels element is unacceptable",             /* 24 */
873           "Association denied due to requesting STA not supporting "
874             "the Short Slot Time option",                                       /* 25 */
875           "Reserved",                                       /* 26 */
876           "Association denied because the requested STA does not support HT "
877             "features",                                                         /* 27 */
878           "R0KH unreachable",                                         /* 28 */
879           "Association denied because the requesting STA does not "
880             "support the phased coexistence operation (PCO) "
881             "transition time required by the AP",           /* 29 */
882           "Association request rejected temporarily; try again "
883             "later",                                                                      /* 30 */
884           "Robust management frame policy violation",       /* 31 */
885           "Unspecified, QoS-related failure",                         /* 32 */
886           "Association denied because QoS AP or PCP has "
887             "insufficient bandwidth to handle another QoS "
888             "STA",                                                                                  /* 33 */
889           "Association denied due to excessive frame loss rates and/or "
890             "poor conditions on current operating channel", /* 34 */
891           "Association (with QoS BSS) denied because the requesting STA "
892             "does not support the QoS facility",                      /* 35 */
893           "Reserved",                                                                                         /* 36 */
894           "The request has been declined",                            /* 37 */
895           "The request has not been successful as one or more parameters "
896             "have invalid values",                                    /* 38 */
897           "The allocation or TS has not been created because the request "
898             "cannot be honored; however, a suggested TSPEC/DMG TSPEC is "
899             "provided so that the initiating STA can attempt to set "
900             "another allocation or TS with the suggested changes to the "
901             "TSPEC/DMG TSPEC",                                                  /* 39 */
902           "Invalid element, i.e., an element defined in this standard "
903             "for which the content does not meet the specifications in "
904             "Clause 9",                                                                             /* 40 */
905           "Invalid group cipher",                                                         /* 41 */
906           "Invalid pairwise cipher",                                            /* 42 */
907           "Invalid AKMP",                                                                           /* 43 */
908           "Unsupported RSNE version",                                           /* 44 */
909           "Invalid RSNE capabilities",                                /* 45 */
910           "Cipher suite rejected because of security policy",                   /* 46 */
911           "The TS or allocation has not been created; however, the "
912             "HC or PCP might be capable of creating a TS or "
913             "allocation, in response to a request, after the time "
914             "indicated in the TS Delay element",            /* 47 */
915           "Direct Link is not allowed in the BSS by policy",          /* 48 */
916           "The Destination STA is not present within this BSS",       /* 49 */
917           "The Destination STA is not a QoS STA",           /* 50 */
918 
919           "Association denied because the listen interval is "
920             "too large",                                                                            /* 51 */
921           "Invalid FT Action frame count",                            /* 52 */
922           "Invalid pairwise master key identifier (PMKID)", /* 53 */
923           "Invalid MDE",                                                                            /* 54 */
924           "Invalid FTE",                                                                            /* 55 */
925           "Requested TCLAS processing is not supported by the AP "
926             "or PCP",                                                                                         /* 56 */
927           "The AP or PCP has insufficient TCLAS processing "
928             "resources to satisfy the request",             /* 57 */
929           "The TS has not been created because the request "
930             "cannot be honored; however, the HC or PCP suggests "
931             "that the STA transition to a different BSS to set up "
932             "the TS",                                                                                         /* 58 */
933           "GAS Advertisement Protocol not supported",       /* 59 */
934           "No outstanding GAS request",                               /* 60 */
935           "GAS Response not received from the Advertisement "
936             "Server",                                                                                         /* 61 */
937           "STA timed out waiting for GAS Query Response", /* 62 */
938           "LARGE GAS Response is larger than query response "
939             "length limit",                                                               /* 63 */
940           "Request refused because home network does not support "
941             "request",                                                                              /* 64 */
942           "Advertisement Server in the network is not currently "
943             "reachable",                                                                            /* 65 */
944           "Reserved",                                                                                         /* 66 */
945           "Request refused due to permissions received via SSPN "
946             "interface",                                                                            /* 67 */
947           "Request refused because the AP or PCP does not "
948             "support unauthenticated access",                         /* 68 */
949           "Reserved",                                                                                         /* 69 */
950           "Reserved",                                                                                         /* 70 */
951           "Reserved",                                                                                         /* 71 */
952           "Invalid contents of RSNE",                                 /* 72 */
953           "U-APSD coexistence is not supported",            /* 73 */
954           "Requested U-APSD coexistence mode is not supported", /* 74 */
955           "Requested Interval/Duration value cannot be "
956             "supported with U-APSD coexistence",            /* 75 */
957           "Authentication is rejected because an Anti-Clogging "
958             "Token is required",                                                          /* 76 */
959           "Authentication is rejected because the offered "
960             "finite cyclic group is not supported",         /* 77 */
961           "The TBTT adjustment request has not been successful "
962             "because the STA could not find an alternative TBTT", /* 78 */
963           "Transmission failure",                                                         /* 79 */
964           "Requested TCLAS Not Supported",                            /* 80 */
965           "TCLAS Resources Exhausted",                                /* 81 */
966           "Rejected with Suggested BSS transition",         /* 82 */
967           "Reject with recommended schedule",                         /* 83 */
968           "Reject because no wakeup schedule specified", /* 84 */
969           "Success, the destination STA is in power save mode", /* 85 */
970           "FST pending, in process of admitting FST session", /* 86 */
971           "Performing FST now",                                                           /* 87 */
972           "FST pending, gap(s) in block ack window",        /* 88 */
973           "Reject because of U-PID setting",                          /* 89 */
974           "Reserved",                                                                                         /* 90 */
975           "Reserved",                                                                                         /* 91 */
976           "(Re)Association refused for some external reason", /* 92 */
977           "(Re)Association refused because of memory limits "
978             "at the AP",                                                                            /* 93 */
979           "(Re)Association refused because emergency services "
980             "are not supported at the AP",                            /* 94 */
981           "GAS query response not yet received",            /* 95 */
982           "Reject since the request is for transition to a "
983             "frequency band subject to DSE procedures and "
984             "FST Initiator is a dependent STA",             /* 96 */
985           "Requested TCLAS processing has been terminated by "
986             "the AP",                                                                                         /* 97 */
987           "The TS schedule conflicts with an existing "
988             "schedule; an alternative schedule is provided", /* 98 */
989           "The association has been denied; however, one or "
990             "more Multi-band elements are included that can "
991             "be used by the receiving STA to join the BSS", /* 99 */
992           "The request failed due to a reservation conflict", /* 100 */
993           "The request failed due to exceeded MAF limit", /* 101 */
994           "The request failed due to exceeded MCCA track "
995             "limit",                                                                                          /* 102 */
996           "Association denied because the information in the"
997             "Spectrum Management field is unacceptable", /* 103 */
998           "Association denied because the requesting STA "
999             "does not support VHT features",                          /* 104 */
1000           "Enablement denied",                                                            /* 105 */
1001           "Enablement denied due to restriction from an "
1002             "authorized GDB",                                                             /* 106 */
1003           "Authorization deenabled",                                            /* 107 */
1004 };
1005 #define NUM_STATUSES          (sizeof(status_text) / sizeof(status_text[0]))
1006 
1007 static const char *reason_text[] = {
1008           "Reserved",                                                           /* 0 */
1009           "Unspecified reason",                                                 /* 1 */
1010           "Previous authentication no longer valid",                  /* 2 */
1011           "Deauthenticated because sending STA is leaving (or has left) "
1012             "IBSS or ESS",                                            /* 3 */
1013           "Disassociated due to inactivity",                          /* 4 */
1014           "Disassociated because AP is unable to handle all currently "
1015             " associated STAs",                                       /* 5 */
1016           "Class 2 frame received from nonauthenticated STA", /* 6 */
1017           "Class 3 frame received from nonassociated STA",  /* 7 */
1018           "Disassociated because sending STA is leaving "
1019             "(or has left) BSS",                                                /* 8 */
1020           "STA requesting (re)association is not authenticated with "
1021             "responding STA",                                         /* 9 */
1022           "Disassociated because the information in the Power Capability "
1023             "element is unacceptable",                                /* 10 */
1024           "Disassociated because the information in the Supported Channels "
1025             "element is unacceptable",                                /* 11 */
1026           "Disassociated due to BSS transition management", /* 12 */
1027           "Invalid element, i.e., an element defined in this standard for "
1028             "which the content does not meet the specifications "
1029             "in Clause 9",                                                      /* 13 */
1030           "Message integrity code (MIC) failure", /* 14 */
1031           "4-Way Handshake timeout",                                  /* 15 */
1032           "Group key handshake timeout",                              /* 16 */
1033           "Information element in 4-Way Handshake different from (Re)Association"
1034             "Request/Probe Response/Beacon frame",          /* 17 */
1035           "Invalid group cipher",                                               /* 18 */
1036           "Invalid pairwise cipher",                                  /* 19 */
1037           "Invalid AKMP",                                                                 /* 20 */
1038           "Unsupported RSNE version",                                 /* 21 */
1039           "Invalid RSNE capabilities",                                /* 22 */
1040           "IEEE 802.1X authentication failed",                        /* 23 */
1041           "Cipher suite rejected because of the security policy",               /* 24 */
1042           "TDLS direct-link teardown due to TDLS peer STA "
1043             "unreachable via the TDLS direct link",                                       /* 25 */
1044           "TDLS direct-link teardown for unspecified reason",                   /* 26 */
1045           "Disassociated because session terminated by SSP request",/* 27 */
1046           "Disassociated because of lack of SSP roaming agreement",/* 28 */
1047           "Requested service rejected because of SSP cipher suite or "
1048             "AKM requirement",                                                            /* 29 */
1049           "Requested service not authorized in this location",        /* 30 */
1050           "TS deleted because QoS AP lacks sufficient bandwidth for this "
1051             "QoS STA due to a change in BSS service characteristics or "
1052             "operational mode (e.g. an HT BSS change from 40 MHz channel "
1053             "to 20 MHz channel)",                                               /* 31 */
1054           "Disassociated for unspecified, QoS-related reason",        /* 32 */
1055           "Disassociated because QoS AP lacks sufficient bandwidth for this "
1056             "QoS STA",                                                          /* 33 */
1057           "Disassociated because of excessive number of frames that need to be "
1058             "acknowledged, but are not acknowledged due to AP transmissions "
1059             "and/or poor channel conditions",                         /* 34 */
1060           "Disassociated because STA is transmitting outside the limits "
1061             "of its TXOPs",                                           /* 35 */
1062           "Requested from peer STA as the STA is leaving the BSS "
1063             "(or resetting)",                                         /* 36 */
1064           "Requested from peer STA as it does not want to use the "
1065             "mechanism",                                                        /* 37 */
1066           "Requested from peer STA as the STA received frames using the "
1067             "mechanism for which a set up is required",               /* 38 */
1068           "Requested from peer STA due to time out",                  /* 39 */
1069           "Reserved",                                                           /* 40 */
1070           "Reserved",                                                           /* 41 */
1071           "Reserved",                                                           /* 42 */
1072           "Reserved",                                                           /* 43 */
1073           "Reserved",                                                           /* 44 */
1074           "Peer STA does not support the requested cipher suite",     /* 45 */
1075           "In a DLS Teardown frame: The teardown was initiated by the "
1076             "DLS peer. In a Disassociation frame: Disassociated because "
1077             "authorized access limit reached",                                            /* 46 */
1078           "In a DLS Teardown frame: The teardown was initiated by the "
1079             "AP. In a Disassociation frame: Disassociated due to external "
1080             "service requirements",                                                                           /* 47 */
1081           "Invalid FT Action frame count",                                                          /* 48 */
1082           "Invalid pairwise master key identifier (PMKID)",           /* 49 */
1083           "Invalid MDE",                                                                                                          /* 50 */
1084           "Invalid FTE",                                                                                                          /* 51 */
1085           "Mesh peering canceled for unknown reasons",                          /* 52 */
1086           "The mesh STA has reached the supported maximum number of "
1087             "peer mesh STAs",                                                                                           /* 53 */
1088           "The received information violates the Mesh Configuration "
1089             "policy configured in the mesh STA profile",                        /* 54 */
1090           "The mesh STA has received a Mesh Peering Close frame "
1091             "requesting to close the mesh peering",                                       /* 55 */
1092           "The mesh STA has resent dot11MeshMaxRetries Mesh "
1093             "Peering Open frames, without receiving a Mesh Peering "
1094             "Confirm frame",                                                                                            /* 56 */
1095           "The confirmTimer for the mesh peering instance times out", /* 57 */
1096           "The mesh STA fails to unwrap the GTK or the values in the "
1097             "wrapped contents do not match",                                                        /* 58 */
1098           "The mesh STA receives inconsistent information about the "
1099             "mesh parameters between mesh peering Management frames", /* 59 */
1100           "The mesh STA fails the authenticated mesh peering exchange "
1101             "because due to failure in selecting either the pairwise "
1102             "ciphersuite or group ciphersuite",                                           /* 60 */
1103           "The mesh STA does not have proxy information for this "
1104             "external destination",                                                                           /* 61 */
1105           "The mesh STA does not have forwarding information for this "
1106             "destination",                                                                                              /* 62 */
1107           "The mesh STA determines that the link to the next hop of an "
1108             "active path in its forwarding information is no longer "
1109             "usable",                                                                                                                       /* 63 */
1110           "The Deauthentication frame was sent because the MAC "
1111             "address of the STA already exists in the mesh BSS",      /* 64 */
1112           "The mesh STA performs channel switch to meet regulatory "
1113             "requirements",                                                                                             /* 65 */
1114           "The mesh STA performs channel switching with unspecified "
1115             "reason",                                                                                                                       /* 66 */
1116 };
1117 #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0]))
1118 
1119 static int
wep_print(netdissect_options * ndo,const u_char * p)1120 wep_print(netdissect_options *ndo,
1121             const u_char *p)
1122 {
1123           uint32_t iv;
1124 
1125           ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN);
1126           iv = GET_LE_U_4(p);
1127 
1128           ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
1129               IV_KEYID(iv));
1130 
1131           return 1;
1132 trunc:
1133           return 0;
1134 }
1135 
1136 static int
parse_elements(netdissect_options * ndo,struct mgmt_body_t * pbody,const u_char * p,int offset,u_int length)1137 parse_elements(netdissect_options *ndo,
1138                  struct mgmt_body_t *pbody, const u_char *p, int offset,
1139                  u_int length)
1140 {
1141           u_int elementlen;
1142           struct ssid_t ssid;
1143           struct challenge_t challenge;
1144           struct rates_t rates;
1145           struct ds_t ds;
1146           struct cf_t cf;
1147           struct tim_t tim;
1148 
1149           /*
1150            * We haven't seen any elements yet.
1151            */
1152           pbody->challenge_present = 0;
1153           pbody->ssid_present = 0;
1154           pbody->rates_present = 0;
1155           pbody->ds_present = 0;
1156           pbody->cf_present = 0;
1157           pbody->tim_present = 0;
1158 
1159           while (length != 0) {
1160                     /* Make sure we at least have the element ID and length. */
1161                     ND_TCHECK_2(p + offset);
1162                     if (length < 2)
1163                               goto trunc;
1164                     elementlen = GET_U_1(p + offset + 1);
1165 
1166                     /* Make sure we have the entire element. */
1167                     ND_TCHECK_LEN(p + offset + 2, elementlen);
1168                     if (length < elementlen + 2)
1169                               goto trunc;
1170 
1171                     switch (GET_U_1(p + offset)) {
1172                     case E_SSID:
1173                               memcpy(&ssid, p + offset, 2);
1174                               offset += 2;
1175                               length -= 2;
1176                               if (ssid.length != 0) {
1177                                         if (ssid.length > sizeof(ssid.ssid) - 1)
1178                                                   return 0;
1179                                         memcpy(&ssid.ssid, p + offset, ssid.length);
1180                                         offset += ssid.length;
1181                                         length -= ssid.length;
1182                               }
1183                               ssid.ssid[ssid.length] = '\0';
1184                               /*
1185                                * Present and not truncated.
1186                                *
1187                                * If we haven't already seen an SSID IE,
1188                                * copy this one, otherwise ignore this one,
1189                                * so we later report the first one we saw.
1190                                */
1191                               if (!pbody->ssid_present) {
1192                                         pbody->ssid = ssid;
1193                                         pbody->ssid_present = 1;
1194                               }
1195                               break;
1196                     case E_CHALLENGE:
1197                               memcpy(&challenge, p + offset, 2);
1198                               offset += 2;
1199                               length -= 2;
1200                               if (challenge.length != 0) {
1201                                         if (challenge.length >
1202                                             sizeof(challenge.text) - 1)
1203                                                   return 0;
1204                                         memcpy(&challenge.text, p + offset,
1205                                             challenge.length);
1206                                         offset += challenge.length;
1207                                         length -= challenge.length;
1208                               }
1209                               challenge.text[challenge.length] = '\0';
1210                               /*
1211                                * Present and not truncated.
1212                                *
1213                                * If we haven't already seen a challenge IE,
1214                                * copy this one, otherwise ignore this one,
1215                                * so we later report the first one we saw.
1216                                */
1217                               if (!pbody->challenge_present) {
1218                                         pbody->challenge = challenge;
1219                                         pbody->challenge_present = 1;
1220                               }
1221                               break;
1222                     case E_RATES:
1223                               memcpy(&rates, p + offset, 2);
1224                               offset += 2;
1225                               length -= 2;
1226                               if (rates.length != 0) {
1227                                         if (rates.length > sizeof(rates.rate))
1228                                                   return 0;
1229                                         memcpy(&rates.rate, p + offset, rates.length);
1230                                         offset += rates.length;
1231                                         length -= rates.length;
1232                               }
1233                               /*
1234                                * Present and not truncated.
1235                                *
1236                                * If we haven't already seen a rates IE,
1237                                * copy this one if it's not zero-length,
1238                                * otherwise ignore this one, so we later
1239                                * report the first one we saw.
1240                                *
1241                                * We ignore zero-length rates IEs as some
1242                                * devices seem to put a zero-length rates
1243                                * IE, followed by an SSID IE, followed by
1244                                * a non-zero-length rates IE into frames,
1245                                * even though IEEE Std 802.11-2007 doesn't
1246                                * seem to indicate that a zero-length rates
1247                                * IE is valid.
1248                                */
1249                               if (!pbody->rates_present && rates.length != 0) {
1250                                         pbody->rates = rates;
1251                                         pbody->rates_present = 1;
1252                               }
1253                               break;
1254                     case E_DS:
1255                               memcpy(&ds, p + offset, 2);
1256                               offset += 2;
1257                               length -= 2;
1258                               if (ds.length != 1) {
1259                                         offset += ds.length;
1260                                         length -= ds.length;
1261                                         break;
1262                               }
1263                               ds.channel = GET_U_1(p + offset);
1264                               offset += 1;
1265                               length -= 1;
1266                               /*
1267                                * Present and not truncated.
1268                                *
1269                                * If we haven't already seen a DS IE,
1270                                * copy this one, otherwise ignore this one,
1271                                * so we later report the first one we saw.
1272                                */
1273                               if (!pbody->ds_present) {
1274                                         pbody->ds = ds;
1275                                         pbody->ds_present = 1;
1276                               }
1277                               break;
1278                     case E_CF:
1279                               memcpy(&cf, p + offset, 2);
1280                               offset += 2;
1281                               length -= 2;
1282                               if (cf.length != 6) {
1283                                         offset += cf.length;
1284                                         length -= cf.length;
1285                                         break;
1286                               }
1287                               memcpy(&cf.count, p + offset, 6);
1288                               offset += 6;
1289                               length -= 6;
1290                               /*
1291                                * Present and not truncated.
1292                                *
1293                                * If we haven't already seen a CF IE,
1294                                * copy this one, otherwise ignore this one,
1295                                * so we later report the first one we saw.
1296                                */
1297                               if (!pbody->cf_present) {
1298                                         pbody->cf = cf;
1299                                         pbody->cf_present = 1;
1300                               }
1301                               break;
1302                     case E_TIM:
1303                               memcpy(&tim, p + offset, 2);
1304                               offset += 2;
1305                               length -= 2;
1306                               if (tim.length <= 3U) {
1307                                         offset += tim.length;
1308                                         length -= tim.length;
1309                                         break;
1310                               }
1311                               if (tim.length - 3U > sizeof(tim.bitmap))
1312                                         return 0;
1313                               memcpy(&tim.count, p + offset, 3);
1314                               offset += 3;
1315                               length -= 3;
1316 
1317                               memcpy(tim.bitmap, p + offset, tim.length - 3);
1318                               offset += tim.length - 3;
1319                               length -= tim.length - 3;
1320                               /*
1321                                * Present and not truncated.
1322                                *
1323                                * If we haven't already seen a TIM IE,
1324                                * copy this one, otherwise ignore this one,
1325                                * so we later report the first one we saw.
1326                                */
1327                               if (!pbody->tim_present) {
1328                                         pbody->tim = tim;
1329                                         pbody->tim_present = 1;
1330                               }
1331                               break;
1332                     default:
1333 #if 0
1334                               ND_PRINT("(1) unhandled element_id (%u)  ",
1335                                   GET_U_1(p + offset));
1336 #endif
1337                               offset += 2 + elementlen;
1338                               length -= 2 + elementlen;
1339                               break;
1340                     }
1341           }
1342 
1343           /* No problems found. */
1344           return 1;
1345 trunc:
1346           return 0;
1347 }
1348 
1349 /*********************************************************************************
1350  * Print Handle functions for the management frame types
1351  *********************************************************************************/
1352 
1353 static int
handle_beacon(netdissect_options * ndo,const u_char * p,u_int length)1354 handle_beacon(netdissect_options *ndo,
1355                 const u_char *p, u_int length)
1356 {
1357           struct mgmt_body_t pbody;
1358           int offset = 0;
1359           int ret;
1360 
1361           memset(&pbody, 0, sizeof(pbody));
1362 
1363           ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1364                           IEEE802_11_CAPINFO_LEN);
1365           if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1366               IEEE802_11_CAPINFO_LEN)
1367                     goto trunc;
1368           memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
1369           offset += IEEE802_11_TSTAMP_LEN;
1370           length -= IEEE802_11_TSTAMP_LEN;
1371           pbody.beacon_interval = GET_LE_U_2(p + offset);
1372           offset += IEEE802_11_BCNINT_LEN;
1373           length -= IEEE802_11_BCNINT_LEN;
1374           pbody.capability_info = GET_LE_U_2(p + offset);
1375           offset += IEEE802_11_CAPINFO_LEN;
1376           length -= IEEE802_11_CAPINFO_LEN;
1377 
1378           ret = parse_elements(ndo, &pbody, p, offset, length);
1379 
1380           PRINT_SSID(pbody);
1381           PRINT_RATES(pbody);
1382           ND_PRINT(" %s",
1383               CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
1384           PRINT_DS_CHANNEL(pbody);
1385 
1386           return ret;
1387 trunc:
1388           return 0;
1389 }
1390 
1391 static int
handle_assoc_request(netdissect_options * ndo,const u_char * p,u_int length)1392 handle_assoc_request(netdissect_options *ndo,
1393                          const u_char *p, u_int length)
1394 {
1395           struct mgmt_body_t pbody;
1396           int offset = 0;
1397           int ret;
1398 
1399           memset(&pbody, 0, sizeof(pbody));
1400 
1401           ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
1402           if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
1403                     goto trunc;
1404           pbody.capability_info = GET_LE_U_2(p);
1405           offset += IEEE802_11_CAPINFO_LEN;
1406           length -= IEEE802_11_CAPINFO_LEN;
1407           pbody.listen_interval = GET_LE_U_2(p + offset);
1408           offset += IEEE802_11_LISTENINT_LEN;
1409           length -= IEEE802_11_LISTENINT_LEN;
1410 
1411           ret = parse_elements(ndo, &pbody, p, offset, length);
1412 
1413           PRINT_SSID(pbody);
1414           PRINT_RATES(pbody);
1415           return ret;
1416 trunc:
1417           return 0;
1418 }
1419 
1420 static int
handle_assoc_response(netdissect_options * ndo,const u_char * p,u_int length)1421 handle_assoc_response(netdissect_options *ndo,
1422                           const u_char *p, u_int length)
1423 {
1424           struct mgmt_body_t pbody;
1425           int offset = 0;
1426           int ret;
1427 
1428           memset(&pbody, 0, sizeof(pbody));
1429 
1430           ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1431                           IEEE802_11_AID_LEN);
1432           if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1433               IEEE802_11_AID_LEN)
1434                     goto trunc;
1435           pbody.capability_info = GET_LE_U_2(p);
1436           offset += IEEE802_11_CAPINFO_LEN;
1437           length -= IEEE802_11_CAPINFO_LEN;
1438           pbody.status_code = GET_LE_U_2(p + offset);
1439           offset += IEEE802_11_STATUS_LEN;
1440           length -= IEEE802_11_STATUS_LEN;
1441           pbody.aid = GET_LE_U_2(p + offset);
1442           offset += IEEE802_11_AID_LEN;
1443           length -= IEEE802_11_AID_LEN;
1444 
1445           ret = parse_elements(ndo, &pbody, p, offset, length);
1446 
1447           ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
1448               CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
1449               (pbody.status_code < NUM_STATUSES
1450                     ? status_text[pbody.status_code]
1451                     : "n/a"));
1452 
1453           return ret;
1454 trunc:
1455           return 0;
1456 }
1457 
1458 static int
handle_reassoc_request(netdissect_options * ndo,const u_char * p,u_int length)1459 handle_reassoc_request(netdissect_options *ndo,
1460                            const u_char *p, u_int length)
1461 {
1462           struct mgmt_body_t pbody;
1463           int offset = 0;
1464           int ret;
1465 
1466           memset(&pbody, 0, sizeof(pbody));
1467 
1468           ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1469                           IEEE802_11_AP_LEN);
1470           if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1471               IEEE802_11_AP_LEN)
1472                     goto trunc;
1473           pbody.capability_info = GET_LE_U_2(p);
1474           offset += IEEE802_11_CAPINFO_LEN;
1475           length -= IEEE802_11_CAPINFO_LEN;
1476           pbody.listen_interval = GET_LE_U_2(p + offset);
1477           offset += IEEE802_11_LISTENINT_LEN;
1478           length -= IEEE802_11_LISTENINT_LEN;
1479           memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
1480           offset += IEEE802_11_AP_LEN;
1481           length -= IEEE802_11_AP_LEN;
1482 
1483           ret = parse_elements(ndo, &pbody, p, offset, length);
1484 
1485           PRINT_SSID(pbody);
1486           ND_PRINT(" AP : %s", etheraddr_string(ndo,  pbody.ap ));
1487 
1488           return ret;
1489 trunc:
1490           return 0;
1491 }
1492 
1493 static int
handle_reassoc_response(netdissect_options * ndo,const u_char * p,u_int length)1494 handle_reassoc_response(netdissect_options *ndo,
1495                               const u_char *p, u_int length)
1496 {
1497           /* Same as a Association Response */
1498           return handle_assoc_response(ndo, p, length);
1499 }
1500 
1501 static int
handle_probe_request(netdissect_options * ndo,const u_char * p,u_int length)1502 handle_probe_request(netdissect_options *ndo,
1503                          const u_char *p, u_int length)
1504 {
1505           struct mgmt_body_t  pbody;
1506           int offset = 0;
1507           int ret;
1508 
1509           memset(&pbody, 0, sizeof(pbody));
1510 
1511           ret = parse_elements(ndo, &pbody, p, offset, length);
1512 
1513           PRINT_SSID(pbody);
1514           PRINT_RATES(pbody);
1515 
1516           return ret;
1517 }
1518 
1519 static int
handle_probe_response(netdissect_options * ndo,const u_char * p,u_int length)1520 handle_probe_response(netdissect_options *ndo,
1521                           const u_char *p, u_int length)
1522 {
1523           struct mgmt_body_t  pbody;
1524           int offset = 0;
1525           int ret;
1526 
1527           memset(&pbody, 0, sizeof(pbody));
1528 
1529           ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1530                           IEEE802_11_CAPINFO_LEN);
1531           if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1532               IEEE802_11_CAPINFO_LEN)
1533                     goto trunc;
1534           memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
1535           offset += IEEE802_11_TSTAMP_LEN;
1536           length -= IEEE802_11_TSTAMP_LEN;
1537           pbody.beacon_interval = GET_LE_U_2(p + offset);
1538           offset += IEEE802_11_BCNINT_LEN;
1539           length -= IEEE802_11_BCNINT_LEN;
1540           pbody.capability_info = GET_LE_U_2(p + offset);
1541           offset += IEEE802_11_CAPINFO_LEN;
1542           length -= IEEE802_11_CAPINFO_LEN;
1543 
1544           ret = parse_elements(ndo, &pbody, p, offset, length);
1545 
1546           PRINT_SSID(pbody);
1547           PRINT_RATES(pbody);
1548           PRINT_DS_CHANNEL(pbody);
1549 
1550           return ret;
1551 trunc:
1552           return 0;
1553 }
1554 
1555 static int
handle_atim(void)1556 handle_atim(void)
1557 {
1558           /* the frame body for ATIM is null. */
1559           return 1;
1560 }
1561 
1562 static int
handle_disassoc(netdissect_options * ndo,const u_char * p,u_int length)1563 handle_disassoc(netdissect_options *ndo,
1564                     const u_char *p, u_int length)
1565 {
1566           struct mgmt_body_t  pbody;
1567 
1568           memset(&pbody, 0, sizeof(pbody));
1569 
1570           ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
1571           if (length < IEEE802_11_REASON_LEN)
1572                     goto trunc;
1573           pbody.reason_code = GET_LE_U_2(p);
1574 
1575           ND_PRINT(": %s",
1576               (pbody.reason_code < NUM_REASONS)
1577                     ? reason_text[pbody.reason_code]
1578                     : "Reserved");
1579 
1580           return 1;
1581 trunc:
1582           return 0;
1583 }
1584 
1585 static int
handle_auth(netdissect_options * ndo,const u_char * p,u_int length)1586 handle_auth(netdissect_options *ndo,
1587               const u_char *p, u_int length)
1588 {
1589           struct mgmt_body_t  pbody;
1590           int offset = 0;
1591           int ret;
1592 
1593           memset(&pbody, 0, sizeof(pbody));
1594 
1595           ND_TCHECK_6(p);
1596           if (length < 6)
1597                     goto trunc;
1598           pbody.auth_alg = GET_LE_U_2(p);
1599           offset += 2;
1600           length -= 2;
1601           pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
1602           offset += 2;
1603           length -= 2;
1604           pbody.status_code = GET_LE_U_2(p + offset);
1605           offset += 2;
1606           length -= 2;
1607 
1608           ret = parse_elements(ndo, &pbody, p, offset, length);
1609 
1610           if ((pbody.auth_alg == 1) &&
1611               ((pbody.auth_trans_seq_num == 2) ||
1612                (pbody.auth_trans_seq_num == 3))) {
1613                     ND_PRINT(" (%s)-%x [Challenge Text] %s",
1614                         (pbody.auth_alg < NUM_AUTH_ALGS)
1615                               ? auth_alg_text[pbody.auth_alg]
1616                               : "Reserved",
1617                         pbody.auth_trans_seq_num,
1618                         ((pbody.auth_trans_seq_num % 2)
1619                               ? ((pbody.status_code < NUM_STATUSES)
1620                                      ? status_text[pbody.status_code]
1621                                      : "n/a") : ""));
1622                     return ret;
1623           }
1624           ND_PRINT(" (%s)-%x: %s",
1625               (pbody.auth_alg < NUM_AUTH_ALGS)
1626                     ? auth_alg_text[pbody.auth_alg]
1627                     : "Reserved",
1628               pbody.auth_trans_seq_num,
1629               (pbody.auth_trans_seq_num % 2)
1630                     ? ((pbody.status_code < NUM_STATUSES)
1631                         ? status_text[pbody.status_code]
1632                         : "n/a")
1633                     : "");
1634 
1635           return ret;
1636 trunc:
1637           return 0;
1638 }
1639 
1640 static int
handle_deauth(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)1641 handle_deauth(netdissect_options *ndo,
1642                 const uint8_t *src, const u_char *p, u_int length)
1643 {
1644           struct mgmt_body_t  pbody;
1645           const char *reason = NULL;
1646 
1647           memset(&pbody, 0, sizeof(pbody));
1648 
1649           ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
1650           if (length < IEEE802_11_REASON_LEN)
1651                     goto trunc;
1652           pbody.reason_code = GET_LE_U_2(p);
1653 
1654           reason = (pbody.reason_code < NUM_REASONS)
1655                               ? reason_text[pbody.reason_code]
1656                               : "Reserved";
1657 
1658           if (ndo->ndo_eflag) {
1659                     ND_PRINT(": %s", reason);
1660           } else {
1661                     ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
1662           }
1663           return 1;
1664 trunc:
1665           return 0;
1666 }
1667 
1668 #define   PRINT_HT_ACTION(v) (\
1669           (v) == 0 ? ND_PRINT("TxChWidth"): \
1670           (v) == 1 ? ND_PRINT("MIMOPwrSave"): \
1671                        ND_PRINT("Act#%u", (v)))
1672 #define   PRINT_BA_ACTION(v) (\
1673           (v) == 0 ? ND_PRINT("ADDBA Request"): \
1674           (v) == 1 ? ND_PRINT("ADDBA Response"): \
1675           (v) == 2 ? ND_PRINT("DELBA"): \
1676                        ND_PRINT("Act#%u", (v)))
1677 #define   PRINT_MESHLINK_ACTION(v) (\
1678           (v) == 0 ? ND_PRINT("Request"): \
1679           (v) == 1 ? ND_PRINT("Report"): \
1680                        ND_PRINT("Act#%u", (v)))
1681 #define   PRINT_MESHPEERING_ACTION(v) (\
1682           (v) == 0 ? ND_PRINT("Open"): \
1683           (v) == 1 ? ND_PRINT("Confirm"): \
1684           (v) == 2 ? ND_PRINT("Close"): \
1685                        ND_PRINT("Act#%u", (v)))
1686 #define   PRINT_MESHPATH_ACTION(v) (\
1687           (v) == 0 ? ND_PRINT("Request"): \
1688           (v) == 1 ? ND_PRINT("Report"): \
1689           (v) == 2 ? ND_PRINT("Error"): \
1690           (v) == 3 ? ND_PRINT("RootAnnouncement"): \
1691                        ND_PRINT("Act#%u", (v)))
1692 
1693 #define PRINT_MESH_ACTION(v) (\
1694           (v) == 0 ? ND_PRINT("MeshLink"): \
1695           (v) == 1 ? ND_PRINT("HWMP"): \
1696           (v) == 2 ? ND_PRINT("Gate Announcement"): \
1697           (v) == 3 ? ND_PRINT("Congestion Control"): \
1698           (v) == 4 ? ND_PRINT("MCCA Setup Request"): \
1699           (v) == 5 ? ND_PRINT("MCCA Setup Reply"): \
1700           (v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \
1701           (v) == 7 ? ND_PRINT("MCCA Advertisement"): \
1702           (v) == 8 ? ND_PRINT("MCCA Teardown"): \
1703           (v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \
1704           (v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \
1705                        ND_PRINT("Act#%u", (v)))
1706 #define PRINT_MULTIHOP_ACTION(v) (\
1707           (v) == 0 ? ND_PRINT("Proxy Update"): \
1708           (v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \
1709                        ND_PRINT("Act#%u", (v)))
1710 #define PRINT_SELFPROT_ACTION(v) (\
1711           (v) == 1 ? ND_PRINT("Peering Open"): \
1712           (v) == 2 ? ND_PRINT("Peering Confirm"): \
1713           (v) == 3 ? ND_PRINT("Peering Close"): \
1714           (v) == 4 ? ND_PRINT("Group Key Inform"): \
1715           (v) == 5 ? ND_PRINT("Group Key Acknowledge"): \
1716                        ND_PRINT("Act#%u", (v)))
1717 
1718 static int
handle_action(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)1719 handle_action(netdissect_options *ndo,
1720                 const uint8_t *src, const u_char *p, u_int length)
1721 {
1722           ND_TCHECK_2(p);
1723           if (length < 2)
1724                     goto trunc;
1725           if (ndo->ndo_eflag) {
1726                     ND_PRINT(": ");
1727           } else {
1728                     ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
1729           }
1730           switch (GET_U_1(p)) {
1731           case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break;
1732           case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break;
1733           case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break;
1734           case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break;
1735           case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break;
1736           case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break;
1737           case 14:
1738                     ND_PRINT("MultiohopAction ");
1739                     PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break;
1740           case 15:
1741                     ND_PRINT("SelfprotectAction ");
1742                     PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break;
1743           case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break;
1744           default:
1745                     ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1));
1746                     break;
1747           }
1748           return 1;
1749 trunc:
1750           return 0;
1751 }
1752 
1753 
1754 /*********************************************************************************
1755  * Print Body funcs
1756  *********************************************************************************/
1757 
1758 
1759 static int
mgmt_body_print(netdissect_options * ndo,uint16_t fc,const uint8_t * src,const u_char * p,u_int length)1760 mgmt_body_print(netdissect_options *ndo,
1761                     uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
1762 {
1763           ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
1764 
1765           /* There may be a problem w/ AP not having this bit set */
1766           if (FC_PROTECTED(fc))
1767                     return wep_print(ndo, p);
1768           switch (FC_SUBTYPE(fc)) {
1769           case ST_ASSOC_REQUEST:
1770                     return handle_assoc_request(ndo, p, length);
1771           case ST_ASSOC_RESPONSE:
1772                     return handle_assoc_response(ndo, p, length);
1773           case ST_REASSOC_REQUEST:
1774                     return handle_reassoc_request(ndo, p, length);
1775           case ST_REASSOC_RESPONSE:
1776                     return handle_reassoc_response(ndo, p, length);
1777           case ST_PROBE_REQUEST:
1778                     return handle_probe_request(ndo, p, length);
1779           case ST_PROBE_RESPONSE:
1780                     return handle_probe_response(ndo, p, length);
1781           case ST_BEACON:
1782                     return handle_beacon(ndo, p, length);
1783           case ST_ATIM:
1784                     return handle_atim();
1785           case ST_DISASSOC:
1786                     return handle_disassoc(ndo, p, length);
1787           case ST_AUTH:
1788                     return handle_auth(ndo, p, length);
1789           case ST_DEAUTH:
1790                     return handle_deauth(ndo, src, p, length);
1791           case ST_ACTION:
1792                     return handle_action(ndo, src, p, length);
1793           default:
1794                     return 1;
1795           }
1796 }
1797 
1798 
1799 /*********************************************************************************
1800  * Handles printing all the control frame types
1801  *********************************************************************************/
1802 
1803 static int
ctrl_body_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1804 ctrl_body_print(netdissect_options *ndo,
1805                     uint16_t fc, const u_char *p)
1806 {
1807           ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
1808           switch (FC_SUBTYPE(fc)) {
1809           case CTRL_CONTROL_WRAPPER:
1810                     /* XXX - requires special handling */
1811                     break;
1812           case CTRL_BAR:
1813                     ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
1814                     if (!ndo->ndo_eflag)
1815                               ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1816                                   GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
1817                                   GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
1818                                   GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
1819                                   GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
1820                     break;
1821           case CTRL_BA:
1822                     ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
1823                     if (!ndo->ndo_eflag)
1824                               ND_PRINT(" RA:%s ",
1825                                   GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
1826                     break;
1827           case CTRL_PS_POLL:
1828                     ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
1829                     ND_PRINT(" AID(%x)",
1830                         GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
1831                     break;
1832           case CTRL_RTS:
1833                     ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
1834                     if (!ndo->ndo_eflag)
1835                               ND_PRINT(" TA:%s ",
1836                                   GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
1837                     break;
1838           case CTRL_CTS:
1839                     ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
1840                     if (!ndo->ndo_eflag)
1841                               ND_PRINT(" RA:%s ",
1842                                   GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
1843                     break;
1844           case CTRL_ACK:
1845                     ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
1846                     if (!ndo->ndo_eflag)
1847                               ND_PRINT(" RA:%s ",
1848                                   GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
1849                     break;
1850           case CTRL_CF_END:
1851                     ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
1852                     if (!ndo->ndo_eflag)
1853                               ND_PRINT(" RA:%s ",
1854                                   GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
1855                     break;
1856           case CTRL_END_ACK:
1857                     ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
1858                     if (!ndo->ndo_eflag)
1859                               ND_PRINT(" RA:%s ",
1860                                   GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
1861                     break;
1862           }
1863           return 1;
1864 trunc:
1865           return 0;
1866 }
1867 
1868 /*
1869  *  Data Frame - Address field contents
1870  *
1871  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
1872  *    0    |  0      |  DA    | SA     | BSSID  | n/a
1873  *    0    |  1      |  DA    | BSSID  | SA     | n/a
1874  *    1    |  0      |  BSSID | SA     | DA     | n/a
1875  *    1    |  1      |  RA    | TA     | DA     | SA
1876  */
1877 
1878 /*
1879  * Function to get source and destination MAC addresses for a data frame.
1880  */
1881 static void
get_data_src_dst_mac(uint16_t fc,const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)1882 get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
1883                          const uint8_t **dstp)
1884 {
1885 #define ADDR1  (p + 4)
1886 #define ADDR2  (p + 10)
1887 #define ADDR3  (p + 16)
1888 #define ADDR4  (p + 24)
1889 
1890           if (!FC_TO_DS(fc)) {
1891                     if (!FC_FROM_DS(fc)) {
1892                               /* not To DS and not From DS */
1893                               *srcp = ADDR2;
1894                               *dstp = ADDR1;
1895                     } else {
1896                               /* not To DS and From DS */
1897                               *srcp = ADDR3;
1898                               *dstp = ADDR1;
1899                     }
1900           } else {
1901                     if (!FC_FROM_DS(fc)) {
1902                               /* From DS and not To DS */
1903                               *srcp = ADDR2;
1904                               *dstp = ADDR3;
1905                     } else {
1906                               /* To DS and From DS */
1907                               *srcp = ADDR4;
1908                               *dstp = ADDR3;
1909                     }
1910           }
1911 
1912 #undef ADDR1
1913 #undef ADDR2
1914 #undef ADDR3
1915 #undef ADDR4
1916 }
1917 
1918 static void
get_mgmt_src_dst_mac(const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)1919 get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
1920 {
1921           const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
1922 
1923           if (srcp != NULL)
1924                     *srcp = hp->sa;
1925           if (dstp != NULL)
1926                     *dstp = hp->da;
1927 }
1928 
1929 /*
1930  * Print Header funcs
1931  */
1932 
1933 static void
data_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1934 data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1935 {
1936           u_int subtype = FC_SUBTYPE(fc);
1937 
1938           if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
1939               DATA_FRAME_IS_QOS(subtype)) {
1940                     ND_PRINT("CF ");
1941                     if (DATA_FRAME_IS_CF_ACK(subtype)) {
1942                               if (DATA_FRAME_IS_CF_POLL(subtype))
1943                                         ND_PRINT("Ack/Poll");
1944                               else
1945                                         ND_PRINT("Ack");
1946                     } else {
1947                               if (DATA_FRAME_IS_CF_POLL(subtype))
1948                                         ND_PRINT("Poll");
1949                     }
1950                     if (DATA_FRAME_IS_QOS(subtype))
1951                               ND_PRINT("+QoS");
1952                     ND_PRINT(" ");
1953           }
1954 
1955 #define ADDR1  (p + 4)
1956 #define ADDR2  (p + 10)
1957 #define ADDR3  (p + 16)
1958 #define ADDR4  (p + 24)
1959 
1960           if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1961                     ND_PRINT("DA:%s SA:%s BSSID:%s ",
1962                         GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1963                         GET_ETHERADDR_STRING(ADDR3));
1964           } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1965                     ND_PRINT("DA:%s BSSID:%s SA:%s ",
1966                         GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1967                         GET_ETHERADDR_STRING(ADDR3));
1968           } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1969                     ND_PRINT("BSSID:%s SA:%s DA:%s ",
1970                         GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1971                         GET_ETHERADDR_STRING(ADDR3));
1972           } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1973                     ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
1974                         GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1975                         GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
1976           }
1977 
1978 #undef ADDR1
1979 #undef ADDR2
1980 #undef ADDR3
1981 #undef ADDR4
1982 }
1983 
1984 static void
mgmt_header_print(netdissect_options * ndo,const u_char * p)1985 mgmt_header_print(netdissect_options *ndo, const u_char *p)
1986 {
1987           const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
1988 
1989           ND_PRINT("BSSID:%s DA:%s SA:%s ",
1990               GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
1991               GET_ETHERADDR_STRING((hp)->sa));
1992 }
1993 
1994 static void
ctrl_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1995 ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1996 {
1997           switch (FC_SUBTYPE(fc)) {
1998           case CTRL_BAR:
1999                     ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
2000                         GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
2001                         GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
2002                         GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
2003                         GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
2004                     break;
2005           case CTRL_BA:
2006                     ND_PRINT("RA:%s ",
2007                         GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
2008                     break;
2009           case CTRL_PS_POLL:
2010                     ND_PRINT("BSSID:%s TA:%s ",
2011                         GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
2012                         GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
2013                     break;
2014           case CTRL_RTS:
2015                     ND_PRINT("RA:%s TA:%s ",
2016                         GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
2017                         GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
2018                     break;
2019           case CTRL_CTS:
2020                     ND_PRINT("RA:%s ",
2021                         GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
2022                     break;
2023           case CTRL_ACK:
2024                     ND_PRINT("RA:%s ",
2025                         GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
2026                     break;
2027           case CTRL_CF_END:
2028                     ND_PRINT("RA:%s BSSID:%s ",
2029                         GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
2030                         GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
2031                     break;
2032           case CTRL_END_ACK:
2033                     ND_PRINT("RA:%s BSSID:%s ",
2034                         GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
2035                         GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
2036                     break;
2037           default:
2038                     /* We shouldn't get here - we should already have quit */
2039                     break;
2040           }
2041 }
2042 
2043 static int
extract_header_length(netdissect_options * ndo,uint16_t fc)2044 extract_header_length(netdissect_options *ndo,
2045                           uint16_t fc)
2046 {
2047           int len;
2048 
2049           switch (FC_TYPE(fc)) {
2050           case T_MGMT:
2051                     return MGMT_HDRLEN;
2052           case T_CTRL:
2053                     switch (FC_SUBTYPE(fc)) {
2054                     case CTRL_CONTROL_WRAPPER:
2055                               return CTRL_CONTROL_WRAPPER_HDRLEN;
2056                     case CTRL_BAR:
2057                               return CTRL_BAR_HDRLEN;
2058                     case CTRL_BA:
2059                               return CTRL_BA_HDRLEN;
2060                     case CTRL_PS_POLL:
2061                               return CTRL_PS_POLL_HDRLEN;
2062                     case CTRL_RTS:
2063                               return CTRL_RTS_HDRLEN;
2064                     case CTRL_CTS:
2065                               return CTRL_CTS_HDRLEN;
2066                     case CTRL_ACK:
2067                               return CTRL_ACK_HDRLEN;
2068                     case CTRL_CF_END:
2069                               return CTRL_END_HDRLEN;
2070                     case CTRL_END_ACK:
2071                               return CTRL_END_ACK_HDRLEN;
2072                     default:
2073                               ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
2074                               return 0;
2075                     }
2076           case T_DATA:
2077                     len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
2078                     if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
2079                               len += 2;
2080                     return len;
2081           default:
2082                     ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
2083                     return 0;
2084           }
2085 }
2086 
2087 static int
extract_mesh_header_length(netdissect_options * ndo,const u_char * p)2088 extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
2089 {
2090           return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
2091 }
2092 
2093 /*
2094  * Print the 802.11 MAC header.
2095  */
2096 static void
ieee_802_11_hdr_print(netdissect_options * ndo,uint16_t fc,const u_char * p,u_int hdrlen,u_int meshdrlen)2097 ieee_802_11_hdr_print(netdissect_options *ndo,
2098                           uint16_t fc, const u_char *p, u_int hdrlen,
2099                           u_int meshdrlen)
2100 {
2101           if (ndo->ndo_vflag) {
2102                     if (FC_MORE_DATA(fc))
2103                               ND_PRINT("More Data ");
2104                     if (FC_MORE_FLAG(fc))
2105                               ND_PRINT("More Fragments ");
2106                     if (FC_POWER_MGMT(fc))
2107                               ND_PRINT("Pwr Mgmt ");
2108                     if (FC_RETRY(fc))
2109                               ND_PRINT("Retry ");
2110                     if (FC_ORDER(fc))
2111                               ND_PRINT("Strictly Ordered ");
2112                     if (FC_PROTECTED(fc))
2113                               ND_PRINT("Protected ");
2114                     if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
2115                               ND_PRINT("%uus ",
2116                                   GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
2117           }
2118           if (meshdrlen != 0) {
2119                     const struct meshcntl_t *mc =
2120                         (const struct meshcntl_t *)(p + hdrlen - meshdrlen);
2121                     u_int ae = GET_U_1(mc->flags) & 3;
2122 
2123                     ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
2124                         GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
2125                     if (ae > 0)
2126                               ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
2127                     if (ae > 1)
2128                               ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
2129                     if (ae > 2)
2130                               ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
2131                     ND_PRINT(") ");
2132           }
2133 
2134           switch (FC_TYPE(fc)) {
2135           case T_MGMT:
2136                     mgmt_header_print(ndo, p);
2137                     break;
2138           case T_CTRL:
2139                     ctrl_header_print(ndo, fc, p);
2140                     break;
2141           case T_DATA:
2142                     data_header_print(ndo, fc, p);
2143                     break;
2144           default:
2145                     break;
2146           }
2147 }
2148 
2149 static u_int
ieee802_11_print(netdissect_options * ndo,const u_char * p,u_int length,u_int orig_caplen,int pad,u_int fcslen)2150 ieee802_11_print(netdissect_options *ndo,
2151                      const u_char *p, u_int length, u_int orig_caplen, int pad,
2152                      u_int fcslen)
2153 {
2154           uint16_t fc;
2155           u_int caplen, hdrlen, meshdrlen;
2156           struct lladdr_info src, dst;
2157           int llc_hdrlen;
2158 
2159           ndo->ndo_protocol = "802.11";
2160           caplen = orig_caplen;
2161           /* Remove FCS, if present */
2162           if (length < fcslen) {
2163                     nd_print_trunc(ndo);
2164                     return caplen;
2165           }
2166           length -= fcslen;
2167           if (caplen > length) {
2168                     /* Amount of FCS in actual packet data, if any */
2169                     fcslen = caplen - length;
2170                     caplen -= fcslen;
2171                     ndo->ndo_snapend -= fcslen;
2172           }
2173 
2174           if (caplen < IEEE802_11_FC_LEN) {
2175                     nd_print_trunc(ndo);
2176                     return orig_caplen;
2177           }
2178 
2179           fc = GET_LE_U_2(p);
2180           hdrlen = extract_header_length(ndo, fc);
2181           if (hdrlen == 0) {
2182                     /* Unknown frame type or control frame subtype; quit. */
2183                     return (0);
2184           }
2185           if (pad)
2186                     hdrlen = roundup2(hdrlen, 4);
2187           if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
2188               DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
2189                     if(!ND_TTEST_1(p + hdrlen)) {
2190                               nd_print_trunc(ndo);
2191                               return hdrlen;
2192                     }
2193                     meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
2194                     hdrlen += meshdrlen;
2195           } else
2196                     meshdrlen = 0;
2197 
2198           if (caplen < hdrlen) {
2199                     nd_print_trunc(ndo);
2200                     return hdrlen;
2201           }
2202 
2203           if (ndo->ndo_eflag)
2204                     ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
2205 
2206           /*
2207            * Go past the 802.11 header.
2208            */
2209           length -= hdrlen;
2210           caplen -= hdrlen;
2211           p += hdrlen;
2212 
2213           src.addr_string = etheraddr_string;
2214           dst.addr_string = etheraddr_string;
2215           switch (FC_TYPE(fc)) {
2216           case T_MGMT:
2217                     get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
2218                     if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
2219                               nd_print_trunc(ndo);
2220                               return hdrlen;
2221                     }
2222                     break;
2223           case T_CTRL:
2224                     if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
2225                               nd_print_trunc(ndo);
2226                               return hdrlen;
2227                     }
2228                     break;
2229           case T_DATA:
2230                     if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
2231                               return hdrlen;      /* no-data frame */
2232                     /* There may be a problem w/ AP not having this bit set */
2233                     if (FC_PROTECTED(fc)) {
2234                               ND_PRINT("Data");
2235                               if (!wep_print(ndo, p)) {
2236                                         nd_print_trunc(ndo);
2237                                         return hdrlen;
2238                               }
2239                     } else {
2240                               get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
2241                               llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
2242                               if (llc_hdrlen < 0) {
2243                                         /*
2244                                          * Some kinds of LLC packet we cannot
2245                                          * handle intelligently
2246                                          */
2247                                         if (!ndo->ndo_suppress_default_print)
2248                                                   ND_DEFAULTPRINT(p, caplen);
2249                                         llc_hdrlen = -llc_hdrlen;
2250                               }
2251                               hdrlen += llc_hdrlen;
2252                     }
2253                     break;
2254           default:
2255                     /* We shouldn't get here - we should already have quit */
2256                     break;
2257           }
2258 
2259           return hdrlen;
2260 }
2261 
2262 /*
2263  * This is the top level routine of the printer.  'p' points
2264  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
2265  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
2266  * is the number of bytes actually captured.
2267  */
2268 void
ieee802_11_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)2269 ieee802_11_if_print(netdissect_options *ndo,
2270                         const struct pcap_pkthdr *h, const u_char *p)
2271 {
2272           ndo->ndo_protocol = "802.11";
2273           ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
2274 }
2275 
2276 
2277 /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
2278 /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp  */
2279 
2280 /*-
2281  * Copyright (c) 2003, 2004 David Young.  All rights reserved.
2282  *
2283  * Redistribution and use in source and binary forms, with or without
2284  * modification, are permitted provided that the following conditions
2285  * are met:
2286  * 1. Redistributions of source code must retain the above copyright
2287  *    notice, this list of conditions and the following disclaimer.
2288  * 2. Redistributions in binary form must reproduce the above copyright
2289  *    notice, this list of conditions and the following disclaimer in the
2290  *    documentation and/or other materials provided with the distribution.
2291  * 3. The name of David Young may not be used to endorse or promote
2292  *    products derived from this software without specific prior
2293  *    written permission.
2294  *
2295  * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
2296  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2297  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2298  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
2299  * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2300  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2301  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2302  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2303  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2304  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2305  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2306  * OF SUCH DAMAGE.
2307  */
2308 
2309 /* A generic radio capture format is desirable. It must be
2310  * rigidly defined (e.g., units for fields should be given),
2311  * and easily extensible.
2312  *
2313  * The following is an extensible radio capture format. It is
2314  * based on a bitmap indicating which fields are present.
2315  *
2316  * I am trying to describe precisely what the application programmer
2317  * should expect in the following, and for that reason I tell the
2318  * units and origin of each measurement (where it applies), or else I
2319  * use sufficiently weaselly language ("is a monotonically nondecreasing
2320  * function of...") that I cannot set false expectations for lawyerly
2321  * readers.
2322  */
2323 
2324 /*
2325  * The radio capture header precedes the 802.11 header.
2326  *
2327  * Note well: all radiotap fields are little-endian.
2328  */
2329 struct ieee80211_radiotap_header {
2330           nd_uint8_t          it_version;         /* Version 0. Only increases
2331                                                    * for drastic changes,
2332                                                    * introduction of compatible
2333                                                    * new fields does not count.
2334                                                    */
2335           nd_uint8_t          it_pad;
2336           nd_uint16_t         it_len;             /* length of the whole
2337                                                    * header in bytes, including
2338                                                    * it_version, it_pad,
2339                                                    * it_len, and data fields.
2340                                                    */
2341           nd_uint32_t         it_present;         /* A bitmap telling which
2342                                                    * fields are present. Set bit 31
2343                                                    * (0x80000000) to extend the
2344                                                    * bitmap by another 32 bits.
2345                                                    * Additional extensions are made
2346                                                    * by setting bit 31.
2347                                                    */
2348 };
2349 
2350 /* Name                                 Data type       Units
2351  * ----                                 ---------       -----
2352  *
2353  * IEEE80211_RADIOTAP_TSFT              uint64_t       microseconds
2354  *
2355  *      Value in microseconds of the MAC's 64-bit 802.11 Time
2356  *      Synchronization Function timer when the first bit of the
2357  *      MPDU arrived at the MAC. For received frames, only.
2358  *
2359  * IEEE80211_RADIOTAP_CHANNEL           2 x uint16_t   MHz, bitmap
2360  *
2361  *      Tx/Rx frequency in MHz, followed by flags (see below).
2362  *        Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
2363  *        represent an HT channel as there is not enough room in
2364  *        the flags word.
2365  *
2366  * IEEE80211_RADIOTAP_FHSS              uint16_t       see below
2367  *
2368  *      For frequency-hopping radios, the hop set (first byte)
2369  *      and pattern (second byte).
2370  *
2371  * IEEE80211_RADIOTAP_RATE              uint8_t        500kb/s or index
2372  *
2373  *      Tx/Rx data rate.  If bit 0x80 is set then it represents an
2374  *        an MCS index and not an IEEE rate.
2375  *
2376  * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t         decibels from
2377  *                                                     one milliwatt (dBm)
2378  *
2379  *      RF signal power at the antenna, decibel difference from
2380  *      one milliwatt.
2381  *
2382  * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t         decibels from
2383  *                                                     one milliwatt (dBm)
2384  *
2385  *      RF noise power at the antenna, decibel difference from one
2386  *      milliwatt.
2387  *
2388  * IEEE80211_RADIOTAP_DB_ANTSIGNAL      uint8_t        decibel (dB)
2389  *
2390  *      RF signal power at the antenna, decibel difference from an
2391  *      arbitrary, fixed reference.
2392  *
2393  * IEEE80211_RADIOTAP_DB_ANTNOISE       uint8_t        decibel (dB)
2394  *
2395  *      RF noise power at the antenna, decibel difference from an
2396  *      arbitrary, fixed reference point.
2397  *
2398  * IEEE80211_RADIOTAP_LOCK_QUALITY      uint16_t       unitless
2399  *
2400  *      Quality of Barker code lock. Unitless. Monotonically
2401  *      nondecreasing with "better" lock strength. Called "Signal
2402  *      Quality" in datasheets.  (Is there a standard way to measure
2403  *      this?)
2404  *
2405  * IEEE80211_RADIOTAP_TX_ATTENUATION    uint16_t       unitless
2406  *
2407  *      Transmit power expressed as unitless distance from max
2408  *      power set at factory calibration.  0 is max power.
2409  *      Monotonically nondecreasing with lower power levels.
2410  *
2411  * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t       decibels (dB)
2412  *
2413  *      Transmit power expressed as decibel distance from max power
2414  *      set at factory calibration.  0 is max power.  Monotonically
2415  *      nondecreasing with lower power levels.
2416  *
2417  * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t         decibels from
2418  *                                                     one milliwatt (dBm)
2419  *
2420  *      Transmit power expressed as dBm (decibels from a 1 milliwatt
2421  *      reference). This is the absolute power level measured at
2422  *      the antenna port.
2423  *
2424  * IEEE80211_RADIOTAP_FLAGS             uint8_t        bitmap
2425  *
2426  *      Properties of transmitted and received frames. See flags
2427  *      defined below.
2428  *
2429  * IEEE80211_RADIOTAP_ANTENNA           uint8_t        antenna index
2430  *
2431  *      Unitless indication of the Rx/Tx antenna for this packet.
2432  *      The first antenna is antenna 0.
2433  *
2434  * IEEE80211_RADIOTAP_RX_FLAGS          uint16_t       bitmap
2435  *
2436  *     Properties of received frames. See flags defined below.
2437  *
2438  * IEEE80211_RADIOTAP_XCHANNEL          uint32_t       bitmap
2439  *                                                uint16_t       MHz
2440  *                                                uint8_t        channel number
2441  *                                                uint8_t        .5 dBm
2442  *
2443  *        Extended channel specification: flags (see below) followed by
2444  *        frequency in MHz, the corresponding IEEE channel number, and
2445  *        finally the maximum regulatory transmit power cap in .5 dBm
2446  *        units.  This property supersedes IEEE80211_RADIOTAP_CHANNEL
2447  *        and only one of the two should be present.
2448  *
2449  * IEEE80211_RADIOTAP_MCS               uint8_t        known
2450  *                                                uint8_t        flags
2451  *                                                uint8_t        mcs
2452  *
2453  *        Bitset indicating which fields have known values, followed
2454  *        by bitset of flag values, followed by the MCS rate index as
2455  *        in IEEE 802.11n.
2456  *
2457  *
2458  * IEEE80211_RADIOTAP_AMPDU_STATUS      u32, u16, u8, u8    unitless
2459  *
2460  *        Contains the AMPDU information for the subframe.
2461  *
2462  * IEEE80211_RADIOTAP_VHT     u16, u8, u8, u8[4], u8, u8, u16
2463  *
2464  *        Contains VHT information about this frame.
2465  *
2466  * IEEE80211_RADIOTAP_VENDOR_NAMESPACE
2467  *                                                uint8_t  OUI[3]
2468  *                                      uint8_t        subspace
2469  *                                      uint16_t       length
2470  *
2471  *     The Vendor Namespace Field contains three sub-fields. The first
2472  *     sub-field is 3 bytes long. It contains the vendor's IEEE 802
2473  *     Organizationally Unique Identifier (OUI). The fourth byte is a
2474  *     vendor-specific "namespace selector."
2475  *
2476  */
2477 enum ieee80211_radiotap_type {
2478           IEEE80211_RADIOTAP_TSFT = 0,
2479           IEEE80211_RADIOTAP_FLAGS = 1,
2480           IEEE80211_RADIOTAP_RATE = 2,
2481           IEEE80211_RADIOTAP_CHANNEL = 3,
2482           IEEE80211_RADIOTAP_FHSS = 4,
2483           IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
2484           IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
2485           IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
2486           IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
2487           IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
2488           IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
2489           IEEE80211_RADIOTAP_ANTENNA = 11,
2490           IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
2491           IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
2492           IEEE80211_RADIOTAP_RX_FLAGS = 14,
2493           /* NB: gap for netbsd definitions */
2494           IEEE80211_RADIOTAP_XCHANNEL = 18,
2495           IEEE80211_RADIOTAP_MCS = 19,
2496           IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
2497           IEEE80211_RADIOTAP_VHT = 21,
2498           IEEE80211_RADIOTAP_NAMESPACE = 29,
2499           IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
2500           IEEE80211_RADIOTAP_EXT = 31
2501 };
2502 
2503 /* channel attributes */
2504 #define   IEEE80211_CHAN_TURBO          0x00010   /* Turbo channel */
2505 #define   IEEE80211_CHAN_CCK  0x00020   /* CCK channel */
2506 #define   IEEE80211_CHAN_OFDM 0x00040   /* OFDM channel */
2507 #define   IEEE80211_CHAN_2GHZ 0x00080   /* 2 GHz spectrum channel. */
2508 #define   IEEE80211_CHAN_5GHZ 0x00100   /* 5 GHz spectrum channel */
2509 #define   IEEE80211_CHAN_PASSIVE        0x00200   /* Only passive scan allowed */
2510 #define   IEEE80211_CHAN_DYN  0x00400   /* Dynamic CCK-OFDM channel */
2511 #define   IEEE80211_CHAN_GFSK 0x00800   /* GFSK channel (FHSS PHY) */
2512 #define   IEEE80211_CHAN_GSM  0x01000   /* 900 MHz spectrum channel */
2513 #define   IEEE80211_CHAN_STURBO         0x02000   /* 11a static turbo channel only */
2514 #define   IEEE80211_CHAN_HALF 0x04000   /* Half rate channel */
2515 #define   IEEE80211_CHAN_QUARTER        0x08000   /* Quarter rate channel */
2516 #define   IEEE80211_CHAN_HT20 0x10000   /* HT 20 channel */
2517 #define   IEEE80211_CHAN_HT40U          0x20000   /* HT 40 channel w/ ext above */
2518 #define   IEEE80211_CHAN_HT40D          0x40000   /* HT 40 channel w/ ext below */
2519 
2520 /* Useful combinations of channel characteristics, borrowed from Ethereal */
2521 #define IEEE80211_CHAN_A \
2522           (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2523 #define IEEE80211_CHAN_B \
2524           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2525 #define IEEE80211_CHAN_G \
2526           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2527 #define IEEE80211_CHAN_TA \
2528           (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
2529 #define IEEE80211_CHAN_TG \
2530           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN  | IEEE80211_CHAN_TURBO)
2531 
2532 
2533 /* For IEEE80211_RADIOTAP_FLAGS */
2534 #define   IEEE80211_RADIOTAP_F_CFP      0x01      /* sent/received
2535                                                              * during CFP
2536                                                              */
2537 #define   IEEE80211_RADIOTAP_F_SHORTPRE 0x02      /* sent/received
2538                                                              * with short
2539                                                              * preamble
2540                                                              */
2541 #define   IEEE80211_RADIOTAP_F_WEP      0x04      /* sent/received
2542                                                              * with WEP encryption
2543                                                              */
2544 #define   IEEE80211_RADIOTAP_F_FRAG     0x08      /* sent/received
2545                                                              * with fragmentation
2546                                                              */
2547 #define   IEEE80211_RADIOTAP_F_FCS      0x10      /* frame includes FCS */
2548 #define   IEEE80211_RADIOTAP_F_DATAPAD  0x20      /* frame has padding between
2549                                                              * 802.11 header and payload
2550                                                              * (to 32-bit boundary)
2551                                                              */
2552 #define   IEEE80211_RADIOTAP_F_BADFCS   0x40      /* does not pass FCS check */
2553 
2554 /* For IEEE80211_RADIOTAP_RX_FLAGS */
2555 #define IEEE80211_RADIOTAP_F_RX_BADFCS  0x0001    /* frame failed crc check */
2556 #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC          0x0002    /* frame failed PLCP CRC check */
2557 
2558 /* For IEEE80211_RADIOTAP_MCS known */
2559 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN              0x01
2560 #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN              0x02      /* MCS index field */
2561 #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN         0x04
2562 #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN              0x08
2563 #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN               0x10
2564 #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN                   0x20
2565 #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN                   0x40
2566 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1                   0x80
2567 
2568 /* For IEEE80211_RADIOTAP_MCS flags */
2569 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK     0x03
2570 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20       0
2571 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40       1
2572 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L      2
2573 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U      3
2574 #define IEEE80211_RADIOTAP_MCS_SHORT_GI           0x04 /* short guard interval */
2575 #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD      0x08
2576 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC           0x10
2577 #define IEEE80211_RADIOTAP_MCS_STBC_MASK          0x60
2578 #define             IEEE80211_RADIOTAP_MCS_STBC_1 1
2579 #define             IEEE80211_RADIOTAP_MCS_STBC_2 2
2580 #define             IEEE80211_RADIOTAP_MCS_STBC_3 3
2581 #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT         5
2582 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0         0x80
2583 
2584 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
2585 #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN             0x0001
2586 #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN                 0x0002
2587 #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN                 0x0004
2588 #define IEEE80211_RADIOTAP_AMPDU_IS_LAST                    0x0008
2589 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR              0x0010
2590 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN  0x0020
2591 
2592 /* For IEEE80211_RADIOTAP_VHT known */
2593 #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN                             0x0001
2594 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN                       0x0002
2595 #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN                   0x0004
2596 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN           0x0008
2597 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN    0x0010
2598 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN                       0x0020
2599 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN                        0x0040
2600 #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN                         0x0080
2601 #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN            0x0100
2602 
2603 /* For IEEE80211_RADIOTAP_VHT flags */
2604 #define IEEE80211_RADIOTAP_VHT_STBC                         0x01
2605 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA                   0x02
2606 #define IEEE80211_RADIOTAP_VHT_SHORT_GI                     0x04
2607 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9               0x08
2608 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM          0x10
2609 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED                   0x20
2610 
2611 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK     0x1f
2612 
2613 #define IEEE80211_RADIOTAP_VHT_NSS_MASK           0x0f
2614 #define IEEE80211_RADIOTAP_VHT_MCS_MASK           0xf0
2615 #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT          4
2616 
2617 #define IEEE80211_RADIOTAP_CODING_LDPC_USERn                          0x01
2618 
2619 #define   IEEE80211_CHAN_FHSS \
2620           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
2621 #define   IEEE80211_CHAN_A \
2622           (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2623 #define   IEEE80211_CHAN_B \
2624           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2625 #define   IEEE80211_CHAN_PUREG \
2626           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
2627 #define   IEEE80211_CHAN_G \
2628           (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2629 
2630 #define   IS_CHAN_FHSS(flags) \
2631           ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
2632 #define   IS_CHAN_A(flags) \
2633           ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
2634 #define   IS_CHAN_B(flags) \
2635           ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
2636 #define   IS_CHAN_PUREG(flags) \
2637           ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
2638 #define   IS_CHAN_G(flags) \
2639           ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
2640 #define   IS_CHAN_ANYG(flags) \
2641           (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
2642 
2643 static void
print_chaninfo(netdissect_options * ndo,uint16_t freq,uint32_t flags,uint32_t presentflags)2644 print_chaninfo(netdissect_options *ndo,
2645                  uint16_t freq, uint32_t flags, uint32_t presentflags)
2646 {
2647           ND_PRINT("%u MHz", freq);
2648           if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
2649                     /*
2650                      * We have the MCS field, so this is 11n, regardless
2651                      * of what the channel flags say.
2652                      */
2653                     ND_PRINT(" 11n");
2654           } else {
2655                     if (IS_CHAN_FHSS(flags))
2656                               ND_PRINT(" FHSS");
2657                     if (IS_CHAN_A(flags)) {
2658                               if (flags & IEEE80211_CHAN_HALF)
2659                                         ND_PRINT(" 11a/10Mhz");
2660                               else if (flags & IEEE80211_CHAN_QUARTER)
2661                                         ND_PRINT(" 11a/5Mhz");
2662                               else
2663                                         ND_PRINT(" 11a");
2664                     }
2665                     if (IS_CHAN_ANYG(flags)) {
2666                               if (flags & IEEE80211_CHAN_HALF)
2667                                         ND_PRINT(" 11g/10Mhz");
2668                               else if (flags & IEEE80211_CHAN_QUARTER)
2669                                         ND_PRINT(" 11g/5Mhz");
2670                               else
2671                                         ND_PRINT(" 11g");
2672                     } else if (IS_CHAN_B(flags))
2673                               ND_PRINT(" 11b");
2674                     if (flags & IEEE80211_CHAN_TURBO)
2675                               ND_PRINT(" Turbo");
2676           }
2677           /*
2678            * These apply to 11n.
2679            */
2680           if (flags & IEEE80211_CHAN_HT20)
2681                     ND_PRINT(" ht/20");
2682           else if (flags & IEEE80211_CHAN_HT40D)
2683                     ND_PRINT(" ht/40-");
2684           else if (flags & IEEE80211_CHAN_HT40U)
2685                     ND_PRINT(" ht/40+");
2686           ND_PRINT(" ");
2687 }
2688 
2689 static int
print_radiotap_field(netdissect_options * ndo,struct cpack_state * s,uint32_t bit,uint8_t * flagsp,uint32_t presentflags)2690 print_radiotap_field(netdissect_options *ndo,
2691                          struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
2692                          uint32_t presentflags)
2693 {
2694           u_int i;
2695           int rc;
2696 
2697           switch (bit) {
2698 
2699           case IEEE80211_RADIOTAP_TSFT: {
2700                     uint64_t tsft;
2701 
2702                     rc = nd_cpack_uint64(ndo, s, &tsft);
2703                     if (rc != 0)
2704                               goto trunc;
2705                     ND_PRINT("%" PRIu64 "us tsft ", tsft);
2706                     break;
2707                     }
2708 
2709           case IEEE80211_RADIOTAP_FLAGS: {
2710                     uint8_t flagsval;
2711 
2712                     rc = nd_cpack_uint8(ndo, s, &flagsval);
2713                     if (rc != 0)
2714                               goto trunc;
2715                     *flagsp = flagsval;
2716                     if (flagsval & IEEE80211_RADIOTAP_F_CFP)
2717                               ND_PRINT("cfp ");
2718                     if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
2719                               ND_PRINT("short preamble ");
2720                     if (flagsval & IEEE80211_RADIOTAP_F_WEP)
2721                               ND_PRINT("wep ");
2722                     if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
2723                               ND_PRINT("fragmented ");
2724                     if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
2725                               ND_PRINT("bad-fcs ");
2726                     break;
2727                     }
2728 
2729           case IEEE80211_RADIOTAP_RATE: {
2730                     uint8_t rate;
2731 
2732                     rc = nd_cpack_uint8(ndo, s, &rate);
2733                     if (rc != 0)
2734                               goto trunc;
2735                     /*
2736                      * XXX On FreeBSD rate & 0x80 means we have an MCS. On
2737                      * Linux and AirPcap it does not.  (What about
2738                      * macOS, NetBSD, OpenBSD, and DragonFly BSD?)
2739                      *
2740                      * This is an issue either for proprietary extensions
2741                      * to 11a or 11g, which do exist, or for 11n
2742                      * implementations that stuff a rate value into
2743                      * this field, which also appear to exist.
2744                      *
2745                      * We currently handle that by assuming that
2746                      * if the 0x80 bit is set *and* the remaining
2747                      * bits have a value between 0 and 15 it's
2748                      * an MCS value, otherwise it's a rate.  If
2749                      * there are cases where systems that use
2750                      * "0x80 + MCS index" for MCS indices > 15,
2751                      * or stuff a rate value here between 64 and
2752                      * 71.5 Mb/s in here, we'll need a preference
2753                      * setting.  Such rates do exist, e.g. 11n
2754                      * MCS 7 at 20 MHz with a long guard interval.
2755                      */
2756                     if (rate >= 0x80 && rate <= 0x8f) {
2757                               /*
2758                                * XXX - we don't know the channel width
2759                                * or guard interval length, so we can't
2760                                * convert this to a data rate.
2761                                *
2762                                * If you want us to show a data rate,
2763                                * use the MCS field, not the Rate field;
2764                                * the MCS field includes not only the
2765                                * MCS index, it also includes bandwidth
2766                                * and guard interval information.
2767                                *
2768                                * XXX - can we get the channel width
2769                                * from XChannel and the guard interval
2770                                * information from Flags, at least on
2771                                * FreeBSD?
2772                                */
2773                               ND_PRINT("MCS %u ", rate & 0x7f);
2774                     } else
2775                               ND_PRINT("%2.1f Mb/s ", .5 * rate);
2776                     break;
2777                     }
2778 
2779           case IEEE80211_RADIOTAP_CHANNEL: {
2780                     uint16_t frequency;
2781                     uint16_t flags;
2782 
2783                     rc = nd_cpack_uint16(ndo, s, &frequency);
2784                     if (rc != 0)
2785                               goto trunc;
2786                     rc = nd_cpack_uint16(ndo, s, &flags);
2787                     if (rc != 0)
2788                               goto trunc;
2789                     /*
2790                      * If CHANNEL and XCHANNEL are both present, skip
2791                      * CHANNEL.
2792                      */
2793                     if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
2794                               break;
2795                     print_chaninfo(ndo, frequency, flags, presentflags);
2796                     break;
2797                     }
2798 
2799           case IEEE80211_RADIOTAP_FHSS: {
2800                     uint8_t hopset;
2801                     uint8_t hoppat;
2802 
2803                     rc = nd_cpack_uint8(ndo, s, &hopset);
2804                     if (rc != 0)
2805                               goto trunc;
2806                     rc = nd_cpack_uint8(ndo, s, &hoppat);
2807                     if (rc != 0)
2808                               goto trunc;
2809                     ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
2810                     break;
2811                     }
2812 
2813           case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
2814                     int8_t dbm_antsignal;
2815 
2816                     rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
2817                     if (rc != 0)
2818                               goto trunc;
2819                     ND_PRINT("%ddBm signal ", dbm_antsignal);
2820                     break;
2821                     }
2822 
2823           case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
2824                     int8_t dbm_antnoise;
2825 
2826                     rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
2827                     if (rc != 0)
2828                               goto trunc;
2829                     ND_PRINT("%ddBm noise ", dbm_antnoise);
2830                     break;
2831                     }
2832 
2833           case IEEE80211_RADIOTAP_LOCK_QUALITY: {
2834                     uint16_t lock_quality;
2835 
2836                     rc = nd_cpack_uint16(ndo, s, &lock_quality);
2837                     if (rc != 0)
2838                               goto trunc;
2839                     ND_PRINT("%u sq ", lock_quality);
2840                     break;
2841                     }
2842 
2843           case IEEE80211_RADIOTAP_TX_ATTENUATION: {
2844                     int16_t tx_attenuation;
2845 
2846                     rc = nd_cpack_int16(ndo, s, &tx_attenuation);
2847                     if (rc != 0)
2848                               goto trunc;
2849                     ND_PRINT("%d tx power ", -tx_attenuation);
2850                     break;
2851                     }
2852 
2853           case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
2854                     int8_t db_tx_attenuation;
2855 
2856                     rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
2857                     if (rc != 0)
2858                               goto trunc;
2859                     ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
2860                     break;
2861                     }
2862 
2863           case IEEE80211_RADIOTAP_DBM_TX_POWER: {
2864                     int8_t dbm_tx_power;
2865 
2866                     rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
2867                     if (rc != 0)
2868                               goto trunc;
2869                     ND_PRINT("%ddBm tx power ", dbm_tx_power);
2870                     break;
2871                     }
2872 
2873           case IEEE80211_RADIOTAP_ANTENNA: {
2874                     uint8_t antenna;
2875 
2876                     rc = nd_cpack_uint8(ndo, s, &antenna);
2877                     if (rc != 0)
2878                               goto trunc;
2879                     ND_PRINT("antenna %u ", antenna);
2880                     break;
2881                     }
2882 
2883           case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
2884                     uint8_t db_antsignal;
2885 
2886                     rc = nd_cpack_uint8(ndo, s, &db_antsignal);
2887                     if (rc != 0)
2888                               goto trunc;
2889                     ND_PRINT("%udB signal ", db_antsignal);
2890                     break;
2891                     }
2892 
2893           case IEEE80211_RADIOTAP_DB_ANTNOISE: {
2894                     uint8_t db_antnoise;
2895 
2896                     rc = nd_cpack_uint8(ndo, s, &db_antnoise);
2897                     if (rc != 0)
2898                               goto trunc;
2899                     ND_PRINT("%udB noise ", db_antnoise);
2900                     break;
2901                     }
2902 
2903           case IEEE80211_RADIOTAP_RX_FLAGS: {
2904                     uint16_t rx_flags;
2905 
2906                     rc = nd_cpack_uint16(ndo, s, &rx_flags);
2907                     if (rc != 0)
2908                               goto trunc;
2909                     /* Do nothing for now */
2910                     break;
2911                     }
2912 
2913           case IEEE80211_RADIOTAP_XCHANNEL: {
2914                     uint32_t flags;
2915                     uint16_t frequency;
2916                     uint8_t channel;
2917                     uint8_t maxpower;
2918 
2919                     rc = nd_cpack_uint32(ndo, s, &flags);
2920                     if (rc != 0)
2921                               goto trunc;
2922                     rc = nd_cpack_uint16(ndo, s, &frequency);
2923                     if (rc != 0)
2924                               goto trunc;
2925                     rc = nd_cpack_uint8(ndo, s, &channel);
2926                     if (rc != 0)
2927                               goto trunc;
2928                     rc = nd_cpack_uint8(ndo, s, &maxpower);
2929                     if (rc != 0)
2930                               goto trunc;
2931                     print_chaninfo(ndo, frequency, flags, presentflags);
2932                     break;
2933                     }
2934 
2935           case IEEE80211_RADIOTAP_MCS: {
2936                     uint8_t known;
2937                     uint8_t flags;
2938                     uint8_t mcs_index;
2939                     static const char *ht_bandwidth[4] = {
2940                               "20 MHz",
2941                               "40 MHz",
2942                               "20 MHz (L)",
2943                               "20 MHz (U)"
2944                     };
2945                     float htrate;
2946 
2947                     rc = nd_cpack_uint8(ndo, s, &known);
2948                     if (rc != 0)
2949                               goto trunc;
2950                     rc = nd_cpack_uint8(ndo, s, &flags);
2951                     if (rc != 0)
2952                               goto trunc;
2953                     rc = nd_cpack_uint8(ndo, s, &mcs_index);
2954                     if (rc != 0)
2955                               goto trunc;
2956                     if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
2957                               /*
2958                                * We know the MCS index.
2959                                */
2960                               if (mcs_index <= MAX_MCS_INDEX) {
2961                                         /*
2962                                          * And it's in-range.
2963                                          */
2964                                         if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
2965                                                   /*
2966                                                    * And we know both the bandwidth and
2967                                                    * the guard interval, so we can look
2968                                                    * up the rate.
2969                                                    */
2970                                                   htrate =
2971                                                             ieee80211_float_htrates
2972                                                                       [mcs_index]
2973                                                                       [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
2974                                                                       [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
2975                                         } else {
2976                                                   /*
2977                                                    * We don't know both the bandwidth
2978                                                    * and the guard interval, so we can
2979                                                    * only report the MCS index.
2980                                                    */
2981                                                   htrate = 0.0;
2982                                         }
2983                               } else {
2984                                         /*
2985                                          * The MCS value is out of range.
2986                                          */
2987                                         htrate = 0.0;
2988                               }
2989                               if (htrate != 0.0) {
2990                                         /*
2991                                          * We have the rate.
2992                                          * Print it.
2993                                          */
2994                                         ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
2995                               } else {
2996                                         /*
2997                                          * We at least have the MCS index.
2998                                          * Print it.
2999                                          */
3000                                         ND_PRINT("MCS %u ", mcs_index);
3001                               }
3002                     }
3003                     if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
3004                               ND_PRINT("%s ",
3005                                         ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
3006                     }
3007                     if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
3008                               ND_PRINT("%s GI ",
3009                                         (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
3010                                         "short" : "long");
3011                     }
3012                     if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
3013                               ND_PRINT("%s ",
3014                                         (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
3015                                         "greenfield" : "mixed");
3016                     }
3017                     if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
3018                               ND_PRINT("%s FEC ",
3019                                         (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
3020                                         "LDPC" : "BCC");
3021                     }
3022                     if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
3023                               ND_PRINT("RX-STBC%u ",
3024                                         (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
3025                     }
3026                     break;
3027                     }
3028 
3029           case IEEE80211_RADIOTAP_AMPDU_STATUS: {
3030                     uint32_t reference_num;
3031                     uint16_t flags;
3032                     uint8_t delim_crc;
3033                     uint8_t reserved;
3034 
3035                     rc = nd_cpack_uint32(ndo, s, &reference_num);
3036                     if (rc != 0)
3037                               goto trunc;
3038                     rc = nd_cpack_uint16(ndo, s, &flags);
3039                     if (rc != 0)
3040                               goto trunc;
3041                     rc = nd_cpack_uint8(ndo, s, &delim_crc);
3042                     if (rc != 0)
3043                               goto trunc;
3044                     rc = nd_cpack_uint8(ndo, s, &reserved);
3045                     if (rc != 0)
3046                               goto trunc;
3047                     /* Do nothing for now */
3048                     break;
3049                     }
3050 
3051           case IEEE80211_RADIOTAP_VHT: {
3052                     uint16_t known;
3053                     uint8_t flags;
3054                     uint8_t bandwidth;
3055                     uint8_t mcs_nss[4];
3056                     uint8_t coding;
3057                     uint8_t group_id;
3058                     uint16_t partial_aid;
3059                     static const char *vht_bandwidth[32] = {
3060                               "20 MHz",
3061                               "40 MHz",
3062                               "20 MHz (L)",
3063                               "20 MHz (U)",
3064                               "80 MHz",
3065                               "80 MHz (L)",
3066                               "80 MHz (U)",
3067                               "80 MHz (LL)",
3068                               "80 MHz (LU)",
3069                               "80 MHz (UL)",
3070                               "80 MHz (UU)",
3071                               "160 MHz",
3072                               "160 MHz (L)",
3073                               "160 MHz (U)",
3074                               "160 MHz (LL)",
3075                               "160 MHz (LU)",
3076                               "160 MHz (UL)",
3077                               "160 MHz (UU)",
3078                               "160 MHz (LLL)",
3079                               "160 MHz (LLU)",
3080                               "160 MHz (LUL)",
3081                               "160 MHz (UUU)",
3082                               "160 MHz (ULL)",
3083                               "160 MHz (ULU)",
3084                               "160 MHz (UUL)",
3085                               "160 MHz (UUU)",
3086                               "unknown (26)",
3087                               "unknown (27)",
3088                               "unknown (28)",
3089                               "unknown (29)",
3090                               "unknown (30)",
3091                               "unknown (31)"
3092                     };
3093 
3094                     rc = nd_cpack_uint16(ndo, s, &known);
3095                     if (rc != 0)
3096                               goto trunc;
3097                     rc = nd_cpack_uint8(ndo, s, &flags);
3098                     if (rc != 0)
3099                               goto trunc;
3100                     rc = nd_cpack_uint8(ndo, s, &bandwidth);
3101                     if (rc != 0)
3102                               goto trunc;
3103                     for (i = 0; i < 4; i++) {
3104                               rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
3105                               if (rc != 0)
3106                                         goto trunc;
3107                     }
3108                     rc = nd_cpack_uint8(ndo, s, &coding);
3109                     if (rc != 0)
3110                               goto trunc;
3111                     rc = nd_cpack_uint8(ndo, s, &group_id);
3112                     if (rc != 0)
3113                               goto trunc;
3114                     rc = nd_cpack_uint16(ndo, s, &partial_aid);
3115                     if (rc != 0)
3116                               goto trunc;
3117                     for (i = 0; i < 4; i++) {
3118                               u_int nss, mcs;
3119                               nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
3120                               mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
3121 
3122                               if (nss == 0)
3123                                         continue;
3124 
3125                               ND_PRINT("User %u MCS %u ", i, mcs);
3126                               ND_PRINT("%s FEC ",
3127                                         (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
3128                                         "LDPC" : "BCC");
3129                     }
3130                     if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
3131                               ND_PRINT("%s ",
3132                                         vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
3133                     }
3134                     if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
3135                               ND_PRINT("%s GI ",
3136                                         (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
3137                                         "short" : "long");
3138                     }
3139                     break;
3140                     }
3141 
3142           default:
3143                     /* this bit indicates a field whose
3144                      * size we do not know, so we cannot
3145                      * proceed.  Just print the bit number.
3146                      */
3147                     ND_PRINT("[bit %u] ", bit);
3148                     return -1;
3149           }
3150 
3151           return 0;
3152 
3153 trunc:
3154           nd_print_trunc(ndo);
3155           return rc;
3156 }
3157 
3158 
3159 static int
print_in_radiotap_namespace(netdissect_options * ndo,struct cpack_state * s,uint8_t * flags,uint32_t presentflags,int bit0)3160 print_in_radiotap_namespace(netdissect_options *ndo,
3161                                   struct cpack_state *s, uint8_t *flags,
3162                                   uint32_t presentflags, int bit0)
3163 {
3164 #define   BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
3165 #define   BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
3166 #define   BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
3167 #define   BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
3168 #define   BITNO_2(x) (((x) & 2) ? 1 : 0)
3169           uint32_t present, next_present;
3170           int bitno;
3171           enum ieee80211_radiotap_type bit;
3172           int rc;
3173 
3174           for (present = presentflags; present; present = next_present) {
3175                     /*
3176                      * Clear the least significant bit that is set.
3177                      */
3178                     next_present = present & (present - 1);
3179 
3180                     /*
3181                      * Get the bit number, within this presence word,
3182                      * of the remaining least significant bit that
3183                      * is set.
3184                      */
3185                     bitno = BITNO_32(present ^ next_present);
3186 
3187                     /*
3188                      * Stop if this is one of the "same meaning
3189                      * in all presence flags" bits.
3190                      */
3191                     if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
3192                               break;
3193 
3194                     /*
3195                      * Get the radiotap bit number of that bit.
3196                      */
3197                     bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
3198 
3199                     rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
3200                     if (rc != 0)
3201                               return rc;
3202           }
3203 
3204           return 0;
3205 }
3206 
3207 u_int
ieee802_11_radio_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3208 ieee802_11_radio_print(netdissect_options *ndo,
3209                            const u_char *p, u_int length, u_int caplen)
3210 {
3211 #define   BIT(n)    (1U << n)
3212 #define   IS_EXTENDED(__p)    \
3213               (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
3214 
3215           struct cpack_state cpacker;
3216           const struct ieee80211_radiotap_header *hdr;
3217           uint32_t presentflags;
3218           const nd_uint32_t *presentp, *last_presentp;
3219           int vendor_namespace;
3220           uint8_t vendor_oui[3];
3221           uint8_t vendor_subnamespace;
3222           uint16_t skip_length;
3223           int bit0;
3224           u_int len;
3225           uint8_t flags;
3226           int pad;
3227           u_int fcslen;
3228 
3229           ndo->ndo_protocol = "802.11_radio";
3230           if (caplen < sizeof(*hdr)) {
3231                     nd_print_trunc(ndo);
3232                     return caplen;
3233           }
3234 
3235           hdr = (const struct ieee80211_radiotap_header *)p;
3236 
3237           len = GET_LE_U_2(hdr->it_len);
3238           if (len < sizeof(*hdr)) {
3239                     /*
3240                      * The length is the length of the entire header, so
3241                      * it must be as large as the fixed-length part of
3242                      * the header.
3243                      */
3244                     nd_print_trunc(ndo);
3245                     return caplen;
3246           }
3247 
3248           /*
3249            * If we don't have the entire radiotap header, just give up.
3250            */
3251           if (caplen < len) {
3252                     nd_print_trunc(ndo);
3253                     return caplen;
3254           }
3255           nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
3256           nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
3257           for (last_presentp = &hdr->it_present;
3258                (const u_char*)(last_presentp + 1) <= p + len &&
3259                IS_EXTENDED(last_presentp);
3260                last_presentp++)
3261             nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
3262 
3263           /* are there more bitmap extensions than bytes in header? */
3264           if ((const u_char*)(last_presentp + 1) > p + len) {
3265                     nd_print_trunc(ndo);
3266                     return caplen;
3267           }
3268 
3269           /*
3270            * Start out at the beginning of the default radiotap namespace.
3271            */
3272           bit0 = 0;
3273           vendor_namespace = 0;
3274           memset(vendor_oui, 0, 3);
3275           vendor_subnamespace = 0;
3276           skip_length = 0;
3277           /* Assume no flags */
3278           flags = 0;
3279           /* Assume no Atheros padding between 802.11 header and body */
3280           pad = 0;
3281           /* Assume no FCS at end of frame */
3282           fcslen = 0;
3283           for (presentp = &hdr->it_present; presentp <= last_presentp;
3284               presentp++) {
3285                     presentflags = GET_LE_U_4(presentp);
3286 
3287                     /*
3288                      * If this is a vendor namespace, we don't handle it.
3289                      */
3290                     if (vendor_namespace) {
3291                               /*
3292                                * Skip past the stuff we don't understand.
3293                                * If we add support for any vendor namespaces,
3294                                * it'd be added here; use vendor_oui and
3295                                * vendor_subnamespace to interpret the fields.
3296                                */
3297                               if (nd_cpack_advance(&cpacker, skip_length) != 0) {
3298                                         /*
3299                                          * Ran out of space in the packet.
3300                                          */
3301                                         break;
3302                               }
3303 
3304                               /*
3305                                * We've skipped it all; nothing more to
3306                                * skip.
3307                                */
3308                               skip_length = 0;
3309                     } else {
3310                               if (print_in_radiotap_namespace(ndo, &cpacker,
3311                                   &flags, presentflags, bit0) != 0) {
3312                                         /*
3313                                          * Fatal error - can't process anything
3314                                          * more in the radiotap header.
3315                                          */
3316                                         break;
3317                               }
3318                     }
3319 
3320                     /*
3321                      * Handle the namespace switch bits; we've already handled
3322                      * the extension bit in all but the last word above.
3323                      */
3324                     switch (presentflags &
3325                         (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
3326 
3327                     case 0:
3328                               /*
3329                                * We're not changing namespaces.
3330                                * advance to the next 32 bits in the current
3331                                * namespace.
3332                                */
3333                               bit0 += 32;
3334                               break;
3335 
3336                     case BIT(IEEE80211_RADIOTAP_NAMESPACE):
3337                               /*
3338                                * We're switching to the radiotap namespace.
3339                                * Reset the presence-bitmap index to 0, and
3340                                * reset the namespace to the default radiotap
3341                                * namespace.
3342                                */
3343                               bit0 = 0;
3344                               vendor_namespace = 0;
3345                               memset(vendor_oui, 0, 3);
3346                               vendor_subnamespace = 0;
3347                               skip_length = 0;
3348                               break;
3349 
3350                     case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
3351                               /*
3352                                * We're switching to a vendor namespace.
3353                                * Reset the presence-bitmap index to 0,
3354                                * note that we're in a vendor namespace,
3355                                * and fetch the fields of the Vendor Namespace
3356                                * item.
3357                                */
3358                               bit0 = 0;
3359                               vendor_namespace = 1;
3360                               if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
3361                                         nd_print_trunc(ndo);
3362                                         break;
3363                               }
3364                               if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
3365                                         nd_print_trunc(ndo);
3366                                         break;
3367                               }
3368                               if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
3369                                         nd_print_trunc(ndo);
3370                                         break;
3371                               }
3372                               if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
3373                                         nd_print_trunc(ndo);
3374                                         break;
3375                               }
3376                               if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
3377                                         nd_print_trunc(ndo);
3378                                         break;
3379                               }
3380                               if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
3381                                         nd_print_trunc(ndo);
3382                                         break;
3383                               }
3384                               break;
3385 
3386                     default:
3387                               /*
3388                                * Illegal combination.  The behavior in this
3389                                * case is undefined by the radiotap spec; we
3390                                * just ignore both bits.
3391                                */
3392                               break;
3393                     }
3394           }
3395 
3396           if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
3397                     pad = 1;  /* Atheros padding */
3398           if (flags & IEEE80211_RADIOTAP_F_FCS)
3399                     fcslen = 4;         /* FCS at end of packet */
3400           return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
3401               fcslen);
3402 #undef BITNO_32
3403 #undef BITNO_16
3404 #undef BITNO_8
3405 #undef BITNO_4
3406 #undef BITNO_2
3407 #undef BIT
3408 }
3409 
3410 static u_int
ieee802_11_radio_avs_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3411 ieee802_11_radio_avs_print(netdissect_options *ndo,
3412                                  const u_char *p, u_int length, u_int caplen)
3413 {
3414           uint32_t caphdr_len;
3415 
3416           ndo->ndo_protocol = "802.11_radio_avs";
3417           if (caplen < 8) {
3418                     nd_print_trunc(ndo);
3419                     return caplen;
3420           }
3421 
3422           caphdr_len = GET_BE_U_4(p + 4);
3423           if (caphdr_len < 8) {
3424                     /*
3425                      * Yow!  The capture header length is claimed not
3426                      * to be large enough to include even the version
3427                      * cookie or capture header length!
3428                      */
3429                     nd_print_trunc(ndo);
3430                     return caplen;
3431           }
3432 
3433           if (caplen < caphdr_len) {
3434                     nd_print_trunc(ndo);
3435                     return caplen;
3436           }
3437 
3438           return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
3439               length - caphdr_len, caplen - caphdr_len, 0, 0);
3440 }
3441 
3442 #define PRISM_HDR_LEN                   144
3443 
3444 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
3445 #define WLANCAP_MAGIC_COOKIE_V1         0x80211001
3446 #define WLANCAP_MAGIC_COOKIE_V2         0x80211002
3447 
3448 /*
3449  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
3450  * containing information such as radio information, which we
3451  * currently ignore.
3452  *
3453  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
3454  * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
3455  * (currently, on Linux, there's no ARPHRD_ type for
3456  * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
3457  * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
3458  * the AVS header, and the first 4 bytes of the header are used to
3459  * indicate whether it's a Prism header or an AVS header).
3460  */
3461 void
prism_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3462 prism_if_print(netdissect_options *ndo,
3463                  const struct pcap_pkthdr *h, const u_char *p)
3464 {
3465           u_int caplen = h->caplen;
3466           u_int length = h->len;
3467           uint32_t msgcode;
3468 
3469           ndo->ndo_protocol = "prism";
3470           if (caplen < 4) {
3471                     nd_print_trunc(ndo);
3472                     ndo->ndo_ll_hdr_len += caplen;
3473                     return;
3474           }
3475 
3476           msgcode = GET_BE_U_4(p);
3477           if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
3478               msgcode == WLANCAP_MAGIC_COOKIE_V2) {
3479                     ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
3480                     return;
3481           }
3482 
3483           if (caplen < PRISM_HDR_LEN) {
3484                     nd_print_trunc(ndo);
3485                     ndo->ndo_ll_hdr_len += caplen;
3486                     return;
3487           }
3488 
3489           p += PRISM_HDR_LEN;
3490           length -= PRISM_HDR_LEN;
3491           caplen -= PRISM_HDR_LEN;
3492           ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
3493           ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
3494 }
3495 
3496 /*
3497  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
3498  * header, containing information such as radio information.
3499  */
3500 void
ieee802_11_radio_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3501 ieee802_11_radio_if_print(netdissect_options *ndo,
3502                                 const struct pcap_pkthdr *h, const u_char *p)
3503 {
3504           ndo->ndo_protocol = "802.11_radio";
3505           ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
3506 }
3507 
3508 /*
3509  * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
3510  * extra header, containing information such as radio information,
3511  * which we currently ignore.
3512  */
3513 void
ieee802_11_radio_avs_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3514 ieee802_11_radio_avs_if_print(netdissect_options *ndo,
3515                                     const struct pcap_pkthdr *h, const u_char *p)
3516 {
3517           ndo->ndo_protocol = "802.11_radio_avs";
3518           ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
3519 }
3520