xref: /dragonfly/contrib/tcpdump/print-802_11.c (revision 73e0051e)
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 #ifndef lint
24 static const char rcsid[] _U_ =
25     "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.47.2.2 2007-12-29 23:25:28 guy Exp $ (LBL)";
26 #endif
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include <tcpdump-stdinc.h>
33 
34 #include <stdio.h>
35 #include <pcap.h>
36 #include <string.h>
37 
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "ethertype.h"
41 
42 #include "extract.h"
43 
44 #include "cpack.h"
45 
46 #include "ieee802_11.h"
47 #include "ieee802_11_radio.h"
48 
49 #define PRINT_SSID(p) \
50 	switch (p.ssid_status) { \
51 	case TRUNCATED: \
52 		return 0; \
53 	case PRESENT: \
54 		printf(" ("); \
55 		fn_print(p.ssid.ssid, NULL); \
56 		printf(")"); \
57 		break; \
58 	case NOT_PRESENT: \
59 		break; \
60 	}
61 
62 #define PRINT_RATE(_sep, _r, _suf) \
63 	printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
64 #define PRINT_RATES(p) \
65 	switch (p.rates_status) { \
66 	case TRUNCATED: \
67 		return 0; \
68 	case PRESENT: \
69 		do { \
70 			int z; \
71 			const char *sep = " ["; \
72 			for (z = 0; z < p.rates.length ; z++) { \
73 				PRINT_RATE(sep, p.rates.rate[z], \
74 					(p.rates.rate[z] & 0x80 ? "*" : "")); \
75 				sep = " "; \
76 			} \
77 			if (p.rates.length != 0) \
78 				printf(" Mbit]"); \
79 		} while (0); \
80 		break; \
81 	case NOT_PRESENT: \
82 		break; \
83 	}
84 
85 #define PRINT_DS_CHANNEL(p) \
86 	switch (p.ds_status) { \
87 	case TRUNCATED: \
88 		return 0; \
89 	case PRESENT: \
90 		printf(" CH: %u", p.ds.channel); \
91 		break; \
92 	case NOT_PRESENT: \
93 		break; \
94 	} \
95 	printf("%s", \
96 	    CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "" );
97 
98 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
99 #define NUM_AUTH_ALGS	(sizeof auth_alg_text / sizeof auth_alg_text[0])
100 
101 static const char *status_text[] = {
102 	"Succesful",  /*  0  */
103 	"Unspecified failure",  /*  1  */
104 	"Reserved",	  /*  2  */
105 	"Reserved",	  /*  3  */
106 	"Reserved",	  /*  4  */
107 	"Reserved",	  /*  5  */
108 	"Reserved",	  /*  6  */
109 	"Reserved",	  /*  7  */
110 	"Reserved",	  /*  8  */
111 	"Reserved",	  /*  9  */
112 	"Cannot Support all requested capabilities in the Capability Information field",	  /*  10  */
113 	"Reassociation denied due to inability to confirm that association exists",	  /*  11  */
114 	"Association denied due to reason outside the scope of the standard",	  /*  12  */
115 	"Responding station does not support the specified authentication algorithm ",	  /*  13  */
116 	"Received an Authentication frame with authentication transaction " \
117 		"sequence number out of expected sequence",	  /*  14  */
118 	"Authentication rejected because of challenge failure",	  /*  15 */
119 	"Authentication rejected due to timeout waiting for next frame in sequence",	  /*  16 */
120 	"Association denied because AP is unable to handle additional associated stations",	  /*  17 */
121 	"Association denied due to requesting station not supporting all of the " \
122 		"data rates in BSSBasicRateSet parameter",	  /*  18 */
123 };
124 #define NUM_STATUSES	(sizeof status_text / sizeof status_text[0])
125 
126 static const char *reason_text[] = {
127 	"Reserved", /* 0 */
128 	"Unspecified reason", /* 1 */
129 	"Previous authentication no longer valid",  /* 2 */
130 	"Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
131 	"Disassociated due to inactivity", /* 4 */
132 	"Disassociated because AP is unable to handle all currently associated stations", /* 5 */
133 	"Class 2 frame received from nonauthenticated station", /* 6 */
134 	"Class 3 frame received from nonassociated station", /* 7 */
135 	"Disassociated because sending station is leaving (or has left) BSS", /* 8 */
136 	"Station requesting (re)association is not authenticated with responding station", /* 9 */
137 };
138 #define NUM_REASONS	(sizeof reason_text / sizeof reason_text[0])
139 
140 static int
141 wep_print(const u_char *p)
142 {
143 	u_int32_t iv;
144 
145 	if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
146 		return 0;
147 	iv = EXTRACT_LE_32BITS(p);
148 
149 	printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
150 	    IV_KEYID(iv));
151 
152 	return 1;
153 }
154 
155 static void
156 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
157 {
158 	/*
159 	 * We haven't seen any elements yet.
160 	 */
161 	pbody->challenge_status = NOT_PRESENT;
162 	pbody->ssid_status = NOT_PRESENT;
163 	pbody->rates_status = NOT_PRESENT;
164 	pbody->ds_status = NOT_PRESENT;
165 	pbody->cf_status = NOT_PRESENT;
166 	pbody->tim_status = NOT_PRESENT;
167 
168 	for (;;) {
169 		if (!TTEST2(*(p + offset), 1))
170 			return;
171 		switch (*(p + offset)) {
172 		case E_SSID:
173 			/* Present, possibly truncated */
174 			pbody->ssid_status = TRUNCATED;
175 			if (!TTEST2(*(p + offset), 2))
176 				return;
177 			memcpy(&pbody->ssid, p + offset, 2);
178 			offset += 2;
179 			if (pbody->ssid.length != 0) {
180 				if (pbody->ssid.length >
181 				    sizeof(pbody->ssid.ssid) - 1)
182 					return;
183 				if (!TTEST2(*(p + offset), pbody->ssid.length))
184 					return;
185 				memcpy(&pbody->ssid.ssid, p + offset,
186 				    pbody->ssid.length);
187 				offset += pbody->ssid.length;
188 			}
189 			pbody->ssid.ssid[pbody->ssid.length] = '\0';
190 			/* Present and not truncated */
191 			pbody->ssid_status = PRESENT;
192 			break;
193 		case E_CHALLENGE:
194 			/* Present, possibly truncated */
195 			pbody->challenge_status = TRUNCATED;
196 			if (!TTEST2(*(p + offset), 2))
197 				return;
198 			memcpy(&pbody->challenge, p + offset, 2);
199 			offset += 2;
200 			if (pbody->challenge.length != 0) {
201 				if (pbody->challenge.length >
202 				    sizeof(pbody->challenge.text) - 1)
203 					return;
204 				if (!TTEST2(*(p + offset), pbody->challenge.length))
205 					return;
206 				memcpy(&pbody->challenge.text, p + offset,
207 				    pbody->challenge.length);
208 				offset += pbody->challenge.length;
209 			}
210 			pbody->challenge.text[pbody->challenge.length] = '\0';
211 			/* Present and not truncated */
212 			pbody->challenge_status = PRESENT;
213 			break;
214 		case E_RATES:
215 			/* Present, possibly truncated */
216 			pbody->rates_status = TRUNCATED;
217 			if (!TTEST2(*(p + offset), 2))
218 				return;
219 			memcpy(&(pbody->rates), p + offset, 2);
220 			offset += 2;
221 			if (pbody->rates.length != 0) {
222 				if (pbody->rates.length > sizeof pbody->rates.rate)
223 					return;
224 				if (!TTEST2(*(p + offset), pbody->rates.length))
225 					return;
226 				memcpy(&pbody->rates.rate, p + offset,
227 				    pbody->rates.length);
228 				offset += pbody->rates.length;
229 			}
230 			/* Present and not truncated */
231 			pbody->rates_status = PRESENT;
232 			break;
233 		case E_DS:
234 			/* Present, possibly truncated */
235 			pbody->ds_status = TRUNCATED;
236 			if (!TTEST2(*(p + offset), 3))
237 				return;
238 			memcpy(&pbody->ds, p + offset, 3);
239 			offset += 3;
240 			/* Present and not truncated */
241 			pbody->ds_status = PRESENT;
242 			break;
243 		case E_CF:
244 			/* Present, possibly truncated */
245 			pbody->cf_status = TRUNCATED;
246 			if (!TTEST2(*(p + offset), 8))
247 				return;
248 			memcpy(&pbody->cf, p + offset, 8);
249 			offset += 8;
250 			/* Present and not truncated */
251 			pbody->cf_status = PRESENT;
252 			break;
253 		case E_TIM:
254 			/* Present, possibly truncated */
255 			pbody->tim_status = TRUNCATED;
256 			if (!TTEST2(*(p + offset), 2))
257 				return;
258 			memcpy(&pbody->tim, p + offset, 2);
259 			offset += 2;
260 			if (!TTEST2(*(p + offset), 3))
261 				return;
262 			memcpy(&pbody->tim.count, p + offset, 3);
263 			offset += 3;
264 
265 			if (pbody->tim.length <= 3)
266 				break;
267 			if (pbody->tim.length - 3 > (int)sizeof pbody->tim.bitmap)
268 				return;
269 			if (!TTEST2(*(p + offset), pbody->tim.length - 3))
270 				return;
271 			memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
272 			    (pbody->tim.length - 3));
273 			offset += pbody->tim.length - 3;
274 			/* Present and not truncated */
275 			pbody->tim_status = PRESENT;
276 			break;
277 		default:
278 #if 0
279 			printf("(1) unhandled element_id (%d)  ",
280 			    *(p + offset) );
281 #endif
282 			if (!TTEST2(*(p + offset), 2))
283 				return;
284 			if (!TTEST2(*(p + offset + 2), *(p + offset + 1)))
285 				return;
286 			offset += *(p + offset + 1) + 2;
287 			break;
288 		}
289 	}
290 }
291 
292 /*********************************************************************************
293  * Print Handle functions for the management frame types
294  *********************************************************************************/
295 
296 static int
297 handle_beacon(const u_char *p)
298 {
299 	struct mgmt_body_t pbody;
300 	int offset = 0;
301 
302 	memset(&pbody, 0, sizeof(pbody));
303 
304 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
305 	    IEEE802_11_CAPINFO_LEN))
306 		return 0;
307 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
308 	offset += IEEE802_11_TSTAMP_LEN;
309 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
310 	offset += IEEE802_11_BCNINT_LEN;
311 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
312 	offset += IEEE802_11_CAPINFO_LEN;
313 
314 	parse_elements(&pbody, p, offset);
315 
316 	PRINT_SSID(pbody);
317 	PRINT_RATES(pbody);
318 	printf(" %s",
319 	    CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
320 	PRINT_DS_CHANNEL(pbody);
321 
322 	return 1;
323 }
324 
325 static int
326 handle_assoc_request(const u_char *p)
327 {
328 	struct mgmt_body_t pbody;
329 	int offset = 0;
330 
331 	memset(&pbody, 0, sizeof(pbody));
332 
333 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
334 		return 0;
335 	pbody.capability_info = EXTRACT_LE_16BITS(p);
336 	offset += IEEE802_11_CAPINFO_LEN;
337 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
338 	offset += IEEE802_11_LISTENINT_LEN;
339 
340 	parse_elements(&pbody, p, offset);
341 
342 	PRINT_SSID(pbody);
343 	PRINT_RATES(pbody);
344 	return 1;
345 }
346 
347 static int
348 handle_assoc_response(const u_char *p)
349 {
350 	struct mgmt_body_t pbody;
351 	int offset = 0;
352 
353 	memset(&pbody, 0, sizeof(pbody));
354 
355 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
356 	    IEEE802_11_AID_LEN))
357 		return 0;
358 	pbody.capability_info = EXTRACT_LE_16BITS(p);
359 	offset += IEEE802_11_CAPINFO_LEN;
360 	pbody.status_code = EXTRACT_LE_16BITS(p+offset);
361 	offset += IEEE802_11_STATUS_LEN;
362 	pbody.aid = EXTRACT_LE_16BITS(p+offset);
363 	offset += IEEE802_11_AID_LEN;
364 
365 	parse_elements(&pbody, p, offset);
366 
367 	printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
368 	    CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
369 	    (pbody.status_code < NUM_STATUSES
370 		? status_text[pbody.status_code]
371 		: "n/a"));
372 
373 	return 1;
374 }
375 
376 static int
377 handle_reassoc_request(const u_char *p)
378 {
379 	struct mgmt_body_t pbody;
380 	int offset = 0;
381 
382 	memset(&pbody, 0, sizeof(pbody));
383 
384 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
385 	    IEEE802_11_AP_LEN))
386 		return 0;
387 	pbody.capability_info = EXTRACT_LE_16BITS(p);
388 	offset += IEEE802_11_CAPINFO_LEN;
389 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
390 	offset += IEEE802_11_LISTENINT_LEN;
391 	memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
392 	offset += IEEE802_11_AP_LEN;
393 
394 	parse_elements(&pbody, p, offset);
395 
396 	PRINT_SSID(pbody);
397 	printf(" AP : %s", etheraddr_string( pbody.ap ));
398 
399 	return 1;
400 }
401 
402 static int
403 handle_reassoc_response(const u_char *p)
404 {
405 	/* Same as a Association Reponse */
406 	return handle_assoc_response(p);
407 }
408 
409 static int
410 handle_probe_request(const u_char *p)
411 {
412 	struct mgmt_body_t  pbody;
413 	int offset = 0;
414 
415 	memset(&pbody, 0, sizeof(pbody));
416 
417 	parse_elements(&pbody, p, offset);
418 
419 	PRINT_SSID(pbody);
420 	PRINT_RATES(pbody);
421 
422 	return 1;
423 }
424 
425 static int
426 handle_probe_response(const u_char *p)
427 {
428 	struct mgmt_body_t  pbody;
429 	int offset = 0;
430 
431 	memset(&pbody, 0, sizeof(pbody));
432 
433 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
434 	    IEEE802_11_CAPINFO_LEN))
435 		return 0;
436 
437 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
438 	offset += IEEE802_11_TSTAMP_LEN;
439 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
440 	offset += IEEE802_11_BCNINT_LEN;
441 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
442 	offset += IEEE802_11_CAPINFO_LEN;
443 
444 	parse_elements(&pbody, p, offset);
445 
446 	PRINT_SSID(pbody);
447 	PRINT_RATES(pbody);
448 	PRINT_DS_CHANNEL(pbody);
449 
450 	return 1;
451 }
452 
453 static int
454 handle_atim(void)
455 {
456 	/* the frame body for ATIM is null. */
457 	return 1;
458 }
459 
460 static int
461 handle_disassoc(const u_char *p)
462 {
463 	struct mgmt_body_t  pbody;
464 
465 	memset(&pbody, 0, sizeof(pbody));
466 
467 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
468 		return 0;
469 	pbody.reason_code = EXTRACT_LE_16BITS(p);
470 
471 	printf(": %s",
472 	    (pbody.reason_code < NUM_REASONS)
473 		? reason_text[pbody.reason_code]
474 		: "Reserved" );
475 
476 	return 1;
477 }
478 
479 static int
480 handle_auth(const u_char *p)
481 {
482 	struct mgmt_body_t  pbody;
483 	int offset = 0;
484 
485 	memset(&pbody, 0, sizeof(pbody));
486 
487 	if (!TTEST2(*p, 6))
488 		return 0;
489 	pbody.auth_alg = EXTRACT_LE_16BITS(p);
490 	offset += 2;
491 	pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
492 	offset += 2;
493 	pbody.status_code = EXTRACT_LE_16BITS(p + offset);
494 	offset += 2;
495 
496 	parse_elements(&pbody, p, offset);
497 
498 	if ((pbody.auth_alg == 1) &&
499 	    ((pbody.auth_trans_seq_num == 2) ||
500 	     (pbody.auth_trans_seq_num == 3))) {
501 		printf(" (%s)-%x [Challenge Text] %s",
502 		    (pbody.auth_alg < NUM_AUTH_ALGS)
503 			? auth_alg_text[pbody.auth_alg]
504 			: "Reserved",
505 		    pbody.auth_trans_seq_num,
506 		    ((pbody.auth_trans_seq_num % 2)
507 		        ? ((pbody.status_code < NUM_STATUSES)
508 			       ? status_text[pbody.status_code]
509 			       : "n/a") : ""));
510 		return 1;
511 	}
512 	printf(" (%s)-%x: %s",
513 	    (pbody.auth_alg < NUM_AUTH_ALGS)
514 		? auth_alg_text[pbody.auth_alg]
515 		: "Reserved",
516 	    pbody.auth_trans_seq_num,
517 	    (pbody.auth_trans_seq_num % 2)
518 	        ? ((pbody.status_code < NUM_STATUSES)
519 		    ? status_text[pbody.status_code]
520 	            : "n/a")
521 	        : "");
522 
523 	return 1;
524 }
525 
526 static int
527 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
528 {
529 	struct mgmt_body_t  pbody;
530 	int offset = 0;
531 	const char *reason = NULL;
532 
533 	memset(&pbody, 0, sizeof(pbody));
534 
535 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
536 		return 0;
537 	pbody.reason_code = EXTRACT_LE_16BITS(p);
538 	offset += IEEE802_11_REASON_LEN;
539 
540 	reason = (pbody.reason_code < NUM_REASONS)
541 			? reason_text[pbody.reason_code]
542 			: "Reserved";
543 
544 	if (eflag) {
545 		printf(": %s", reason);
546 	} else {
547 		printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
548 	}
549 	return 1;
550 }
551 
552 
553 /*********************************************************************************
554  * Print Body funcs
555  *********************************************************************************/
556 
557 
558 static int
559 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
560     const u_char *p)
561 {
562 	switch (FC_SUBTYPE(fc)) {
563 	case ST_ASSOC_REQUEST:
564 		printf("Assoc Request");
565 		return handle_assoc_request(p);
566 	case ST_ASSOC_RESPONSE:
567 		printf("Assoc Response");
568 		return handle_assoc_response(p);
569 	case ST_REASSOC_REQUEST:
570 		printf("ReAssoc Request");
571 		return handle_reassoc_request(p);
572 	case ST_REASSOC_RESPONSE:
573 		printf("ReAssoc Response");
574 		return handle_reassoc_response(p);
575 	case ST_PROBE_REQUEST:
576 		printf("Probe Request");
577 		return handle_probe_request(p);
578 	case ST_PROBE_RESPONSE:
579 		printf("Probe Response");
580 		return handle_probe_response(p);
581 	case ST_BEACON:
582 		printf("Beacon");
583 		return handle_beacon(p);
584 	case ST_ATIM:
585 		printf("ATIM");
586 		return handle_atim();
587 	case ST_DISASSOC:
588 		printf("Disassociation");
589 		return handle_disassoc(p);
590 	case ST_AUTH:
591 		printf("Authentication");
592 		if (!TTEST2(*p, 3))
593 			return 0;
594 		if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
595 			printf("Authentication (Shared-Key)-3 ");
596 			return wep_print(p);
597 		}
598 		return handle_auth(p);
599 	case ST_DEAUTH:
600 		printf("DeAuthentication");
601 		return handle_deauth(pmh, p);
602 		break;
603 	default:
604 		printf("Unhandled Management subtype(%x)",
605 		    FC_SUBTYPE(fc));
606 		return 1;
607 	}
608 }
609 
610 
611 /*********************************************************************************
612  * Handles printing all the control frame types
613  *********************************************************************************/
614 
615 static int
616 ctrl_body_print(u_int16_t fc, const u_char *p)
617 {
618 	switch (FC_SUBTYPE(fc)) {
619 	case CTRL_PS_POLL:
620 		printf("Power Save-Poll");
621 		if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
622 			return 0;
623 		printf(" AID(%x)",
624 		    EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
625 		break;
626 	case CTRL_RTS:
627 		printf("Request-To-Send");
628 		if (!TTEST2(*p, CTRL_RTS_HDRLEN))
629 			return 0;
630 		if (!eflag)
631 			printf(" TA:%s ",
632 			    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
633 		break;
634 	case CTRL_CTS:
635 		printf("Clear-To-Send");
636 		if (!TTEST2(*p, CTRL_CTS_HDRLEN))
637 			return 0;
638 		if (!eflag)
639 			printf(" RA:%s ",
640 			    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
641 		break;
642 	case CTRL_ACK:
643 		printf("Acknowledgment");
644 		if (!TTEST2(*p, CTRL_ACK_HDRLEN))
645 			return 0;
646 		if (!eflag)
647 			printf(" RA:%s ",
648 			    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
649 		break;
650 	case CTRL_CF_END:
651 		printf("CF-End");
652 		if (!TTEST2(*p, CTRL_END_HDRLEN))
653 			return 0;
654 		if (!eflag)
655 			printf(" RA:%s ",
656 			    etheraddr_string(((const struct ctrl_end_t *)p)->ra));
657 		break;
658 	case CTRL_END_ACK:
659 		printf("CF-End+CF-Ack");
660 		if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
661 			return 0;
662 		if (!eflag)
663 			printf(" RA:%s ",
664 			    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
665 		break;
666 	default:
667 		printf("Unknown Ctrl Subtype");
668 	}
669 	return 1;
670 }
671 
672 /*
673  * Print Header funcs
674  */
675 
676 /*
677  *  Data Frame - Address field contents
678  *
679  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
680  *    0    |  0      |  DA    | SA     | BSSID  | n/a
681  *    0    |  1      |  DA    | BSSID  | SA     | n/a
682  *    1    |  0      |  BSSID | SA     | DA     | n/a
683  *    1    |  1      |  RA    | TA     | DA     | SA
684  */
685 
686 static void
687 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
688     const u_int8_t **dstp)
689 {
690 	u_int subtype = FC_SUBTYPE(fc);
691 
692 	if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
693 	    DATA_FRAME_IS_QOS(subtype)) {
694 		printf("CF ");
695 		if (DATA_FRAME_IS_CF_ACK(subtype)) {
696 			if (DATA_FRAME_IS_CF_POLL(subtype))
697 				printf("Ack/Poll");
698 			else
699 				printf("Ack");
700 		} else {
701 			if (DATA_FRAME_IS_CF_POLL(subtype))
702 				printf("Poll");
703 		}
704 		if (DATA_FRAME_IS_QOS(subtype))
705 			printf("+QoS");
706 		printf(" ");
707 	}
708 
709 #define ADDR1  (p + 4)
710 #define ADDR2  (p + 10)
711 #define ADDR3  (p + 16)
712 #define ADDR4  (p + 24)
713 
714 	if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
715 		if (srcp != NULL)
716 			*srcp = ADDR2;
717 		if (dstp != NULL)
718 			*dstp = ADDR1;
719 		if (!eflag)
720 			return;
721 		printf("DA:%s SA:%s BSSID:%s ",
722 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
723 		    etheraddr_string(ADDR3));
724 	} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
725 		if (srcp != NULL)
726 			*srcp = ADDR3;
727 		if (dstp != NULL)
728 			*dstp = ADDR1;
729 		if (!eflag)
730 			return;
731 		printf("DA:%s BSSID:%s SA:%s ",
732 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
733 		    etheraddr_string(ADDR3));
734 	} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
735 		if (srcp != NULL)
736 			*srcp = ADDR2;
737 		if (dstp != NULL)
738 			*dstp = ADDR3;
739 		if (!eflag)
740 			return;
741 		printf("BSSID:%s SA:%s DA:%s ",
742 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
743 		    etheraddr_string(ADDR3));
744 	} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
745 		if (srcp != NULL)
746 			*srcp = ADDR4;
747 		if (dstp != NULL)
748 			*dstp = ADDR3;
749 		if (!eflag)
750 			return;
751 		printf("RA:%s TA:%s DA:%s SA:%s ",
752 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
753 		    etheraddr_string(ADDR3), etheraddr_string(ADDR4));
754 	}
755 
756 #undef ADDR1
757 #undef ADDR2
758 #undef ADDR3
759 #undef ADDR4
760 }
761 
762 static void
763 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
764     const u_int8_t **dstp)
765 {
766 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
767 
768 	if (srcp != NULL)
769 		*srcp = hp->sa;
770 	if (dstp != NULL)
771 		*dstp = hp->da;
772 	if (!eflag)
773 		return;
774 
775 	printf("BSSID:%s DA:%s SA:%s ",
776 	    etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
777 	    etheraddr_string((hp)->sa));
778 }
779 
780 static void
781 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
782     const u_int8_t **dstp)
783 {
784 	if (srcp != NULL)
785 		*srcp = NULL;
786 	if (dstp != NULL)
787 		*dstp = NULL;
788 	if (!eflag)
789 		return;
790 
791 	switch (FC_SUBTYPE(fc)) {
792 	case CTRL_PS_POLL:
793 		printf("BSSID:%s TA:%s ",
794 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
795 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
796 		break;
797 	case CTRL_RTS:
798 		printf("RA:%s TA:%s ",
799 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
800 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
801 		break;
802 	case CTRL_CTS:
803 		printf("RA:%s ",
804 		    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
805 		break;
806 	case CTRL_ACK:
807 		printf("RA:%s ",
808 		    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
809 		break;
810 	case CTRL_CF_END:
811 		printf("RA:%s BSSID:%s ",
812 		    etheraddr_string(((const struct ctrl_end_t *)p)->ra),
813 		    etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
814 		break;
815 	case CTRL_END_ACK:
816 		printf("RA:%s BSSID:%s ",
817 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
818 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
819 		break;
820 	default:
821 		printf("(H) Unknown Ctrl Subtype");
822 		break;
823 	}
824 }
825 
826 static int
827 extract_header_length(u_int16_t fc)
828 {
829 	int len;
830 
831 	switch (FC_TYPE(fc)) {
832 	case T_MGMT:
833 		return MGMT_HDRLEN;
834 	case T_CTRL:
835 		switch (FC_SUBTYPE(fc)) {
836 		case CTRL_PS_POLL:
837 			return CTRL_PS_POLL_HDRLEN;
838 		case CTRL_RTS:
839 			return CTRL_RTS_HDRLEN;
840 		case CTRL_CTS:
841 			return CTRL_CTS_HDRLEN;
842 		case CTRL_ACK:
843 			return CTRL_ACK_HDRLEN;
844 		case CTRL_CF_END:
845 			return CTRL_END_HDRLEN;
846 		case CTRL_END_ACK:
847 			return CTRL_END_ACK_HDRLEN;
848 		default:
849 			return 0;
850 		}
851 	case T_DATA:
852 		len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
853 		if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
854 			len += 2;
855 		return len;
856 	default:
857 		printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
858 		return 0;
859 	}
860 }
861 
862 /*
863  * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
864  * to point to the source and destination MAC addresses in any case if
865  * "srcp" and "dstp" aren't null.
866  */
867 static inline void
868 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
869     const u_int8_t **dstp)
870 {
871 	if (vflag) {
872 		if (FC_MORE_DATA(fc))
873 			printf("More Data ");
874 		if (FC_MORE_FLAG(fc))
875 			printf("More Fragments ");
876 		if (FC_POWER_MGMT(fc))
877 			printf("Pwr Mgmt ");
878 		if (FC_RETRY(fc))
879 			printf("Retry ");
880 		if (FC_ORDER(fc))
881 			printf("Strictly Ordered ");
882 		if (FC_WEP(fc))
883 			printf("WEP Encrypted ");
884 		if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
885 			printf("%dus ",
886 			    EXTRACT_LE_16BITS(
887 			        &((const struct mgmt_header_t *)p)->duration));
888 	}
889 
890 	switch (FC_TYPE(fc)) {
891 	case T_MGMT:
892 		mgmt_header_print(p, srcp, dstp);
893 		break;
894 	case T_CTRL:
895 		ctrl_header_print(fc, p, srcp, dstp);
896 		break;
897 	case T_DATA:
898 		data_header_print(fc, p, srcp, dstp);
899 		break;
900 	default:
901 		printf("(header) unknown IEEE802.11 frame type (%d)",
902 		    FC_TYPE(fc));
903 		*srcp = NULL;
904 		*dstp = NULL;
905 		break;
906 	}
907 }
908 
909 #ifndef roundup2
910 #define	roundup2(x, y)	(((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
911 #endif
912 
913 static u_int
914 ieee802_11_print(const u_char *p, u_int length, u_int caplen, int pad)
915 {
916 	u_int16_t fc;
917 	u_int hdrlen;
918 	const u_int8_t *src, *dst;
919 	u_short extracted_ethertype;
920 
921 	if (caplen < IEEE802_11_FC_LEN) {
922 		printf("[|802.11]");
923 		return caplen;
924 	}
925 
926 	fc = EXTRACT_LE_16BITS(p);
927 	hdrlen = extract_header_length(fc);
928 	if (pad)
929 		hdrlen = roundup2(hdrlen, 4);
930 
931 	if (caplen < hdrlen) {
932 		printf("[|802.11]");
933 		return hdrlen;
934 	}
935 
936 	ieee_802_11_hdr_print(fc, p, &src, &dst);
937 
938 	/*
939 	 * Go past the 802.11 header.
940 	 */
941 	length -= hdrlen;
942 	caplen -= hdrlen;
943 	p += hdrlen;
944 
945 	switch (FC_TYPE(fc)) {
946 	case T_MGMT:
947 		if (!mgmt_body_print(fc,
948 		    (const struct mgmt_header_t *)(p - hdrlen), p)) {
949 			printf("[|802.11]");
950 			return hdrlen;
951 		}
952 		break;
953 	case T_CTRL:
954 		if (!ctrl_body_print(fc, p - hdrlen)) {
955 			printf("[|802.11]");
956 			return hdrlen;
957 		}
958 		break;
959 	case T_DATA:
960 		if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
961 			return hdrlen;	/* no-data frame */
962 		/* There may be a problem w/ AP not having this bit set */
963 		if (FC_WEP(fc)) {
964 			if (!wep_print(p)) {
965 				printf("[|802.11]");
966 				return hdrlen;
967 			}
968 		} else if (llc_print(p, length, caplen, dst, src,
969 		    &extracted_ethertype) == 0) {
970 			/*
971 			 * Some kinds of LLC packet we cannot
972 			 * handle intelligently
973 			 */
974 			if (!eflag)
975 				ieee_802_11_hdr_print(fc, p - hdrlen, NULL,
976 				    NULL);
977 			if (extracted_ethertype)
978 				printf("(LLC %s) ",
979 				    etherproto_string(
980 				        htons(extracted_ethertype)));
981 			if (!suppress_default_print)
982 				default_print(p, caplen);
983 		}
984 		break;
985 	default:
986 		printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
987 		break;
988 	}
989 
990 	return hdrlen;
991 }
992 
993 /*
994  * This is the top level routine of the printer.  'p' points
995  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
996  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
997  * is the number of bytes actually captured.
998  */
999 u_int
1000 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
1001 {
1002 	return ieee802_11_print(p, h->len, h->caplen, 0);
1003 }
1004 
1005 static int
1006 print_radiotap_field(struct cpack_state *s, u_int32_t bit, int *pad)
1007 {
1008 	union {
1009 		int8_t		i8;
1010 		u_int8_t	u8;
1011 		int16_t		i16;
1012 		u_int16_t	u16;
1013 		u_int32_t	u32;
1014 		u_int64_t	u64;
1015 	} u, u2;
1016 	int rc;
1017 
1018 	switch (bit) {
1019 	case IEEE80211_RADIOTAP_FLAGS:
1020 		rc = cpack_uint8(s, &u.u8);
1021 		if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD)
1022 			*pad = 1;
1023 		break;
1024 	case IEEE80211_RADIOTAP_RATE:
1025 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1026 	case IEEE80211_RADIOTAP_DB_ANTNOISE:
1027 	case IEEE80211_RADIOTAP_ANTENNA:
1028 		rc = cpack_uint8(s, &u.u8);
1029 		break;
1030 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1031 	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1032 		rc = cpack_int8(s, &u.i8);
1033 		break;
1034 	case IEEE80211_RADIOTAP_CHANNEL:
1035 		rc = cpack_uint16(s, &u.u16);
1036 		if (rc != 0)
1037 			break;
1038 		rc = cpack_uint16(s, &u2.u16);
1039 		break;
1040 	case IEEE80211_RADIOTAP_FHSS:
1041 	case IEEE80211_RADIOTAP_LOCK_QUALITY:
1042 	case IEEE80211_RADIOTAP_TX_ATTENUATION:
1043 		rc = cpack_uint16(s, &u.u16);
1044 		break;
1045 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1046 		rc = cpack_uint8(s, &u.u8);
1047 		break;
1048 	case IEEE80211_RADIOTAP_DBM_TX_POWER:
1049 		rc = cpack_int8(s, &u.i8);
1050 		break;
1051 	case IEEE80211_RADIOTAP_TSFT:
1052 		rc = cpack_uint64(s, &u.u64);
1053 		break;
1054 	default:
1055 		/* this bit indicates a field whose
1056 		 * size we do not know, so we cannot
1057 		 * proceed.
1058 		 */
1059 		printf("[0x%08x] ", bit);
1060 		return -1;
1061 	}
1062 
1063 	if (rc != 0) {
1064 		printf("[|802.11]");
1065 		return rc;
1066 	}
1067 
1068 	switch (bit) {
1069 	case IEEE80211_RADIOTAP_CHANNEL:
1070 		printf("%u MHz ", u.u16);
1071 		if (u2.u16 != 0)
1072 			printf("(0x%04x) ", u2.u16);
1073 		break;
1074 	case IEEE80211_RADIOTAP_FHSS:
1075 		printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
1076 		break;
1077 	case IEEE80211_RADIOTAP_RATE:
1078 		PRINT_RATE("", u.u8, " Mb/s ");
1079 		break;
1080 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1081 		printf("%ddB signal ", u.i8);
1082 		break;
1083 	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1084 		printf("%ddB noise ", u.i8);
1085 		break;
1086 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1087 		printf("%ddB signal ", u.u8);
1088 		break;
1089 	case IEEE80211_RADIOTAP_DB_ANTNOISE:
1090 		printf("%ddB noise ", u.u8);
1091 		break;
1092 	case IEEE80211_RADIOTAP_LOCK_QUALITY:
1093 		printf("%u sq ", u.u16);
1094 		break;
1095 	case IEEE80211_RADIOTAP_TX_ATTENUATION:
1096 		printf("%d tx power ", -(int)u.u16);
1097 		break;
1098 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1099 		printf("%ddB tx power ", -(int)u.u8);
1100 		break;
1101 	case IEEE80211_RADIOTAP_DBM_TX_POWER:
1102 		printf("%ddBm tx power ", u.i8);
1103 		break;
1104 	case IEEE80211_RADIOTAP_FLAGS:
1105 		if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
1106 			printf("cfp ");
1107 		if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
1108 			printf("short preamble ");
1109 		if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
1110 			printf("wep ");
1111 		if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
1112 			printf("fragmented ");
1113 		if (u.u8 & IEEE80211_RADIOTAP_F_BADFCS)
1114 			printf("bad-fcs ");
1115 		break;
1116 	case IEEE80211_RADIOTAP_ANTENNA:
1117 		printf("antenna %d ", u.u8);
1118 		break;
1119 	case IEEE80211_RADIOTAP_TSFT:
1120 		printf("%" PRIu64 "us tsft ", u.u64);
1121 		break;
1122 	}
1123 	return 0;
1124 }
1125 
1126 static u_int
1127 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
1128 {
1129 #define	BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
1130 #define	BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
1131 #define	BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
1132 #define	BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
1133 #define	BITNO_2(x) (((x) & 2) ? 1 : 0)
1134 #define	BIT(n)	(1 << n)
1135 #define	IS_EXTENDED(__p)	\
1136 	    (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
1137 
1138 	struct cpack_state cpacker;
1139 	struct ieee80211_radiotap_header *hdr;
1140 	u_int32_t present, next_present;
1141 	u_int32_t *presentp, *last_presentp;
1142 	enum ieee80211_radiotap_type bit;
1143 	int bit0;
1144 	const u_char *iter;
1145 	u_int len;
1146 	int pad;
1147 
1148 	if (caplen < sizeof(*hdr)) {
1149 		printf("[|802.11]");
1150 		return caplen;
1151 	}
1152 
1153 	hdr = (struct ieee80211_radiotap_header *)p;
1154 
1155 	len = EXTRACT_LE_16BITS(&hdr->it_len);
1156 
1157 	if (caplen < len) {
1158 		printf("[|802.11]");
1159 		return caplen;
1160 	}
1161 	for (last_presentp = &hdr->it_present;
1162 	     IS_EXTENDED(last_presentp) &&
1163 	     (u_char*)(last_presentp + 1) <= p + len;
1164 	     last_presentp++);
1165 
1166 	/* are there more bitmap extensions than bytes in header? */
1167 	if (IS_EXTENDED(last_presentp)) {
1168 		printf("[|802.11]");
1169 		return caplen;
1170 	}
1171 
1172 	iter = (u_char*)(last_presentp + 1);
1173 
1174 	if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
1175 		/* XXX */
1176 		printf("[|802.11]");
1177 		return caplen;
1178 	}
1179 
1180 	/* Assume no Atheros padding between 802.11 header and body */
1181 	pad = 0;
1182 	for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
1183 	     presentp++, bit0 += 32) {
1184 		for (present = EXTRACT_LE_32BITS(presentp); present;
1185 		     present = next_present) {
1186 			/* clear the least significant bit that is set */
1187 			next_present = present & (present - 1);
1188 
1189 			/* extract the least significant bit that is set */
1190 			bit = (enum ieee80211_radiotap_type)
1191 			    (bit0 + BITNO_32(present ^ next_present));
1192 
1193 			if (print_radiotap_field(&cpacker, bit, &pad) != 0)
1194 				goto out;
1195 		}
1196 	}
1197 out:
1198 	return len + ieee802_11_print(p + len, length - len, caplen - len, pad);
1199 #undef BITNO_32
1200 #undef BITNO_16
1201 #undef BITNO_8
1202 #undef BITNO_4
1203 #undef BITNO_2
1204 #undef BIT
1205 }
1206 
1207 static u_int
1208 ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
1209 {
1210 	u_int32_t caphdr_len;
1211 
1212 	if (caplen < 8) {
1213 		printf("[|802.11]");
1214 		return caplen;
1215 	}
1216 
1217 	caphdr_len = EXTRACT_32BITS(p + 4);
1218 	if (caphdr_len < 8) {
1219 		/*
1220 		 * Yow!  The capture header length is claimed not
1221 		 * to be large enough to include even the version
1222 		 * cookie or capture header length!
1223 		 */
1224 		printf("[|802.11]");
1225 		return caplen;
1226 	}
1227 
1228 	if (caplen < caphdr_len) {
1229 		printf("[|802.11]");
1230 		return caplen;
1231 	}
1232 
1233 	return caphdr_len + ieee802_11_print(p + caphdr_len,
1234 	    length - caphdr_len, caplen - caphdr_len, 0);
1235 }
1236 
1237 #define PRISM_HDR_LEN		144
1238 
1239 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
1240 #define WLANCAP_MAGIC_COOKIE_V1	0x80211001
1241 #define WLANCAP_MAGIC_COOKIE_V2	0x80211002
1242 
1243 /*
1244  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
1245  * containing information such as radio information, which we
1246  * currently ignore.
1247  *
1248  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
1249  * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
1250  * (currently, on Linux, there's no ARPHRD_ type for
1251  * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
1252  * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
1253  * the AVS header, and the first 4 bytes of the header are used to
1254  * indicate whether it's a Prism header or an AVS header).
1255  */
1256 u_int
1257 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
1258 {
1259 	u_int caplen = h->caplen;
1260 	u_int length = h->len;
1261 	u_int32_t msgcode;
1262 
1263 	if (caplen < 4) {
1264 		printf("[|802.11]");
1265 		return caplen;
1266 	}
1267 
1268 	msgcode = EXTRACT_32BITS(p);
1269 	if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
1270 	    msgcode == WLANCAP_MAGIC_COOKIE_V2)
1271 		return ieee802_11_avs_radio_print(p, length, caplen);
1272 
1273 	if (caplen < PRISM_HDR_LEN) {
1274 		printf("[|802.11]");
1275 		return caplen;
1276 	}
1277 
1278 	return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
1279 	    length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN, 0);
1280 }
1281 
1282 /*
1283  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
1284  * header, containing information such as radio information.
1285  */
1286 u_int
1287 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
1288 {
1289 	return ieee802_11_radio_print(p, h->len, h->caplen);
1290 }
1291 
1292 /*
1293  * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
1294  * extra header, containing information such as radio information,
1295  * which we currently ignore.
1296  */
1297 u_int
1298 ieee802_11_radio_avs_if_print(const struct pcap_pkthdr *h, const u_char *p)
1299 {
1300 	return ieee802_11_avs_radio_print(p, h->len, h->caplen);
1301 }
1302