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