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