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