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