xref: /freebsd/contrib/tcpdump/print-802_11.c (revision aa64588d28258aef88cc33b8043112e8856948d0)
1 /* $FreeBSD$ */
2 /*
3  * Copyright (c) 2001
4  *	Fortress Technologies, Inc.  All rights reserved.
5  *      Charlie Lenahan (clenahan@fortresstech.com)
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char rcsid[] _U_ =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.47.2.2 2007-12-29 23:25:28 guy Exp $ (LBL)";
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <tcpdump-stdinc.h>
34 
35 #include <stdio.h>
36 #include <pcap.h>
37 #include <string.h>
38 
39 #include "interface.h"
40 #include "addrtoname.h"
41 #include "ethertype.h"
42 
43 #include "extract.h"
44 
45 #include "cpack.h"
46 
47 #include "ieee802_11.h"
48 #include "ieee802_11_radio.h"
49 
50 #define PRINT_SSID(p) \
51 	switch (p.ssid_status) { \
52 	case TRUNCATED: \
53 		return 0; \
54 	case PRESENT: \
55 		printf(" ("); \
56 		fn_print(p.ssid.ssid, NULL); \
57 		printf(")"); \
58 		break; \
59 	case NOT_PRESENT: \
60 		break; \
61 	}
62 
63 #define PRINT_RATE(_sep, _r, _suf) \
64 	printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
65 #define PRINT_RATES(p) \
66 	switch (p.rates_status) { \
67 	case TRUNCATED: \
68 		return 0; \
69 	case PRESENT: \
70 		do { \
71 			int z; \
72 			const char *sep = " ["; \
73 			for (z = 0; z < p.rates.length ; z++) { \
74 				PRINT_RATE(sep, p.rates.rate[z], \
75 					(p.rates.rate[z] & 0x80 ? "*" : "")); \
76 				sep = " "; \
77 			} \
78 			if (p.rates.length != 0) \
79 				printf(" Mbit]"); \
80 		} while (0); \
81 		break; \
82 	case NOT_PRESENT: \
83 		break; \
84 	}
85 
86 #define PRINT_DS_CHANNEL(p) \
87 	switch (p.ds_status) { \
88 	case TRUNCATED: \
89 		return 0; \
90 	case PRESENT: \
91 		printf(" CH: %u", p.ds.channel); \
92 		break; \
93 	case NOT_PRESENT: \
94 		break; \
95 	} \
96 	printf("%s", \
97 	    CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "" );
98 
99 static const int ieee80211_htrates[16] = {
100 	13,		/* IFM_IEEE80211_MCS0 */
101 	26,		/* IFM_IEEE80211_MCS1 */
102 	39,		/* IFM_IEEE80211_MCS2 */
103 	52,		/* IFM_IEEE80211_MCS3 */
104 	78,		/* IFM_IEEE80211_MCS4 */
105 	104,		/* IFM_IEEE80211_MCS5 */
106 	117,		/* IFM_IEEE80211_MCS6 */
107 	130,		/* IFM_IEEE80211_MCS7 */
108 	26,		/* IFM_IEEE80211_MCS8 */
109 	52,		/* IFM_IEEE80211_MCS9 */
110 	78,		/* IFM_IEEE80211_MCS10 */
111 	104,		/* IFM_IEEE80211_MCS11 */
112 	156,		/* IFM_IEEE80211_MCS12 */
113 	208,		/* IFM_IEEE80211_MCS13 */
114 	234,		/* IFM_IEEE80211_MCS14 */
115 	260,		/* IFM_IEEE80211_MCS15 */
116 };
117 #define PRINT_HT_RATE(_sep, _r, _suf) \
118 	printf("%s%.1f%s", _sep, (.5 * ieee80211_htrates[(_r) & 0xf]), _suf)
119 
120 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
121 #define NUM_AUTH_ALGS	(sizeof auth_alg_text / sizeof auth_alg_text[0])
122 
123 static const char *status_text[] = {
124 	"Succesful",						/*  0 */
125 	"Unspecified failure",					/*  1 */
126 	"Reserved",						/*  2 */
127 	"Reserved",						/*  3 */
128 	"Reserved",						/*  4 */
129 	"Reserved",						/*  5 */
130 	"Reserved",						/*  6 */
131 	"Reserved",						/*  7 */
132 	"Reserved",						/*  8 */
133 	"Reserved",						/*  9 */
134 	"Cannot Support all requested capabilities in the Capability "
135 	  "Information field",	  				/* 10 */
136 	"Reassociation denied due to inability to confirm that association "
137 	  "exists",						/* 11 */
138 	"Association denied due to reason outside the scope of the "
139 	  "standard",						/* 12 */
140 	"Responding station does not support the specified authentication "
141 	  "algorithm ",						/* 13 */
142 	"Received an Authentication frame with authentication transaction "
143 	  "sequence number out of expected sequence",		/* 14 */
144 	"Authentication rejected because of challenge failure",	/* 15 */
145 	"Authentication rejected due to timeout waiting for next frame in "
146 	  "sequence",	  					/* 16 */
147 	"Association denied because AP is unable to handle additional"
148 	  "associated stations",	  			/* 17 */
149 	"Association denied due to requesting station not supporting all of "
150 	  "the data rates in BSSBasicRateSet parameter",	/* 18 */
151 	"Association denied due to requesting station not supporting "
152 	  "short preamble operation",				/* 19 */
153 	"Association denied due to requesting station not supporting "
154 	  "PBCC encoding",					/* 20 */
155 	"Association denied due to requesting station not supporting "
156 	  "channel agility",					/* 21 */
157 	"Association request rejected because Spectrum Management "
158 	  "capability is required",				/* 22 */
159 	"Association request rejected because the information in the "
160 	  "Power Capability element is unacceptable",		/* 23 */
161 	"Association request rejected because the information in the "
162 	  "Supported Channels element is unacceptable",		/* 24 */
163 	"Association denied due to requesting station not supporting "
164 	  "short slot operation",				/* 25 */
165 	"Association denied due to requesting station not supporting "
166 	  "DSSS-OFDM operation",				/* 26 */
167 	"Association denied because the requested STA does not support HT "
168 	  "features",						/* 27 */
169 	"Reserved",						/* 28 */
170 	"Association denied because the requested STA does not support "
171 	  "the PCO transition time required by the AP",		/* 29 */
172 	"Reserved",						/* 30 */
173 	"Reserved",						/* 31 */
174 	"Unspecified, QoS-related failure",			/* 32 */
175 	"Association denied due to QAP having insufficient bandwidth "
176 	  "to handle another QSTA",				/* 33 */
177 	"Association denied due to excessive frame loss rates and/or "
178 	  "poor conditions on current operating channel",	/* 34 */
179 	"Association (with QBSS) denied due to requesting station not "
180 	  "supporting the QoS facility",			/* 35 */
181 	"Association denied due to requesting station not supporting "
182 	  "Block Ack",						/* 36 */
183 	"The request has been declined",			/* 37 */
184 	"The request has not been successful as one or more parameters "
185 	  "have invalid values",				/* 38 */
186 	"The TS has not been created because the request cannot be honored. "
187 	  "However, a suggested TSPEC is provided so that the initiating QSTA"
188 	  "may attempt to set another TS with the suggested changes to the "
189 	  "TSPEC",						/* 39 */
190 	"Invalid Information Element",				/* 40 */
191 	"Group Cipher is not valid",				/* 41 */
192 	"Pairwise Cipher is not valid",				/* 42 */
193 	"AKMP is not valid",					/* 43 */
194 	"Unsupported RSN IE version",				/* 44 */
195 	"Invalid RSN IE Capabilities",				/* 45 */
196 	"Cipher suite is rejected per security policy",		/* 46 */
197 	"The TS has not been created. However, the HC may be capable of "
198 	  "creating a TS, in response to a request, after the time indicated "
199 	  "in the TS Delay element",				/* 47 */
200 	"Direct Link is not allowed in the BSS by policy",	/* 48 */
201 	"Destination STA is not present within this QBSS.",	/* 49 */
202 	"The Destination STA is not a QSTA.",			/* 50 */
203 
204 };
205 #define NUM_STATUSES	(sizeof status_text / sizeof status_text[0])
206 
207 static const char *reason_text[] = {
208 	"Reserved",						/* 0 */
209 	"Unspecified reason",					/* 1 */
210 	"Previous authentication no longer valid",  		/* 2 */
211 	"Deauthenticated because sending station is leaving (or has left) "
212 	  "IBSS or ESS",					/* 3 */
213 	"Disassociated due to inactivity",			/* 4 */
214 	"Disassociated because AP is unable to handle all currently "
215 	  " associated stations",				/* 5 */
216 	"Class 2 frame received from nonauthenticated station", /* 6 */
217 	"Class 3 frame received from nonassociated station",	/* 7 */
218 	"Disassociated because sending station is leaving "
219 	  "(or has left) BSS",					/* 8 */
220 	"Station requesting (re)association is not authenticated with "
221 	  "responding station",					/* 9 */
222 	"Disassociated because the information in the Power Capability "
223 	  "element is unacceptable",				/* 10 */
224 	"Disassociated because the information in the SupportedChannels "
225 	  "element is unacceptable",				/* 11 */
226 	"Invalid Information Element",				/* 12 */
227 	"Reserved",						/* 13 */
228 	"Michael MIC failure",					/* 14 */
229 	"4-Way Handshake timeout",				/* 15 */
230 	"Group key update timeout",				/* 16 */
231 	"Information element in 4-Way Handshake different from (Re)Association"
232 	  "Request/Probe Response/Beacon",			/* 17 */
233 	"Group Cipher is not valid",				/* 18 */
234 	"AKMP is not valid",					/* 20 */
235 	"Unsupported RSN IE version",				/* 21 */
236 	"Invalid RSN IE Capabilities",				/* 22 */
237 	"IEEE 802.1X Authentication failed",			/* 23 */
238 	"Cipher suite is rejected per security policy",		/* 24 */
239 	"Reserved",						/* 25 */
240 	"Reserved",						/* 26 */
241 	"Reserved",						/* 27 */
242 	"Reserved",						/* 28 */
243 	"Reserved",						/* 29 */
244 	"Reserved",						/* 30 */
245 	"TS deleted because QoS AP lacks sufficient bandwidth for this "
246 	  "QoS STA due to a change in BSS service characteristics or "
247 	  "operational mode (e.g. an HT BSS change from 40 MHz channel "
248 	  "to 20 MHz channel)",					/* 31 */
249 	"Disassociated for unspecified, QoS-related reason",	/* 32 */
250 	"Disassociated because QoS AP lacks sufficient bandwidth for this "
251 	  "QoS STA",						/* 33 */
252 	"Disassociated because of excessive number of frames that need to be "
253           "acknowledged, but are not acknowledged for AP transmissions "
254 	  "and/or poor channel conditions",			/* 34 */
255 	"Disassociated because STA is transmitting outside the limits "
256 	  "of its TXOPs",					/* 35 */
257 	"Requested from peer STA as the STA is leaving the BSS "
258 	  "(or resetting)",					/* 36 */
259 	"Requested from peer STA as it does not want to use the "
260 	  "mechanism",						/* 37 */
261 	"Requested from peer STA as the STA received frames using the "
262 	  "mechanism for which a set up is required",		/* 38 */
263 	"Requested from peer STA due to time out",		/* 39 */
264 	"Reserved",						/* 40 */
265 	"Reserved",						/* 41 */
266 	"Reserved",						/* 42 */
267 	"Reserved",						/* 43 */
268 	"Reserved",						/* 44 */
269 	"Peer STA does not support the requested cipher suite",	/* 45 */
270 	"Association denied due to requesting STA not supporting HT "
271 	  "features",						/* 46 */
272 };
273 #define NUM_REASONS	(sizeof reason_text / sizeof reason_text[0])
274 
275 static int
276 wep_print(const u_char *p)
277 {
278 	u_int32_t iv;
279 
280 	if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
281 		return 0;
282 	iv = EXTRACT_LE_32BITS(p);
283 
284 	printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
285 	    IV_KEYID(iv));
286 
287 	return 1;
288 }
289 
290 static void
291 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
292 {
293 	/*
294 	 * We haven't seen any elements yet.
295 	 */
296 	pbody->challenge_status = NOT_PRESENT;
297 	pbody->ssid_status = NOT_PRESENT;
298 	pbody->rates_status = NOT_PRESENT;
299 	pbody->ds_status = NOT_PRESENT;
300 	pbody->cf_status = NOT_PRESENT;
301 	pbody->tim_status = NOT_PRESENT;
302 
303 	for (;;) {
304 		if (!TTEST2(*(p + offset), 1))
305 			return;
306 		switch (*(p + offset)) {
307 		case E_SSID:
308 			/* Present, possibly truncated */
309 			pbody->ssid_status = TRUNCATED;
310 			if (!TTEST2(*(p + offset), 2))
311 				return;
312 			memcpy(&pbody->ssid, p + offset, 2);
313 			offset += 2;
314 			if (pbody->ssid.length != 0) {
315 				if (pbody->ssid.length >
316 				    sizeof(pbody->ssid.ssid) - 1)
317 					return;
318 				if (!TTEST2(*(p + offset), pbody->ssid.length))
319 					return;
320 				memcpy(&pbody->ssid.ssid, p + offset,
321 				    pbody->ssid.length);
322 				offset += pbody->ssid.length;
323 			}
324 			pbody->ssid.ssid[pbody->ssid.length] = '\0';
325 			/* Present and not truncated */
326 			pbody->ssid_status = PRESENT;
327 			break;
328 		case E_CHALLENGE:
329 			/* Present, possibly truncated */
330 			pbody->challenge_status = TRUNCATED;
331 			if (!TTEST2(*(p + offset), 2))
332 				return;
333 			memcpy(&pbody->challenge, p + offset, 2);
334 			offset += 2;
335 			if (pbody->challenge.length != 0) {
336 				if (pbody->challenge.length >
337 				    sizeof(pbody->challenge.text) - 1)
338 					return;
339 				if (!TTEST2(*(p + offset), pbody->challenge.length))
340 					return;
341 				memcpy(&pbody->challenge.text, p + offset,
342 				    pbody->challenge.length);
343 				offset += pbody->challenge.length;
344 			}
345 			pbody->challenge.text[pbody->challenge.length] = '\0';
346 			/* Present and not truncated */
347 			pbody->challenge_status = PRESENT;
348 			break;
349 		case E_RATES:
350 			/* Present, possibly truncated */
351 			pbody->rates_status = TRUNCATED;
352 			if (!TTEST2(*(p + offset), 2))
353 				return;
354 			memcpy(&(pbody->rates), p + offset, 2);
355 			offset += 2;
356 			if (pbody->rates.length != 0) {
357 				if (pbody->rates.length > sizeof pbody->rates.rate)
358 					return;
359 				if (!TTEST2(*(p + offset), pbody->rates.length))
360 					return;
361 				memcpy(&pbody->rates.rate, p + offset,
362 				    pbody->rates.length);
363 				offset += pbody->rates.length;
364 			}
365 			/* Present and not truncated */
366 			pbody->rates_status = PRESENT;
367 			break;
368 		case E_DS:
369 			/* Present, possibly truncated */
370 			pbody->ds_status = TRUNCATED;
371 			if (!TTEST2(*(p + offset), 3))
372 				return;
373 			memcpy(&pbody->ds, p + offset, 3);
374 			offset += 3;
375 			/* Present and not truncated */
376 			pbody->ds_status = PRESENT;
377 			break;
378 		case E_CF:
379 			/* Present, possibly truncated */
380 			pbody->cf_status = TRUNCATED;
381 			if (!TTEST2(*(p + offset), 8))
382 				return;
383 			memcpy(&pbody->cf, p + offset, 8);
384 			offset += 8;
385 			/* Present and not truncated */
386 			pbody->cf_status = PRESENT;
387 			break;
388 		case E_TIM:
389 			/* Present, possibly truncated */
390 			pbody->tim_status = TRUNCATED;
391 			if (!TTEST2(*(p + offset), 2))
392 				return;
393 			memcpy(&pbody->tim, p + offset, 2);
394 			offset += 2;
395 			if (!TTEST2(*(p + offset), 3))
396 				return;
397 			memcpy(&pbody->tim.count, p + offset, 3);
398 			offset += 3;
399 
400 			if (pbody->tim.length <= 3)
401 				break;
402 			if (pbody->tim.length - 3 > (int)sizeof pbody->tim.bitmap)
403 				return;
404 			if (!TTEST2(*(p + offset), pbody->tim.length - 3))
405 				return;
406 			memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
407 			    (pbody->tim.length - 3));
408 			offset += pbody->tim.length - 3;
409 			/* Present and not truncated */
410 			pbody->tim_status = PRESENT;
411 			break;
412 		default:
413 #if 0
414 			printf("(1) unhandled element_id (%d)  ",
415 			    *(p + offset) );
416 #endif
417 			if (!TTEST2(*(p + offset), 2))
418 				return;
419 			if (!TTEST2(*(p + offset + 2), *(p + offset + 1)))
420 				return;
421 			offset += *(p + offset + 1) + 2;
422 			break;
423 		}
424 	}
425 }
426 
427 /*********************************************************************************
428  * Print Handle functions for the management frame types
429  *********************************************************************************/
430 
431 static int
432 handle_beacon(const u_char *p)
433 {
434 	struct mgmt_body_t pbody;
435 	int offset = 0;
436 
437 	memset(&pbody, 0, sizeof(pbody));
438 
439 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
440 	    IEEE802_11_CAPINFO_LEN))
441 		return 0;
442 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
443 	offset += IEEE802_11_TSTAMP_LEN;
444 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
445 	offset += IEEE802_11_BCNINT_LEN;
446 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
447 	offset += IEEE802_11_CAPINFO_LEN;
448 
449 	parse_elements(&pbody, p, offset);
450 
451 	PRINT_SSID(pbody);
452 	PRINT_RATES(pbody);
453 	printf(" %s",
454 	    CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
455 	PRINT_DS_CHANNEL(pbody);
456 
457 	return 1;
458 }
459 
460 static int
461 handle_assoc_request(const u_char *p)
462 {
463 	struct mgmt_body_t pbody;
464 	int offset = 0;
465 
466 	memset(&pbody, 0, sizeof(pbody));
467 
468 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
469 		return 0;
470 	pbody.capability_info = EXTRACT_LE_16BITS(p);
471 	offset += IEEE802_11_CAPINFO_LEN;
472 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
473 	offset += IEEE802_11_LISTENINT_LEN;
474 
475 	parse_elements(&pbody, p, offset);
476 
477 	PRINT_SSID(pbody);
478 	PRINT_RATES(pbody);
479 	return 1;
480 }
481 
482 static int
483 handle_assoc_response(const u_char *p)
484 {
485 	struct mgmt_body_t pbody;
486 	int offset = 0;
487 
488 	memset(&pbody, 0, sizeof(pbody));
489 
490 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
491 	    IEEE802_11_AID_LEN))
492 		return 0;
493 	pbody.capability_info = EXTRACT_LE_16BITS(p);
494 	offset += IEEE802_11_CAPINFO_LEN;
495 	pbody.status_code = EXTRACT_LE_16BITS(p+offset);
496 	offset += IEEE802_11_STATUS_LEN;
497 	pbody.aid = EXTRACT_LE_16BITS(p+offset);
498 	offset += IEEE802_11_AID_LEN;
499 
500 	parse_elements(&pbody, p, offset);
501 
502 	printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
503 	    CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
504 	    (pbody.status_code < NUM_STATUSES
505 		? status_text[pbody.status_code]
506 		: "n/a"));
507 
508 	return 1;
509 }
510 
511 static int
512 handle_reassoc_request(const u_char *p)
513 {
514 	struct mgmt_body_t pbody;
515 	int offset = 0;
516 
517 	memset(&pbody, 0, sizeof(pbody));
518 
519 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
520 	    IEEE802_11_AP_LEN))
521 		return 0;
522 	pbody.capability_info = EXTRACT_LE_16BITS(p);
523 	offset += IEEE802_11_CAPINFO_LEN;
524 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
525 	offset += IEEE802_11_LISTENINT_LEN;
526 	memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
527 	offset += IEEE802_11_AP_LEN;
528 
529 	parse_elements(&pbody, p, offset);
530 
531 	PRINT_SSID(pbody);
532 	printf(" AP : %s", etheraddr_string( pbody.ap ));
533 
534 	return 1;
535 }
536 
537 static int
538 handle_reassoc_response(const u_char *p)
539 {
540 	/* Same as a Association Reponse */
541 	return handle_assoc_response(p);
542 }
543 
544 static int
545 handle_probe_request(const u_char *p)
546 {
547 	struct mgmt_body_t  pbody;
548 	int offset = 0;
549 
550 	memset(&pbody, 0, sizeof(pbody));
551 
552 	parse_elements(&pbody, p, offset);
553 
554 	PRINT_SSID(pbody);
555 	PRINT_RATES(pbody);
556 
557 	return 1;
558 }
559 
560 static int
561 handle_probe_response(const u_char *p)
562 {
563 	struct mgmt_body_t  pbody;
564 	int offset = 0;
565 
566 	memset(&pbody, 0, sizeof(pbody));
567 
568 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
569 	    IEEE802_11_CAPINFO_LEN))
570 		return 0;
571 
572 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
573 	offset += IEEE802_11_TSTAMP_LEN;
574 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
575 	offset += IEEE802_11_BCNINT_LEN;
576 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
577 	offset += IEEE802_11_CAPINFO_LEN;
578 
579 	parse_elements(&pbody, p, offset);
580 
581 	PRINT_SSID(pbody);
582 	PRINT_RATES(pbody);
583 	PRINT_DS_CHANNEL(pbody);
584 
585 	return 1;
586 }
587 
588 static int
589 handle_atim(void)
590 {
591 	/* the frame body for ATIM is null. */
592 	return 1;
593 }
594 
595 static int
596 handle_disassoc(const u_char *p)
597 {
598 	struct mgmt_body_t  pbody;
599 
600 	memset(&pbody, 0, sizeof(pbody));
601 
602 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
603 		return 0;
604 	pbody.reason_code = EXTRACT_LE_16BITS(p);
605 
606 	printf(": %s",
607 	    (pbody.reason_code < NUM_REASONS)
608 		? reason_text[pbody.reason_code]
609 		: "Reserved" );
610 
611 	return 1;
612 }
613 
614 static int
615 handle_auth(const u_char *p)
616 {
617 	struct mgmt_body_t  pbody;
618 	int offset = 0;
619 
620 	memset(&pbody, 0, sizeof(pbody));
621 
622 	if (!TTEST2(*p, 6))
623 		return 0;
624 	pbody.auth_alg = EXTRACT_LE_16BITS(p);
625 	offset += 2;
626 	pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
627 	offset += 2;
628 	pbody.status_code = EXTRACT_LE_16BITS(p + offset);
629 	offset += 2;
630 
631 	parse_elements(&pbody, p, offset);
632 
633 	if ((pbody.auth_alg == 1) &&
634 	    ((pbody.auth_trans_seq_num == 2) ||
635 	     (pbody.auth_trans_seq_num == 3))) {
636 		printf(" (%s)-%x [Challenge Text] %s",
637 		    (pbody.auth_alg < NUM_AUTH_ALGS)
638 			? auth_alg_text[pbody.auth_alg]
639 			: "Reserved",
640 		    pbody.auth_trans_seq_num,
641 		    ((pbody.auth_trans_seq_num % 2)
642 		        ? ((pbody.status_code < NUM_STATUSES)
643 			       ? status_text[pbody.status_code]
644 			       : "n/a") : ""));
645 		return 1;
646 	}
647 	printf(" (%s)-%x: %s",
648 	    (pbody.auth_alg < NUM_AUTH_ALGS)
649 		? auth_alg_text[pbody.auth_alg]
650 		: "Reserved",
651 	    pbody.auth_trans_seq_num,
652 	    (pbody.auth_trans_seq_num % 2)
653 	        ? ((pbody.status_code < NUM_STATUSES)
654 		    ? status_text[pbody.status_code]
655 	            : "n/a")
656 	        : "");
657 
658 	return 1;
659 }
660 
661 static int
662 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
663 {
664 	struct mgmt_body_t  pbody;
665 	int offset = 0;
666 	const char *reason = NULL;
667 
668 	memset(&pbody, 0, sizeof(pbody));
669 
670 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
671 		return 0;
672 	pbody.reason_code = EXTRACT_LE_16BITS(p);
673 	offset += IEEE802_11_REASON_LEN;
674 
675 	reason = (pbody.reason_code < NUM_REASONS)
676 			? reason_text[pbody.reason_code]
677 			: "Reserved";
678 
679 	if (eflag) {
680 		printf(": %s", reason);
681 	} else {
682 		printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
683 	}
684 	return 1;
685 }
686 
687 #define	PRINT_HT_ACTION(v) (\
688 	(v) == 0 ? printf("TxChWidth") : \
689 	(v) == 1 ? printf("MIMOPwrSave") : \
690 		   printf("Act#%d", (v)) \
691 )
692 #define	PRINT_BA_ACTION(v) (\
693 	(v) == 0 ? printf("ADDBA Request") : \
694 	(v) == 1 ? printf("ADDBA Response") : \
695 	(v) == 2 ? printf("DELBA") : \
696 		   printf("Act#%d", (v)) \
697 )
698 #define	PRINT_MESHLINK_ACTION(v) (\
699 	(v) == 0 ? printf("Request") : \
700 	(v) == 1 ? printf("Report") : \
701 		   printf("Act#%d", (v)) \
702 )
703 #define	PRINT_MESHPEERING_ACTION(v) (\
704 	(v) == 0 ? printf("Open") : \
705 	(v) == 1 ? printf("Confirm") : \
706 	(v) == 2 ? printf("Close") : \
707 		   printf("Act#%d", (v)) \
708 )
709 #define	PRINT_MESHPATH_ACTION(v) (\
710 	(v) == 0 ? printf("Request") : \
711 	(v) == 1 ? printf("Report") : \
712 	(v) == 2 ? printf("Error") : \
713 	(v) == 3 ? printf("RootAnnouncement") : \
714 		   printf("Act#%d", (v)) \
715 )
716 
717 static int
718 handle_action(const struct mgmt_header_t *pmh, const u_char *p)
719 {
720 	if (!TTEST2(*p, 2))
721 		return 0;
722 	if (eflag) {
723 		printf(": ");
724 	} else {
725 		printf(" (%s): ", etheraddr_string(pmh->sa));
726 	}
727 	switch (p[0]) {
728 	case 0: printf("Spectrum Management Act#%d", p[1]); break;
729 	case 1: printf("QoS Act#%d", p[1]); break;
730 	case 2: printf("DLS Act#%d", p[1]); break;
731 	case 3: printf("BA "); PRINT_BA_ACTION(p[1]); break;
732 	case 7: printf("HT "); PRINT_HT_ACTION(p[1]); break;
733 	case 13: printf("MeshLMetric "); PRINT_MESHLINK_ACTION(p[1]); break;
734 	case 15: printf("Interwork Act#%d", p[1]); break;
735 	case 16: printf("Resource Act#%d", p[1]); break;
736 	case 17: printf("Proxy Act#%d", p[1]); break;
737 	case 30: printf("MeshPeering "); PRINT_MESHPEERING_ACTION(p[1]); break;
738 	case 32: printf("MeshPath "); PRINT_MESHPATH_ACTION(p[1]); break;
739 	case 127: printf("Vendor Act#%d", p[1]); break;
740 	default:
741 		printf("Reserved(%d) Act#%d", p[0], p[1]);
742 		break;
743 	}
744 	return 1;
745 }
746 
747 
748 /*********************************************************************************
749  * Print Body funcs
750  *********************************************************************************/
751 
752 
753 static int
754 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
755     const u_char *p)
756 {
757 	switch (FC_SUBTYPE(fc)) {
758 	case ST_ASSOC_REQUEST:
759 		printf("Assoc Request");
760 		return handle_assoc_request(p);
761 	case ST_ASSOC_RESPONSE:
762 		printf("Assoc Response");
763 		return handle_assoc_response(p);
764 	case ST_REASSOC_REQUEST:
765 		printf("ReAssoc Request");
766 		return handle_reassoc_request(p);
767 	case ST_REASSOC_RESPONSE:
768 		printf("ReAssoc Response");
769 		return handle_reassoc_response(p);
770 	case ST_PROBE_REQUEST:
771 		printf("Probe Request");
772 		return handle_probe_request(p);
773 	case ST_PROBE_RESPONSE:
774 		printf("Probe Response");
775 		return handle_probe_response(p);
776 	case ST_BEACON:
777 		printf("Beacon");
778 		return handle_beacon(p);
779 	case ST_ATIM:
780 		printf("ATIM");
781 		return handle_atim();
782 	case ST_DISASSOC:
783 		printf("Disassociation");
784 		return handle_disassoc(p);
785 	case ST_AUTH:
786 		printf("Authentication");
787 		if (!TTEST2(*p, 3))
788 			return 0;
789 		if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
790 			printf("Authentication (Shared-Key)-3 ");
791 			return wep_print(p);
792 		}
793 		return handle_auth(p);
794 	case ST_DEAUTH:
795 		printf("DeAuthentication");
796 		return handle_deauth(pmh, p);
797 		break;
798 	case ST_ACTION:
799 		printf("Action");
800 		return handle_action(pmh, p);
801 		break;
802 	default:
803 		printf("Unhandled Management subtype(%x)",
804 		    FC_SUBTYPE(fc));
805 		return 1;
806 	}
807 }
808 
809 
810 /*********************************************************************************
811  * Handles printing all the control frame types
812  *********************************************************************************/
813 
814 static int
815 ctrl_body_print(u_int16_t fc, const u_char *p)
816 {
817 	switch (FC_SUBTYPE(fc)) {
818 	case CTRL_BAR:
819 		printf("BAR");
820 		if (!TTEST2(*p, CTRL_BAR_HDRLEN))
821 			return 0;
822 		if (!eflag)
823 			printf(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
824 			    etheraddr_string(((const struct ctrl_bar_t *)p)->ra),
825 			    etheraddr_string(((const struct ctrl_bar_t *)p)->ta),
826 			    EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->ctl)),
827 			    EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->seq)));
828 		break;
829 	case CTRL_BA:
830 		printf("BA");
831 		if (!TTEST2(*p, CTRL_BA_HDRLEN))
832 			return 0;
833 		if (!eflag)
834 			printf(" RA:%s ",
835 			    etheraddr_string(((const struct ctrl_ba_t *)p)->ra));
836 		break;
837 	case CTRL_PS_POLL:
838 		printf("Power Save-Poll");
839 		if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
840 			return 0;
841 		printf(" AID(%x)",
842 		    EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
843 		break;
844 	case CTRL_RTS:
845 		printf("Request-To-Send");
846 		if (!TTEST2(*p, CTRL_RTS_HDRLEN))
847 			return 0;
848 		if (!eflag)
849 			printf(" TA:%s ",
850 			    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
851 		break;
852 	case CTRL_CTS:
853 		printf("Clear-To-Send");
854 		if (!TTEST2(*p, CTRL_CTS_HDRLEN))
855 			return 0;
856 		if (!eflag)
857 			printf(" RA:%s ",
858 			    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
859 		break;
860 	case CTRL_ACK:
861 		printf("Acknowledgment");
862 		if (!TTEST2(*p, CTRL_ACK_HDRLEN))
863 			return 0;
864 		if (!eflag)
865 			printf(" RA:%s ",
866 			    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
867 		break;
868 	case CTRL_CF_END:
869 		printf("CF-End");
870 		if (!TTEST2(*p, CTRL_END_HDRLEN))
871 			return 0;
872 		if (!eflag)
873 			printf(" RA:%s ",
874 			    etheraddr_string(((const struct ctrl_end_t *)p)->ra));
875 		break;
876 	case CTRL_END_ACK:
877 		printf("CF-End+CF-Ack");
878 		if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
879 			return 0;
880 		if (!eflag)
881 			printf(" RA:%s ",
882 			    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
883 		break;
884 	default:
885 		printf("Unknown Ctrl Subtype");
886 	}
887 	return 1;
888 }
889 
890 /*
891  * Print Header funcs
892  */
893 
894 /*
895  *  Data Frame - Address field contents
896  *
897  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
898  *    0    |  0      |  DA    | SA     | BSSID  | n/a
899  *    0    |  1      |  DA    | BSSID  | SA     | n/a
900  *    1    |  0      |  BSSID | SA     | DA     | n/a
901  *    1    |  1      |  RA    | TA     | DA     | SA
902  */
903 
904 static void
905 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
906     const u_int8_t **dstp)
907 {
908 	u_int subtype = FC_SUBTYPE(fc);
909 
910 	if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
911 	    DATA_FRAME_IS_QOS(subtype)) {
912 		printf("CF ");
913 		if (DATA_FRAME_IS_CF_ACK(subtype)) {
914 			if (DATA_FRAME_IS_CF_POLL(subtype))
915 				printf("Ack/Poll");
916 			else
917 				printf("Ack");
918 		} else {
919 			if (DATA_FRAME_IS_CF_POLL(subtype))
920 				printf("Poll");
921 		}
922 		if (DATA_FRAME_IS_QOS(subtype))
923 			printf("+QoS");
924 		printf(" ");
925 	}
926 
927 #define ADDR1  (p + 4)
928 #define ADDR2  (p + 10)
929 #define ADDR3  (p + 16)
930 #define ADDR4  (p + 24)
931 
932 	if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
933 		if (srcp != NULL)
934 			*srcp = ADDR2;
935 		if (dstp != NULL)
936 			*dstp = ADDR1;
937 		if (!eflag)
938 			return;
939 		printf("DA:%s SA:%s BSSID:%s ",
940 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
941 		    etheraddr_string(ADDR3));
942 	} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
943 		if (srcp != NULL)
944 			*srcp = ADDR3;
945 		if (dstp != NULL)
946 			*dstp = ADDR1;
947 		if (!eflag)
948 			return;
949 		printf("DA:%s BSSID:%s SA:%s ",
950 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
951 		    etheraddr_string(ADDR3));
952 	} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
953 		if (srcp != NULL)
954 			*srcp = ADDR2;
955 		if (dstp != NULL)
956 			*dstp = ADDR3;
957 		if (!eflag)
958 			return;
959 		printf("BSSID:%s SA:%s DA:%s ",
960 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
961 		    etheraddr_string(ADDR3));
962 	} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
963 		if (srcp != NULL)
964 			*srcp = ADDR4;
965 		if (dstp != NULL)
966 			*dstp = ADDR3;
967 		if (!eflag)
968 			return;
969 		printf("RA:%s TA:%s DA:%s SA:%s ",
970 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
971 		    etheraddr_string(ADDR3), etheraddr_string(ADDR4));
972 	}
973 
974 #undef ADDR1
975 #undef ADDR2
976 #undef ADDR3
977 #undef ADDR4
978 }
979 
980 static void
981 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
982     const u_int8_t **dstp)
983 {
984 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
985 
986 	if (srcp != NULL)
987 		*srcp = hp->sa;
988 	if (dstp != NULL)
989 		*dstp = hp->da;
990 	if (!eflag)
991 		return;
992 
993 	printf("BSSID:%s DA:%s SA:%s ",
994 	    etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
995 	    etheraddr_string((hp)->sa));
996 }
997 
998 static void
999 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
1000     const u_int8_t **dstp)
1001 {
1002 	if (srcp != NULL)
1003 		*srcp = NULL;
1004 	if (dstp != NULL)
1005 		*dstp = NULL;
1006 	if (!eflag)
1007 		return;
1008 
1009 	switch (FC_SUBTYPE(fc)) {
1010 	case CTRL_BAR:
1011 		printf(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1012 		    etheraddr_string(((const struct ctrl_bar_t *)p)->ra),
1013 		    etheraddr_string(((const struct ctrl_bar_t *)p)->ta),
1014 		    EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->ctl)),
1015 		    EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->seq)));
1016 		break;
1017 	case CTRL_BA:
1018 		printf("RA:%s ",
1019 		    etheraddr_string(((const struct ctrl_ba_t *)p)->ra));
1020 		break;
1021 	case CTRL_PS_POLL:
1022 		printf("BSSID:%s TA:%s ",
1023 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
1024 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
1025 		break;
1026 	case CTRL_RTS:
1027 		printf("RA:%s TA:%s ",
1028 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
1029 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
1030 		break;
1031 	case CTRL_CTS:
1032 		printf("RA:%s ",
1033 		    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
1034 		break;
1035 	case CTRL_ACK:
1036 		printf("RA:%s ",
1037 		    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
1038 		break;
1039 	case CTRL_CF_END:
1040 		printf("RA:%s BSSID:%s ",
1041 		    etheraddr_string(((const struct ctrl_end_t *)p)->ra),
1042 		    etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
1043 		break;
1044 	case CTRL_END_ACK:
1045 		printf("RA:%s BSSID:%s ",
1046 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
1047 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
1048 		break;
1049 	default:
1050 		printf("(H) Unknown Ctrl Subtype");
1051 		break;
1052 	}
1053 }
1054 
1055 static int
1056 extract_header_length(u_int16_t fc)
1057 {
1058 	int len;
1059 
1060 	switch (FC_TYPE(fc)) {
1061 	case T_MGMT:
1062 		return MGMT_HDRLEN;
1063 	case T_CTRL:
1064 		switch (FC_SUBTYPE(fc)) {
1065 		case CTRL_BAR:
1066 			return CTRL_BAR_HDRLEN;
1067 		case CTRL_PS_POLL:
1068 			return CTRL_PS_POLL_HDRLEN;
1069 		case CTRL_RTS:
1070 			return CTRL_RTS_HDRLEN;
1071 		case CTRL_CTS:
1072 			return CTRL_CTS_HDRLEN;
1073 		case CTRL_ACK:
1074 			return CTRL_ACK_HDRLEN;
1075 		case CTRL_CF_END:
1076 			return CTRL_END_HDRLEN;
1077 		case CTRL_END_ACK:
1078 			return CTRL_END_ACK_HDRLEN;
1079 		default:
1080 			return 0;
1081 		}
1082 	case T_DATA:
1083 		len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
1084 		if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
1085 			len += 2;
1086 		return len;
1087 	default:
1088 		printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
1089 		return 0;
1090 	}
1091 }
1092 
1093 static int
1094 extract_mesh_header_length(const u_char *p)
1095 {
1096 	return (p[0] &~ 3) ? 0 : 6*(1 + (p[0] & 3));
1097 }
1098 
1099 /*
1100  * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
1101  * to point to the source and destination MAC addresses in any case if
1102  * "srcp" and "dstp" aren't null.
1103  */
1104 static void
1105 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, u_int hdrlen,
1106     u_int meshdrlen, const u_int8_t **srcp, const u_int8_t **dstp)
1107 {
1108 	if (vflag) {
1109 		if (FC_MORE_DATA(fc))
1110 			printf("More Data ");
1111 		if (FC_MORE_FLAG(fc))
1112 			printf("More Fragments ");
1113 		if (FC_POWER_MGMT(fc))
1114 			printf("Pwr Mgmt ");
1115 		if (FC_RETRY(fc))
1116 			printf("Retry ");
1117 		if (FC_ORDER(fc))
1118 			printf("Strictly Ordered ");
1119 		if (FC_WEP(fc))
1120 			printf("WEP Encrypted ");
1121 		if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
1122 			printf("%dus ",
1123 			    EXTRACT_LE_16BITS(
1124 			        &((const struct mgmt_header_t *)p)->duration));
1125 	}
1126 	if (meshdrlen != 0) {
1127 		const struct meshcntl_t *mc =
1128 		    (const struct meshcntl_t *)&p[hdrlen - meshdrlen];
1129 		int ae = mc->flags & 3;
1130 
1131 		printf("MeshData (AE %d TTL %u seq %u", ae, mc->ttl,
1132 		    EXTRACT_LE_32BITS(mc->seq));
1133 		if (ae > 0)
1134 			printf(" A4:%s", etheraddr_string(mc->addr4));
1135 		if (ae > 1)
1136 			printf(" A5:%s", etheraddr_string(mc->addr5));
1137 		if (ae > 2)
1138 			printf(" A6:%s", etheraddr_string(mc->addr6));
1139 		printf(") ");
1140 	}
1141 
1142 	switch (FC_TYPE(fc)) {
1143 	case T_MGMT:
1144 		mgmt_header_print(p, srcp, dstp);
1145 		break;
1146 	case T_CTRL:
1147 		ctrl_header_print(fc, p, srcp, dstp);
1148 		break;
1149 	case T_DATA:
1150 		data_header_print(fc, p, srcp, dstp);
1151 		break;
1152 	default:
1153 		printf("(header) unknown IEEE802.11 frame type (%d)",
1154 		    FC_TYPE(fc));
1155 		*srcp = NULL;
1156 		*dstp = NULL;
1157 		break;
1158 	}
1159 }
1160 
1161 #ifndef roundup2
1162 #define	roundup2(x, y)	(((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
1163 #endif
1164 
1165 static u_int
1166 ieee802_11_print(const u_char *p, u_int length, u_int caplen, int pad)
1167 {
1168 	u_int16_t fc;
1169 	u_int hdrlen, meshdrlen;
1170 	const u_int8_t *src, *dst;
1171 	u_short extracted_ethertype;
1172 
1173 	if (caplen < IEEE802_11_FC_LEN) {
1174 		printf("[|802.11]");
1175 		return caplen;
1176 	}
1177 
1178 	fc = EXTRACT_LE_16BITS(p);
1179 	hdrlen = extract_header_length(fc);
1180 	if (pad)
1181 		hdrlen = roundup2(hdrlen, 4);
1182 	if (FC_TYPE(fc) == T_DATA && DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
1183 		meshdrlen = extract_mesh_header_length(p+hdrlen);
1184 		hdrlen += meshdrlen;
1185 	} else
1186 		meshdrlen = 0;
1187 
1188 
1189 	if (caplen < hdrlen) {
1190 		printf("[|802.11]");
1191 		return hdrlen;
1192 	}
1193 
1194 	ieee_802_11_hdr_print(fc, p, hdrlen, meshdrlen, &src, &dst);
1195 
1196 	/*
1197 	 * Go past the 802.11 header.
1198 	 */
1199 	length -= hdrlen;
1200 	caplen -= hdrlen;
1201 	p += hdrlen;
1202 
1203 	switch (FC_TYPE(fc)) {
1204 	case T_MGMT:
1205 		if (!mgmt_body_print(fc,
1206 		    (const struct mgmt_header_t *)(p - hdrlen), p)) {
1207 			printf("[|802.11]");
1208 			return hdrlen;
1209 		}
1210 		break;
1211 	case T_CTRL:
1212 		if (!ctrl_body_print(fc, p - hdrlen)) {
1213 			printf("[|802.11]");
1214 			return hdrlen;
1215 		}
1216 		break;
1217 	case T_DATA:
1218 		if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
1219 			return hdrlen;	/* no-data frame */
1220 		/* There may be a problem w/ AP not having this bit set */
1221 		if (FC_WEP(fc)) {
1222 			if (!wep_print(p)) {
1223 				printf("[|802.11]");
1224 				return hdrlen;
1225 			}
1226 		} else if (llc_print(p, length, caplen, dst, src,
1227 		    &extracted_ethertype) == 0) {
1228 			/*
1229 			 * Some kinds of LLC packet we cannot
1230 			 * handle intelligently
1231 			 */
1232 			if (!eflag)
1233 				ieee_802_11_hdr_print(fc, p - hdrlen, hdrlen,
1234 				    meshdrlen, NULL, NULL);
1235 			if (extracted_ethertype)
1236 				printf("(LLC %s) ",
1237 				    etherproto_string(
1238 				        htons(extracted_ethertype)));
1239 			if (!suppress_default_print)
1240 				default_print(p, caplen);
1241 		}
1242 		break;
1243 	default:
1244 		printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
1245 		break;
1246 	}
1247 
1248 	return hdrlen;
1249 }
1250 
1251 /*
1252  * This is the top level routine of the printer.  'p' points
1253  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
1254  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
1255  * is the number of bytes actually captured.
1256  */
1257 u_int
1258 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
1259 {
1260 	return ieee802_11_print(p, h->len, h->caplen, 0);
1261 }
1262 
1263 #define	IEEE80211_CHAN_FHSS \
1264 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
1265 #define	IEEE80211_CHAN_A \
1266 	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
1267 #define	IEEE80211_CHAN_B \
1268 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
1269 #define	IEEE80211_CHAN_PUREG \
1270 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
1271 #define	IEEE80211_CHAN_G \
1272 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
1273 
1274 #define	IS_CHAN_FHSS(flags) \
1275 	((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
1276 #define	IS_CHAN_A(flags) \
1277 	((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
1278 #define	IS_CHAN_B(flags) \
1279 	((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
1280 #define	IS_CHAN_PUREG(flags) \
1281 	((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
1282 #define	IS_CHAN_G(flags) \
1283 	((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
1284 #define	IS_CHAN_ANYG(flags) \
1285 	(IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
1286 
1287 static void
1288 print_chaninfo(int freq, int flags)
1289 {
1290 	printf("%u MHz", freq);
1291 	if (IS_CHAN_FHSS(flags))
1292 		printf(" FHSS");
1293 	if (IS_CHAN_A(flags)) {
1294 		if (flags & IEEE80211_CHAN_HALF)
1295 			printf(" 11a/10Mhz");
1296 		else if (flags & IEEE80211_CHAN_QUARTER)
1297 			printf(" 11a/5Mhz");
1298 		else
1299 			printf(" 11a");
1300 	}
1301 	if (IS_CHAN_ANYG(flags)) {
1302 		if (flags & IEEE80211_CHAN_HALF)
1303 			printf(" 11g/10Mhz");
1304 		else if (flags & IEEE80211_CHAN_QUARTER)
1305 			printf(" 11g/5Mhz");
1306 		else
1307 			printf(" 11g");
1308 	} else if (IS_CHAN_B(flags))
1309 		printf(" 11b");
1310 	if (flags & IEEE80211_CHAN_TURBO)
1311 		printf(" Turbo");
1312 	if (flags & IEEE80211_CHAN_HT20)
1313 		printf(" ht/20");
1314 	else if (flags & IEEE80211_CHAN_HT40D)
1315 		printf(" ht/40-");
1316 	else if (flags & IEEE80211_CHAN_HT40U)
1317 		printf(" ht/40+");
1318 	printf(" ");
1319 }
1320 
1321 static int
1322 print_radiotap_field(struct cpack_state *s, u_int32_t bit, int *pad)
1323 {
1324 	union {
1325 		int8_t		i8;
1326 		u_int8_t	u8;
1327 		int16_t		i16;
1328 		u_int16_t	u16;
1329 		u_int32_t	u32;
1330 		u_int64_t	u64;
1331 	} u, u2, u3, u4;
1332 	int rc;
1333 
1334 	switch (bit) {
1335 	case IEEE80211_RADIOTAP_FLAGS:
1336 		rc = cpack_uint8(s, &u.u8);
1337 		if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD)
1338 			*pad = 1;
1339 		break;
1340 	case IEEE80211_RADIOTAP_RATE:
1341 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1342 	case IEEE80211_RADIOTAP_DB_ANTNOISE:
1343 	case IEEE80211_RADIOTAP_ANTENNA:
1344 		rc = cpack_uint8(s, &u.u8);
1345 		break;
1346 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1347 	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1348 		rc = cpack_int8(s, &u.i8);
1349 		break;
1350 	case IEEE80211_RADIOTAP_CHANNEL:
1351 		rc = cpack_uint16(s, &u.u16);
1352 		if (rc != 0)
1353 			break;
1354 		rc = cpack_uint16(s, &u2.u16);
1355 		break;
1356 	case IEEE80211_RADIOTAP_FHSS:
1357 	case IEEE80211_RADIOTAP_LOCK_QUALITY:
1358 	case IEEE80211_RADIOTAP_TX_ATTENUATION:
1359 		rc = cpack_uint16(s, &u.u16);
1360 		break;
1361 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1362 		rc = cpack_uint8(s, &u.u8);
1363 		break;
1364 	case IEEE80211_RADIOTAP_DBM_TX_POWER:
1365 		rc = cpack_int8(s, &u.i8);
1366 		break;
1367 	case IEEE80211_RADIOTAP_TSFT:
1368 		rc = cpack_uint64(s, &u.u64);
1369 		break;
1370 	case IEEE80211_RADIOTAP_XCHANNEL:
1371 		rc = cpack_uint32(s, &u.u32);
1372 		if (rc != 0)
1373 			break;
1374 		rc = cpack_uint16(s, &u2.u16);
1375 		if (rc != 0)
1376 			break;
1377 		rc = cpack_uint8(s, &u3.u8);
1378 		if (rc != 0)
1379 			break;
1380 		rc = cpack_uint8(s, &u4.u8);
1381 		break;
1382 	default:
1383 		/* this bit indicates a field whose
1384 		 * size we do not know, so we cannot
1385 		 * proceed.
1386 		 */
1387 		printf("[0x%08x] ", bit);
1388 		return -1;
1389 	}
1390 
1391 	if (rc != 0) {
1392 		printf("[|802.11]");
1393 		return rc;
1394 	}
1395 
1396 	switch (bit) {
1397 	case IEEE80211_RADIOTAP_CHANNEL:
1398 		print_chaninfo(u.u16, u2.u16);
1399 		break;
1400 	case IEEE80211_RADIOTAP_FHSS:
1401 		printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
1402 		break;
1403 	case IEEE80211_RADIOTAP_RATE:
1404 		if (u.u8 & 0x80)
1405 			PRINT_HT_RATE("", u.u8, " Mb/s ");
1406 		else
1407 			PRINT_RATE("", u.u8, " Mb/s ");
1408 		break;
1409 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1410 		printf("%ddB signal ", u.i8);
1411 		break;
1412 	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1413 		printf("%ddB noise ", u.i8);
1414 		break;
1415 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1416 		printf("%ddB signal ", u.u8);
1417 		break;
1418 	case IEEE80211_RADIOTAP_DB_ANTNOISE:
1419 		printf("%ddB noise ", u.u8);
1420 		break;
1421 	case IEEE80211_RADIOTAP_LOCK_QUALITY:
1422 		printf("%u sq ", u.u16);
1423 		break;
1424 	case IEEE80211_RADIOTAP_TX_ATTENUATION:
1425 		printf("%d tx power ", -(int)u.u16);
1426 		break;
1427 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1428 		printf("%ddB tx power ", -(int)u.u8);
1429 		break;
1430 	case IEEE80211_RADIOTAP_DBM_TX_POWER:
1431 		printf("%ddBm tx power ", u.i8);
1432 		break;
1433 	case IEEE80211_RADIOTAP_FLAGS:
1434 		if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
1435 			printf("cfp ");
1436 		if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
1437 			printf("short preamble ");
1438 		if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
1439 			printf("wep ");
1440 		if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
1441 			printf("fragmented ");
1442 		if (u.u8 & IEEE80211_RADIOTAP_F_BADFCS)
1443 			printf("bad-fcs ");
1444 		break;
1445 	case IEEE80211_RADIOTAP_ANTENNA:
1446 		printf("antenna %d ", u.u8);
1447 		break;
1448 	case IEEE80211_RADIOTAP_TSFT:
1449 		printf("%" PRIu64 "us tsft ", u.u64);
1450 		break;
1451 	case IEEE80211_RADIOTAP_XCHANNEL:
1452 		print_chaninfo(u2.u16, u.u32);
1453 		break;
1454 	}
1455 	return 0;
1456 }
1457 
1458 static u_int
1459 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
1460 {
1461 #define	BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
1462 #define	BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
1463 #define	BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
1464 #define	BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
1465 #define	BITNO_2(x) (((x) & 2) ? 1 : 0)
1466 #define	BIT(n)	(1 << n)
1467 #define	IS_EXTENDED(__p)	\
1468 	    (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
1469 
1470 	struct cpack_state cpacker;
1471 	struct ieee80211_radiotap_header *hdr;
1472 	u_int32_t present, next_present;
1473 	u_int32_t *presentp, *last_presentp;
1474 	enum ieee80211_radiotap_type bit;
1475 	int bit0;
1476 	const u_char *iter;
1477 	u_int len;
1478 	int pad;
1479 
1480 	if (caplen < sizeof(*hdr)) {
1481 		printf("[|802.11]");
1482 		return caplen;
1483 	}
1484 
1485 	hdr = (struct ieee80211_radiotap_header *)p;
1486 
1487 	len = EXTRACT_LE_16BITS(&hdr->it_len);
1488 
1489 	if (caplen < len) {
1490 		printf("[|802.11]");
1491 		return caplen;
1492 	}
1493 	for (last_presentp = &hdr->it_present;
1494 	     IS_EXTENDED(last_presentp) &&
1495 	     (u_char*)(last_presentp + 1) <= p + len;
1496 	     last_presentp++);
1497 
1498 	/* are there more bitmap extensions than bytes in header? */
1499 	if (IS_EXTENDED(last_presentp)) {
1500 		printf("[|802.11]");
1501 		return caplen;
1502 	}
1503 
1504 	iter = (u_char*)(last_presentp + 1);
1505 
1506 	if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
1507 		/* XXX */
1508 		printf("[|802.11]");
1509 		return caplen;
1510 	}
1511 
1512 	/* Assume no Atheros padding between 802.11 header and body */
1513 	pad = 0;
1514 	for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
1515 	     presentp++, bit0 += 32) {
1516 		for (present = EXTRACT_LE_32BITS(presentp); present;
1517 		     present = next_present) {
1518 			/* clear the least significant bit that is set */
1519 			next_present = present & (present - 1);
1520 
1521 			/* extract the least significant bit that is set */
1522 			bit = (enum ieee80211_radiotap_type)
1523 			    (bit0 + BITNO_32(present ^ next_present));
1524 
1525 			if (print_radiotap_field(&cpacker, bit, &pad) != 0)
1526 				goto out;
1527 		}
1528 	}
1529 out:
1530 	return len + ieee802_11_print(p + len, length - len, caplen - len, pad);
1531 #undef BITNO_32
1532 #undef BITNO_16
1533 #undef BITNO_8
1534 #undef BITNO_4
1535 #undef BITNO_2
1536 #undef BIT
1537 }
1538 
1539 static u_int
1540 ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
1541 {
1542 	u_int32_t caphdr_len;
1543 
1544 	if (caplen < 8) {
1545 		printf("[|802.11]");
1546 		return caplen;
1547 	}
1548 
1549 	caphdr_len = EXTRACT_32BITS(p + 4);
1550 	if (caphdr_len < 8) {
1551 		/*
1552 		 * Yow!  The capture header length is claimed not
1553 		 * to be large enough to include even the version
1554 		 * cookie or capture header length!
1555 		 */
1556 		printf("[|802.11]");
1557 		return caplen;
1558 	}
1559 
1560 	if (caplen < caphdr_len) {
1561 		printf("[|802.11]");
1562 		return caplen;
1563 	}
1564 
1565 	return caphdr_len + ieee802_11_print(p + caphdr_len,
1566 	    length - caphdr_len, caplen - caphdr_len, 0);
1567 }
1568 
1569 #define PRISM_HDR_LEN		144
1570 
1571 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
1572 #define WLANCAP_MAGIC_COOKIE_V1	0x80211001
1573 #define WLANCAP_MAGIC_COOKIE_V2	0x80211002
1574 
1575 /*
1576  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
1577  * containing information such as radio information, which we
1578  * currently ignore.
1579  *
1580  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
1581  * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
1582  * (currently, on Linux, there's no ARPHRD_ type for
1583  * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
1584  * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
1585  * the AVS header, and the first 4 bytes of the header are used to
1586  * indicate whether it's a Prism header or an AVS header).
1587  */
1588 u_int
1589 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
1590 {
1591 	u_int caplen = h->caplen;
1592 	u_int length = h->len;
1593 	u_int32_t msgcode;
1594 
1595 	if (caplen < 4) {
1596 		printf("[|802.11]");
1597 		return caplen;
1598 	}
1599 
1600 	msgcode = EXTRACT_32BITS(p);
1601 	if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
1602 	    msgcode == WLANCAP_MAGIC_COOKIE_V2)
1603 		return ieee802_11_avs_radio_print(p, length, caplen);
1604 
1605 	if (caplen < PRISM_HDR_LEN) {
1606 		printf("[|802.11]");
1607 		return caplen;
1608 	}
1609 
1610 	return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
1611 	    length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN, 0);
1612 }
1613 
1614 /*
1615  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
1616  * header, containing information such as radio information.
1617  */
1618 u_int
1619 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
1620 {
1621 	return ieee802_11_radio_print(p, h->len, h->caplen);
1622 }
1623 
1624 /*
1625  * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
1626  * extra header, containing information such as radio information,
1627  * which we currently ignore.
1628  */
1629 u_int
1630 ieee802_11_radio_avs_if_print(const struct pcap_pkthdr *h, const u_char *p)
1631 {
1632 	return ieee802_11_avs_radio_print(p, h->len, h->caplen);
1633 }
1634