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