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