xref: /freebsd/contrib/tcpdump/print-802_11.c (revision c98323078dede7579020518ec84cdcb478e5c142)
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.22.2.6 2003/12/10 09:52:33 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 "ieee802_11.h"
45 
46 #define PRINT_RATES(p) \
47 do { \
48 	int z; \
49 	const char *sep = " ["; \
50 	for (z = 0; z < p.rates.length ; z++) { \
51 		printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \
52 		if (p.rates.rate[z] & 0x80) printf("*"); \
53 		sep = " "; \
54 	} \
55 	if (p.rates.length != 0) \
56 		printf(" Mbit]"); \
57 } while (0)
58 
59 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
60 static const char *subtype_text[]={
61 	"Assoc Request",
62 	"Assoc Response",
63 	"ReAssoc Request",
64 	"ReAssoc Response",
65 	"Probe Request",
66 	"Probe Response",
67 	"",
68 	"",
69 	"Beacon",
70 	"ATIM",
71 	"Disassociation",
72 	"Authentication",
73 	"DeAuthentication",
74 	"",
75 	""
76 };
77 
78 static const char *status_text[] = {
79 	"Succesful",  /*  0  */
80 	"Unspecified failure",  /*  1  */
81 	"Reserved",	  /*  2  */
82 	"Reserved",	  /*  3  */
83 	"Reserved",	  /*  4  */
84 	"Reserved",	  /*  5  */
85 	"Reserved",	  /*  6  */
86 	"Reserved",	  /*  7  */
87 	"Reserved",	  /*  8  */
88 	"Reserved",	  /*  9  */
89 	"Cannot Support all requested capabilities in the Capability Information field",	  /*  10  */
90 	"Reassociation denied due to inability to confirm that association exists",	  /*  11  */
91 	"Association denied due to reason outside the scope of the standard",	  /*  12  */
92 	"Responding station does not support the specified authentication algorithm ",	  /*  13  */
93 	"Received an Authentication frame with authentication transaction " \
94 		"sequence number out of expected sequence",	  /*  14  */
95 	"Authentication rejected because of challenge failure",	  /*  15 */
96 	"Authentication rejected due to timeout waiting for next frame in sequence",	  /*  16 */
97 	"Association denied because AP is unable to handle additional associated stations",	  /*  17 */
98 	"Association denied due to requesting station not supporting all of the " \
99 		"data rates in BSSBasicRateSet parameter",	  /*  18 */
100 	NULL
101 };
102 
103 static const char *reason_text[] = {
104 	"Reserved", /* 0 */
105 	"Unspecified reason", /* 1 */
106 	"Previous authentication no longer valid",  /* 2 */
107 	"Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
108 	"Disassociated due to inactivity", /* 4 */
109 	"Disassociated because AP is unable to handle all currently associated stations", /* 5 */
110 	"Class 2 frame receivedfrom nonauthenticated station", /* 6 */
111 	"Class 3 frame received from nonassociated station", /* 7 */
112 	"Disassociated because sending station is leaving (or has left) BSS", /* 8 */
113 	"Station requesting (re)association is not authenticated with responding station", /* 9 */
114 	NULL
115 };
116 
117 static int
118 wep_print(const u_char *p)
119 {
120 	u_int32_t iv;
121 
122 	if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
123 		return 0;
124 	iv = EXTRACT_LE_32BITS(p);
125 
126 	printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
127 	    IV_KEYID(iv));
128 
129 	return 1;
130 }
131 
132 static int
133 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
134 {
135 	for (;;) {
136 		if (!TTEST2(*(p + offset), 1))
137 			return 1;
138 		switch (*(p + offset)) {
139 		case E_SSID:
140 			if (!TTEST2(*(p + offset), 2))
141 				return 0;
142 			memcpy(&pbody->ssid, p + offset, 2);
143 			offset += 2;
144 			if (pbody->ssid.length <= 0)
145 				break;
146 			if (!TTEST2(*(p + offset), pbody->ssid.length))
147 				return 0;
148 			memcpy(&pbody->ssid.ssid, p + offset,
149 			    pbody->ssid.length);
150 			offset += pbody->ssid.length;
151 			pbody->ssid.ssid[pbody->ssid.length] = '\0';
152 			break;
153 		case E_CHALLENGE:
154 			if (!TTEST2(*(p + offset), 2))
155 				return 0;
156 			memcpy(&pbody->challenge, p + offset, 2);
157 			offset += 2;
158 			if (pbody->challenge.length <= 0)
159 				break;
160 			if (!TTEST2(*(p + offset), pbody->challenge.length))
161 				return 0;
162 			memcpy(&pbody->challenge.text, p + offset,
163 			    pbody->challenge.length);
164 			offset += pbody->challenge.length;
165 			pbody->challenge.text[pbody->challenge.length] = '\0';
166 			break;
167 		case E_RATES:
168 			if (!TTEST2(*(p + offset), 2))
169 				return 0;
170 			memcpy(&(pbody->rates), p + offset, 2);
171 			offset += 2;
172 			if (pbody->rates.length <= 0)
173 				break;
174 			if (!TTEST2(*(p + offset), pbody->rates.length))
175 				return 0;
176 			memcpy(&pbody->rates.rate, p + offset,
177 			    pbody->rates.length);
178 			offset += pbody->rates.length;
179 			break;
180 		case E_DS:
181 			if (!TTEST2(*(p + offset), 3))
182 				return 0;
183 			memcpy(&pbody->ds, p + offset, 3);
184 			offset += 3;
185 			break;
186 		case E_CF:
187 			if (!TTEST2(*(p + offset), 8))
188 				return 0;
189 			memcpy(&pbody->cf, p + offset, 8);
190 			offset += 8;
191 			break;
192 		case E_TIM:
193 			if (!TTEST2(*(p + offset), 2))
194 				return 0;
195 			memcpy(&pbody->tim, p + offset, 2);
196 			offset += 2;
197 			if (!TTEST2(*(p + offset), 3))
198 				return 0;
199 			memcpy(&pbody->tim.count, p + offset, 3);
200 			offset += 3;
201 
202 			if (pbody->tim.length <= 3)
203 				break;
204 			if (!TTEST2(*(p + offset), pbody->tim.length - 3))
205 				return 0;
206 			memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
207 			    (pbody->tim.length - 3));
208 			offset += pbody->tim.length - 3;
209 			break;
210 		default:
211 #if 0
212 			printf("(1) unhandled element_id (%d)  ",
213 			    *(p + offset) );
214 #endif
215 			offset += *(p + offset + 1) + 2;
216 			break;
217 		}
218 	}
219 	return 1;
220 }
221 
222 /*********************************************************************************
223  * Print Handle functions for the management frame types
224  *********************************************************************************/
225 
226 static int
227 handle_beacon(const u_char *p)
228 {
229 	struct mgmt_body_t pbody;
230 	int offset = 0;
231 
232 	memset(&pbody, 0, sizeof(pbody));
233 
234 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
235 	    IEEE802_11_CAPINFO_LEN))
236 		return 0;
237 	memcpy(&pbody.timestamp, p, 8);
238 	offset += IEEE802_11_TSTAMP_LEN;
239 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
240 	offset += IEEE802_11_BCNINT_LEN;
241 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
242 	offset += IEEE802_11_CAPINFO_LEN;
243 
244 	if (!parse_elements(&pbody, p, offset))
245 		return 0;
246 
247 	printf(" (");
248 	fn_print(pbody.ssid.ssid, NULL);
249 	printf(")");
250 	PRINT_RATES(pbody);
251 	printf(" %s CH: %u%s",
252 	    CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS",
253 	    pbody.ds.channel,
254 	    CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
255 
256 	return 1;
257 }
258 
259 static int
260 handle_assoc_request(const u_char *p)
261 {
262 	struct mgmt_body_t pbody;
263 	int offset = 0;
264 
265 	memset(&pbody, 0, sizeof(pbody));
266 
267 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
268 		return 0;
269 	pbody.capability_info = EXTRACT_LE_16BITS(p);
270 	offset += IEEE802_11_CAPINFO_LEN;
271 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
272 	offset += IEEE802_11_LISTENINT_LEN;
273 
274 	if (!parse_elements(&pbody, p, offset))
275 		return 0;
276 
277 	printf(" (");
278 	fn_print(pbody.ssid.ssid, NULL);
279 	printf(")");
280 	PRINT_RATES(pbody);
281 	return 1;
282 }
283 
284 static int
285 handle_assoc_response(const u_char *p)
286 {
287 	struct mgmt_body_t pbody;
288 	int offset = 0;
289 
290 	memset(&pbody, 0, sizeof(pbody));
291 
292 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
293 	    IEEE802_11_AID_LEN))
294 		return 0;
295 	pbody.capability_info = EXTRACT_LE_16BITS(p);
296 	offset += IEEE802_11_CAPINFO_LEN;
297 	pbody.status_code = EXTRACT_LE_16BITS(p+offset);
298 	offset += IEEE802_11_STATUS_LEN;
299 	pbody.aid = EXTRACT_LE_16BITS(p+offset);
300 	offset += IEEE802_11_AID_LEN;
301 
302 	if (!parse_elements(&pbody, p, offset))
303 		return 0;
304 
305 	printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
306 	    CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
307 	    (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a"));
308 
309 	return 1;
310 }
311 
312 static int
313 handle_reassoc_request(const u_char *p)
314 {
315 	struct mgmt_body_t pbody;
316 	int offset = 0;
317 
318 	memset(&pbody, 0, sizeof(pbody));
319 
320 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
321 	    IEEE802_11_AP_LEN))
322 		return 0;
323 	pbody.capability_info = EXTRACT_LE_16BITS(p);
324 	offset += IEEE802_11_CAPINFO_LEN;
325 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
326 	offset += IEEE802_11_LISTENINT_LEN;
327 	memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
328 	offset += IEEE802_11_AP_LEN;
329 
330 	if (!parse_elements(&pbody, p, offset))
331 		return 0;
332 
333 	printf(" (");
334 	fn_print(pbody.ssid.ssid, NULL);
335 	printf(") AP : %s", etheraddr_string( pbody.ap ));
336 
337 	return 1;
338 }
339 
340 static int
341 handle_reassoc_response(const u_char *p)
342 {
343 	/* Same as a Association Reponse */
344 	return handle_assoc_response(p);
345 }
346 
347 static int
348 handle_probe_request(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 (!parse_elements(&pbody, p, offset))
356 		return 0;
357 
358 	printf(" (");
359 	fn_print(pbody.ssid.ssid, NULL);
360 	printf(")");
361 	PRINT_RATES(pbody);
362 
363 	return 1;
364 }
365 
366 static int
367 handle_probe_response(const u_char *p)
368 {
369 	struct mgmt_body_t  pbody;
370 	int offset = 0;
371 
372 	memset(&pbody, 0, sizeof(pbody));
373 
374 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
375 	    IEEE802_11_CAPINFO_LEN))
376 		return 0;
377 
378 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
379 	offset += IEEE802_11_TSTAMP_LEN;
380 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
381 	offset += IEEE802_11_BCNINT_LEN;
382 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
383 	offset += IEEE802_11_CAPINFO_LEN;
384 
385 	if (!parse_elements(&pbody, p, offset))
386 		return 0;
387 
388 	printf(" (");
389 	fn_print(pbody.ssid.ssid, NULL);
390 	printf(") ");
391 	PRINT_RATES(pbody);
392 	printf(" CH: %u%s", pbody.ds.channel,
393 	    CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
394 
395 	return 1;
396 }
397 
398 static int
399 handle_atim(void)
400 {
401 	/* the frame body for ATIM is null. */
402 	return 1;
403 }
404 
405 static int
406 handle_disassoc(const u_char *p)
407 {
408 	struct mgmt_body_t  pbody;
409 
410 	memset(&pbody, 0, sizeof(pbody));
411 
412 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
413 		return 0;
414 	pbody.reason_code = EXTRACT_LE_16BITS(p);
415 
416 	printf(": %s",
417 	    (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
418 	                             : "Reserved" );
419 
420 	return 1;
421 }
422 
423 static int
424 handle_auth(const u_char *p)
425 {
426 	struct mgmt_body_t  pbody;
427 	int offset = 0;
428 
429 	memset(&pbody, 0, sizeof(pbody));
430 
431 	if (!TTEST2(*p, 6))
432 		return 0;
433 	pbody.auth_alg = EXTRACT_LE_16BITS(p);
434 	offset += 2;
435 	pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
436 	offset += 2;
437 	pbody.status_code = EXTRACT_LE_16BITS(p + offset);
438 	offset += 2;
439 
440 	if (!parse_elements(&pbody, p, offset))
441 		return 0;
442 
443 	if ((pbody.auth_alg == 1) &&
444 	    ((pbody.auth_trans_seq_num == 2) ||
445 	     (pbody.auth_trans_seq_num == 3))) {
446 		printf(" (%s)-%x [Challenge Text] %s",
447 		    (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg]
448 		                         : "Reserved",
449 		    pbody.auth_trans_seq_num,
450 		    ((pbody.auth_trans_seq_num % 2)
451 		        ? ((pbody.status_code < 19)
452 			       ? status_text[pbody.status_code]
453 			       : "n/a") : ""));
454 		return 1;
455 	}
456 	printf(" (%s)-%x: %s",
457 	    (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg] : "Reserved",
458 	    pbody.auth_trans_seq_num,
459 	    (pbody.auth_trans_seq_num % 2)
460 	        ? ((pbody.status_code < 19) ? status_text[pbody.status_code]
461 	                                    : "n/a")
462 	        : "");
463 
464 	return 1;
465 }
466 
467 static int
468 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
469 {
470 	struct mgmt_body_t  pbody;
471 	int offset = 0;
472 	const char *reason = NULL;
473 
474 	memset(&pbody, 0, sizeof(pbody));
475 
476 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
477 		return 0;
478 	pbody.reason_code = EXTRACT_LE_16BITS(p);
479 	offset += IEEE802_11_REASON_LEN;
480 
481 	reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
482 	                                  : "Reserved";
483 
484 	if (eflag) {
485 		printf(": %s", reason);
486 	} else {
487 		printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
488 	}
489 	return 1;
490 }
491 
492 
493 /*********************************************************************************
494  * Print Body funcs
495  *********************************************************************************/
496 
497 
498 static int
499 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
500     const u_char *p)
501 {
502 	printf("%s", subtype_text[FC_SUBTYPE(fc)]);
503 
504 	switch (FC_SUBTYPE(fc)) {
505 	case ST_ASSOC_REQUEST:
506 		return handle_assoc_request(p);
507 	case ST_ASSOC_RESPONSE:
508 		return handle_assoc_response(p);
509 	case ST_REASSOC_REQUEST:
510 		return handle_reassoc_request(p);
511 	case ST_REASSOC_RESPONSE:
512 		return handle_reassoc_response(p);
513 	case ST_PROBE_REQUEST:
514 		return handle_probe_request(p);
515 	case ST_PROBE_RESPONSE:
516 		return handle_probe_response(p);
517 	case ST_BEACON:
518 		return handle_beacon(p);
519 	case ST_ATIM:
520 		return handle_atim();
521 	case ST_DISASSOC:
522 		return handle_disassoc(p);
523 	case ST_AUTH:
524 		if (!TTEST2(*p, 3))
525 			return 0;
526 		if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
527 			printf("Authentication (Shared-Key)-3 ");
528 			return wep_print(p);
529 		}
530 		return handle_auth(p);
531 	case ST_DEAUTH:
532 		return handle_deauth(pmh, p);
533 		break;
534 	default:
535 		printf("Unhandled Management subtype(%x)",
536 		    FC_SUBTYPE(fc));
537 		return 1;
538 	}
539 }
540 
541 
542 /*********************************************************************************
543  * Handles printing all the control frame types
544  *********************************************************************************/
545 
546 static int
547 ctrl_body_print(u_int16_t fc, const u_char *p)
548 {
549 	switch (FC_SUBTYPE(fc)) {
550 	case CTRL_PS_POLL:
551 		printf("Power Save-Poll");
552 		if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
553 			return 0;
554 		printf(" AID(%x)",
555 		    EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
556 		break;
557 	case CTRL_RTS:
558 		printf("Request-To-Send");
559 		if (!TTEST2(*p, CTRL_RTS_HDRLEN))
560 			return 0;
561 		if (!eflag)
562 			printf(" TA:%s ",
563 			    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
564 		break;
565 	case CTRL_CTS:
566 		printf("Clear-To-Send");
567 		if (!TTEST2(*p, CTRL_CTS_HDRLEN))
568 			return 0;
569 		if (!eflag)
570 			printf(" RA:%s ",
571 			    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
572 		break;
573 	case CTRL_ACK:
574 		printf("Acknowledgment");
575 		if (!TTEST2(*p, CTRL_ACK_HDRLEN))
576 			return 0;
577 		if (!eflag)
578 			printf(" RA:%s ",
579 			    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
580 		break;
581 	case CTRL_CF_END:
582 		printf("CF-End");
583 		if (!TTEST2(*p, CTRL_END_HDRLEN))
584 			return 0;
585 		if (!eflag)
586 			printf(" RA:%s ",
587 			    etheraddr_string(((const struct ctrl_end_t *)p)->ra));
588 		break;
589 	case CTRL_END_ACK:
590 		printf("CF-End+CF-Ack");
591 		if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
592 			return 0;
593 		if (!eflag)
594 			printf(" RA:%s ",
595 			    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
596 		break;
597 	default:
598 		printf("Unknown Ctrl Subtype");
599 	}
600 	return 1;
601 }
602 
603 /*
604  * Print Header funcs
605  */
606 
607 /*
608  *  Data Frame - Address field contents
609  *
610  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
611  *    0    |  0      |  DA    | SA     | BSSID  | n/a
612  *    0    |  1      |  DA    | BSSID  | SA     | n/a
613  *    1    |  0      |  BSSID | SA     | DA     | n/a
614  *    1    |  1      |  RA    | TA     | DA     | SA
615  */
616 
617 static void
618 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
619     const u_int8_t **dstp)
620 {
621 	switch (FC_SUBTYPE(fc)) {
622 	case DATA_DATA:
623 	case DATA_NODATA:
624 		break;
625 	case DATA_DATA_CF_ACK:
626 	case DATA_NODATA_CF_ACK:
627 		printf("CF Ack ");
628 		break;
629 	case DATA_DATA_CF_POLL:
630 	case DATA_NODATA_CF_POLL:
631 		printf("CF Poll ");
632 		break;
633 	case DATA_DATA_CF_ACK_POLL:
634 	case DATA_NODATA_CF_ACK_POLL:
635 		printf("CF Ack/Poll ");
636 		break;
637 	}
638 
639 #define ADDR1  (p + 4)
640 #define ADDR2  (p + 10)
641 #define ADDR3  (p + 16)
642 #define ADDR4  (p + 24)
643 
644 	if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
645 		if (srcp != NULL)
646 			*srcp = ADDR2;
647 		if (dstp != NULL)
648 			*dstp = ADDR1;
649 		if (!eflag)
650 			return;
651 		printf("DA:%s SA:%s BSSID:%s ",
652 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
653 		    etheraddr_string(ADDR3));
654 	} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
655 		if (srcp != NULL)
656 			*srcp = ADDR3;
657 		if (dstp != NULL)
658 			*dstp = ADDR1;
659 		if (!eflag)
660 			return;
661 		printf("DA:%s BSSID:%s SA:%s ",
662 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
663 		    etheraddr_string(ADDR3));
664 	} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
665 		if (srcp != NULL)
666 			*srcp = ADDR2;
667 		if (dstp != NULL)
668 			*dstp = ADDR3;
669 		if (!eflag)
670 			return;
671 		printf("BSSID:%s SA:%s DA:%s ",
672 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
673 		    etheraddr_string(ADDR3));
674 	} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
675 		if (srcp != NULL)
676 			*srcp = ADDR4;
677 		if (dstp != NULL)
678 			*dstp = ADDR3;
679 		if (!eflag)
680 			return;
681 		printf("RA:%s TA:%s DA:%s SA:%s ",
682 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
683 		    etheraddr_string(ADDR3), etheraddr_string(ADDR4));
684 	}
685 
686 #undef ADDR1
687 #undef ADDR2
688 #undef ADDR3
689 #undef ADDR4
690 }
691 
692 static void
693 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
694     const u_int8_t **dstp)
695 {
696 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
697 
698 	if (srcp != NULL)
699 		*srcp = hp->sa;
700 	if (dstp != NULL)
701 		*dstp = hp->da;
702 	if (!eflag)
703 		return;
704 
705 	printf("BSSID:%s DA:%s SA:%s ",
706 	    etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
707 	    etheraddr_string((hp)->sa));
708 }
709 
710 static void
711 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
712     const u_int8_t **dstp)
713 {
714 	if (srcp != NULL)
715 		*srcp = NULL;
716 	if (dstp != NULL)
717 		*dstp = NULL;
718 	if (!eflag)
719 		return;
720 
721 	switch (FC_SUBTYPE(fc)) {
722 	case CTRL_PS_POLL:
723 		printf("BSSID:%s TA:%s ",
724 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
725 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
726 		break;
727 	case CTRL_RTS:
728 		printf("RA:%s TA:%s ",
729 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
730 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
731 		break;
732 	case CTRL_CTS:
733 		printf("RA:%s ",
734 		    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
735 		break;
736 	case CTRL_ACK:
737 		printf("RA:%s ",
738 		    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
739 		break;
740 	case CTRL_CF_END:
741 		printf("RA:%s BSSID:%s ",
742 		    etheraddr_string(((const struct ctrl_end_t *)p)->ra),
743 		    etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
744 		break;
745 	case CTRL_END_ACK:
746 		printf("RA:%s BSSID:%s ",
747 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
748 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
749 		break;
750 	default:
751 		printf("(H) Unknown Ctrl Subtype");
752 		break;
753 	}
754 }
755 
756 static int
757 extract_header_length(u_int16_t fc)
758 {
759 	switch (FC_TYPE(fc)) {
760 	case T_MGMT:
761 		return MGMT_HDRLEN;
762 	case T_CTRL:
763 		switch (FC_SUBTYPE(fc)) {
764 		case CTRL_PS_POLL:
765 			return CTRL_PS_POLL_HDRLEN;
766 		case CTRL_RTS:
767 			return CTRL_RTS_HDRLEN;
768 		case CTRL_CTS:
769 			return CTRL_CTS_HDRLEN;
770 		case CTRL_ACK:
771 			return CTRL_ACK_HDRLEN;
772 		case CTRL_CF_END:
773 			return CTRL_END_HDRLEN;
774 		case CTRL_END_ACK:
775 			return CTRL_END_ACK_HDRLEN;
776 		default:
777 			return 0;
778 		}
779 	case T_DATA:
780 		return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
781 	default:
782 		printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
783 		return 0;
784 	}
785 }
786 
787 /*
788  * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
789  * to point to the source and destination MAC addresses in any case if
790  * "srcp" and "dstp" aren't null.
791  */
792 static inline void
793 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
794     const u_int8_t **dstp)
795 {
796 	if (vflag) {
797 		if (FC_MORE_DATA(fc))
798 			printf("More Data ");
799 		if (FC_MORE_FLAG(fc))
800 			printf("More Fragments ");
801 		if (FC_POWER_MGMT(fc))
802 			printf("Pwr Mgmt ");
803 		if (FC_RETRY(fc))
804 			printf("Retry ");
805 		if (FC_ORDER(fc))
806 			printf("Strictly Ordered ");
807 		if (FC_WEP(fc))
808 			printf("WEP Encrypted ");
809 		if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
810 			printf("%dus ",
811 			    EXTRACT_LE_16BITS(
812 			        &((const struct mgmt_header_t *)p)->duration));
813 	}
814 
815 	switch (FC_TYPE(fc)) {
816 	case T_MGMT:
817 		mgmt_header_print(p, srcp, dstp);
818 		break;
819 	case T_CTRL:
820 		ctrl_header_print(fc, p, srcp, dstp);
821 		break;
822 	case T_DATA:
823 		data_header_print(fc, p, srcp, dstp);
824 		break;
825 	default:
826 		printf("(header) unknown IEEE802.11 frame type (%d)",
827 		    FC_TYPE(fc));
828 		*srcp = NULL;
829 		*dstp = NULL;
830 		break;
831 	}
832 }
833 
834 static u_int
835 ieee802_11_print(const u_char *p, u_int length, u_int caplen)
836 {
837 	u_int16_t fc;
838 	u_int hdrlen;
839 	const u_int8_t *src, *dst;
840 	u_short extracted_ethertype;
841 
842 	if (caplen < IEEE802_11_FC_LEN) {
843 		printf("[|802.11]");
844 		return caplen;
845 	}
846 
847 	fc = EXTRACT_LE_16BITS(p);
848 	hdrlen = extract_header_length(fc);
849 
850 	if (caplen < hdrlen) {
851 		printf("[|802.11]");
852 		return hdrlen;
853 	}
854 
855 	ieee_802_11_hdr_print(fc, p, &src, &dst);
856 
857 	/*
858 	 * Go past the 802.11 header.
859 	 */
860 	length -= hdrlen;
861 	caplen -= hdrlen;
862 	p += hdrlen;
863 
864 	switch (FC_TYPE(fc)) {
865 	case T_MGMT:
866 		if (!mgmt_body_print(fc,
867 		    (const struct mgmt_header_t *)(p - hdrlen), p)) {
868 			printf("[|802.11]");
869 			return hdrlen;
870 		}
871 		break;
872 	case T_CTRL:
873 		if (!ctrl_body_print(fc, p - hdrlen)) {
874 			printf("[|802.11]");
875 			return hdrlen;
876 		}
877 		break;
878 	case T_DATA:
879 		/* There may be a problem w/ AP not having this bit set */
880 		if (FC_WEP(fc)) {
881 			if (!wep_print(p)) {
882 				printf("[|802.11]");
883 				return hdrlen;
884 			}
885 		} else if (llc_print(p, length, caplen, dst, src,
886 		    &extracted_ethertype) == 0) {
887 			/*
888 			 * Some kinds of LLC packet we cannot
889 			 * handle intelligently
890 			 */
891 			if (!eflag)
892 				ieee_802_11_hdr_print(fc, p - hdrlen, NULL,
893 				    NULL);
894 			if (extracted_ethertype)
895 				printf("(LLC %s) ",
896 				    etherproto_string(
897 				        htons(extracted_ethertype)));
898 			if (!xflag && !qflag)
899 				default_print(p, caplen);
900 		}
901 		break;
902 	default:
903 		printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
904 		break;
905 	}
906 
907 	return hdrlen;
908 }
909 
910 /*
911  * This is the top level routine of the printer.  'p' points
912  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
913  * 'h->length' is the length of the packet off the wire, and 'h->caplen'
914  * is the number of bytes actually captured.
915  */
916 u_int
917 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
918 {
919 	return ieee802_11_print(p, h->len, h->caplen);
920 }
921 
922 static u_int
923 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
924 {
925 	u_int32_t caphdr_len;
926 
927 	caphdr_len = EXTRACT_32BITS(p + 4);
928 	if (caphdr_len < 8) {
929 		/*
930 		 * Yow!  The capture header length is claimed not
931 		 * to be large enough to include even the version
932 		 * cookie or capture header length!
933 		 */
934 		printf("[|802.11]");
935 		return caplen;
936 	}
937 
938 	if (caplen < caphdr_len) {
939 		printf("[|802.11]");
940 		return caplen;
941 	}
942 
943 	return caphdr_len + ieee802_11_print(p + caphdr_len,
944 	    length - caphdr_len, caplen - caphdr_len);
945 }
946 
947 #define PRISM_HDR_LEN		144
948 
949 #define WLANCAP_MAGIC_COOKIE_V1	0x80211001
950 
951 /*
952  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
953  * containing information such as radio information, which we
954  * currently ignore.
955  *
956  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
957  * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
958  * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
959  * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
960  * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
961  * the first 4 bytes of the header are used to indicate which it is).
962  */
963 u_int
964 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
965 {
966 	u_int caplen = h->caplen;
967 	u_int length = h->len;
968 
969 	if (caplen < 4) {
970 		printf("[|802.11]");
971 		return caplen;
972 	}
973 
974 	if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
975 		return ieee802_11_radio_print(p, length, caplen);
976 
977 	if (caplen < PRISM_HDR_LEN) {
978 		printf("[|802.11]");
979 		return caplen;
980 	}
981 
982 	return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
983 	    length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN);
984 }
985 
986 /*
987  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
988  * header, containing information such as radio information, which we
989  * currently ignore.
990  */
991 u_int
992 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
993 {
994 	u_int caplen = h->caplen;
995 	u_int length = h->len;
996 
997 	if (caplen < 8) {
998 		printf("[|802.11]");
999 		return caplen;
1000 	}
1001 
1002 	return ieee802_11_radio_print(p, length, caplen);
1003 }
1004