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