xref: /freebsd/contrib/tcpdump/print-802_11.c (revision f9218d3d4fd34f082473b3a021c6d4d109fb47cf)
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[] =
25     "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.6.4.1 2002/05/13 08:34:50 guy Exp $ (LBL)";
26 #endif
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/socket.h>
35 
36 #include <netinet/in.h>
37 
38 #include <stdio.h>
39 #include <pcap.h>
40 #include <string.h>
41 
42 #include "interface.h"
43 #include "addrtoname.h"
44 #include "ethertype.h"
45 
46 #include "extract.h"
47 
48 #include "ieee802_11.h"
49 
50 #define PRINT_RATES(p) \
51 do { \
52 	int z; \
53 	char *sep = " ["; \
54 	for (z = 0; z < p.rates.length ; z++) { \
55 		printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \
56 		sep = " "; \
57 	} \
58 	if (p.rates.length != 0) \
59 		printf(" Mbit]"); \
60 } while (0)
61 
62 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
63 static const char *subtype_text[]={
64 	"Assoc Request",
65 	"Assoc Response",
66 	"ReAssoc Request",
67 	"ReAssoc Response",
68 	"Probe Request",
69 	"Probe Response",
70 	"RESERVED",
71 	"RESERVED",
72 	"Beacon",
73 	"ATIM",
74 	"Disassociation",
75 	"Authentication",
76 	"DeAuthentication",
77 	"RESERVED",
78 	"RESERVED"
79 };
80 
81 static const char *status_text[] = {
82 	"Succesful",  /*  0  */
83 	"Unspecified failure",  /*  1  */
84 	"Reserved",	  /*  2  */
85 	"Reserved",	  /*  3  */
86 	"Reserved",	  /*  4  */
87 	"Reserved",	  /*  5  */
88 	"Reserved",	  /*  6  */
89 	"Reserved",	  /*  7  */
90 	"Reserved",	  /*  8  */
91 	"Reserved",	  /*  9  */
92 	"Cannot Support all requested capabilities in the Capability Information field",	  /*  10  */
93 	"Reassociation denied due to inability to confirm that association exists",	  /*  11  */
94 	"Association denied due to reason outside the scope of the standard",	  /*  12  */
95 	"Responding station does not support the specified authentication algorithm ",	  /*  13  */
96 	"Received an Authentication frame with authentication transaction " \
97 		"sequence number out of expected sequence",	  /*  14  */
98 	"Authentication rejected because of challenge failure",	  /*  15 */
99 	"Authentication rejected due to timeout waiting for next frame in sequence",	  /*  16 */
100 	"Association denied because AP is unable to handle additional associated stations",	  /*  17 */
101 	"Association denied due to requesting station not supporting all of the " \
102 		"data rates in BSSBasicRateSet parameter",	  /*  18 */
103 	NULL
104 };
105 
106 static const char *reason_text[] = {
107 	"Reserved", /* 0 */
108 	"Unspecified reason", /* 1 */
109 	"Previous authentication no longer valid",  /* 2 */
110 	"Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
111 	"Disassociated due to inactivity", /* 4 */
112 	"Disassociated because AP is unable to handle all currently associated stations", /* 5 */
113 	"Class 2 frame receivedfrom nonauthenticated station", /* 6 */
114 	"Class 3 frame received from nonassociated station", /* 7 */
115 	"Disassociated because sending station is leaving (or has left) BSS", /* 8 */
116 	"Station requesting (re)association is not authenticated with responding station", /* 9 */
117 	NULL
118 };
119 
120 static int wep_print(const u_char *p,u_int length)
121 {
122 	u_int32_t iv;
123 
124 	if (!TTEST2(*p, 4))
125 		return 0;
126 	iv = EXTRACT_LE_32BITS(p);
127 
128 	printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
129 	    IV_KEYID(iv));
130 
131 	return 1;
132 }
133 
134 
135 static int parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset)
136 {
137 	for (;;) {
138 		if (!TTEST2(*(p + offset), 1))
139 			return 1;
140 		switch (*(p + offset)) {
141 		case E_SSID:
142 			if (!TTEST2(*(p+offset), 2))
143 				return 0;
144 			memcpy(&(pbody->ssid),p+offset,2); offset += 2;
145 			if (pbody->ssid.length > 0)
146 			{
147 				if (!TTEST2(*(p+offset), pbody->ssid.length))
148 					return 0;
149 				memcpy(&(pbody->ssid.ssid),p+offset,pbody->ssid.length); offset += pbody->ssid.length;
150 				pbody->ssid.ssid[pbody->ssid.length]='\0';
151 			}
152 			break;
153 		case E_CHALLENGE:
154 			if (!TTEST2(*(p+offset), 2))
155 				return 0;
156 			memcpy(&(pbody->challenge),p+offset,2); offset += 2;
157 			if (pbody->challenge.length > 0)
158 			{
159 				if (!TTEST2(*(p+offset), pbody->challenge.length))
160 					return 0;
161 				memcpy(&(pbody->challenge.text),p+offset,pbody->challenge.length); offset += pbody->challenge.length;
162 				pbody->challenge.text[pbody->challenge.length]='\0';
163 			}
164 			break;
165 		case E_RATES:
166 			if (!TTEST2(*(p+offset), 2))
167 				return 0;
168 			memcpy(&(pbody->rates),p+offset,2); offset += 2;
169 			if (pbody->rates.length > 0) {
170 				if (!TTEST2(*(p+offset), pbody->rates.length))
171 					return 0;
172 				memcpy(&(pbody->rates.rate),p+offset,pbody->rates.length); offset += pbody->rates.length;
173 			}
174 			break;
175 		case E_DS:
176 			if (!TTEST2(*(p+offset), 3))
177 				return 0;
178 			memcpy(&(pbody->ds),p+offset,3); offset +=3;
179 			break;
180 		case E_CF:
181 			if (!TTEST2(*(p+offset), 8))
182 				return 0;
183 			memcpy(&(pbody->cf),p+offset,8); offset +=8;
184 			break;
185 		case E_TIM:
186 			if (!TTEST2(*(p+offset), 2))
187 				return 0;
188 			memcpy(&(pbody->tim),p+offset,2); offset +=2;
189 			if (!TTEST2(*(p+offset), 3))
190 				return 0;
191 			memcpy(&(pbody->tim.count),p+offset,3); offset +=3;
192 
193 			if ((pbody->tim.length -3) > 0)
194 			{
195 				if (!TTEST2(*(p+offset), pbody->tim.length -3))
196 					return 0;
197 				memcpy((pbody->tim.bitmap),p+(pbody->tim.length -3),(pbody->tim.length -3));
198 				offset += pbody->tim.length -3;
199 			}
200 
201 			break;
202 		default:
203 #if 0
204 			printf("(1) unhandled element_id (%d)  ", *(p+offset) );
205 #endif
206 			offset+= *(p+offset+1) + 2;
207 			break;
208 		}
209 	}
210 	return 1;
211 }
212 
213 /*********************************************************************************
214  * Print Handle functions for the management frame types
215  *********************************************************************************/
216 
217 static int handle_beacon(u_int16_t fc, const struct mgmt_header_t *pmh,
218     const u_char *p)
219 {
220 	struct mgmt_body_t pbody;
221 	int offset = 0;
222 
223 	memset(&pbody, 0, sizeof(pbody));
224 
225 	if (!TTEST2(*p, 12))
226 		return 0;
227 	memcpy(&pbody.timestamp, p, 8);
228 	offset += 8;
229 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
230 	offset += 2;
231 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
232 	offset += 2;
233 
234 	if (!parse_elements(&pbody,p,offset))
235 		return 0;
236 
237 	printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
238 	fn_print(pbody.ssid.ssid, NULL);
239 	printf(")");
240 	PRINT_RATES(pbody);
241 	printf(" %s CH: %u %s",
242 	    CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS",
243 	    pbody.ds.channel,
244 	    CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
245 
246 	return 1;
247 }
248 
249 static int handle_assoc_request(u_int16_t fc, const struct mgmt_header_t *pmh,
250     const u_char *p)
251 {
252 	struct mgmt_body_t pbody;
253 	int offset = 0;
254 
255 	memset(&pbody, 0, sizeof(pbody));
256 
257 	if (!TTEST2(*p, 4))
258 		return 0;
259 	pbody.capability_info = EXTRACT_LE_16BITS(p);
260 	offset += 2;
261 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
262 	offset += 2;
263 
264 	if (!parse_elements(&pbody,p,offset))
265 		return 0;
266 
267 	printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
268 	fn_print(pbody.ssid.ssid, NULL);
269 	printf(")");
270 	PRINT_RATES(pbody);
271 	return 1;
272 }
273 
274 static int handle_assoc_response(u_int16_t fc, const struct mgmt_header_t *pmh,
275     const u_char *p)
276 {
277 	struct mgmt_body_t pbody;
278 	int offset = 0;
279 
280 	memset(&pbody, 0, sizeof(pbody));
281 
282 	if (!TTEST2(*p, 6))
283 		return 0;
284 	pbody.capability_info = EXTRACT_LE_16BITS(p);
285 	offset += 2;
286 	pbody.status_code = EXTRACT_LE_16BITS(p+offset);
287 	offset += 2;
288 	pbody.aid = EXTRACT_LE_16BITS(p+offset);
289 	offset += 2;
290 
291 	if (!parse_elements(&pbody,p,offset))
292 		return 0;
293 
294 	printf("%s AID(%x) :%s: %s", subtype_text[FC_SUBTYPE(fc)],
295 	    ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
296 	    CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
297 	    (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a"));
298 
299 	return 1;
300 }
301 
302 
303 static int handle_reassoc_request(u_int16_t fc, const struct mgmt_header_t *pmh,
304     const u_char *p)
305 {
306 	struct mgmt_body_t pbody;
307 	int offset = 0;
308 
309 	memset(&pbody, 0, sizeof(pbody));
310 
311 	if (!TTEST2(*p, 10))
312 		return 0;
313 	pbody.capability_info = EXTRACT_LE_16BITS(p);
314 	offset += 2;
315 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
316 	offset += 2;
317 	memcpy(&pbody.ap,p+offset,6);
318 	offset += 6;
319 
320 	if (!parse_elements(&pbody,p,offset))
321 		return 0;
322 
323 	printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
324 	fn_print(pbody.ssid.ssid, NULL);
325 	printf(") AP : %s", etheraddr_string( pbody.ap ));
326 
327 	return 1;
328 }
329 
330 static int handle_reassoc_response(u_int16_t fc, const struct mgmt_header_t *pmh,
331     const u_char *p)
332 {
333 	/* Same as a Association Reponse */
334 	return handle_assoc_response(fc,pmh,p);
335 }
336 
337 static int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh,
338     const u_char *p)
339 {
340 	struct mgmt_body_t  pbody;
341 	int offset = 0;
342 
343 	memset(&pbody, 0, sizeof(pbody));
344 
345 	if (!parse_elements(&pbody, p, offset))
346 		return 0;
347 
348 	printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
349 	fn_print(pbody.ssid.ssid, NULL);
350 	printf(")");
351 	PRINT_RATES(pbody);
352 
353 	return 1;
354 }
355 
356 static int handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh,
357     const u_char *p)
358 {
359 	struct mgmt_body_t  pbody;
360 	int offset = 0;
361 
362 	memset(&pbody, 0, sizeof(pbody));
363 
364 	if (!TTEST2(*p, 12))
365 		return 0;
366 	memcpy(&pbody.timestamp,p,8);
367 	offset += 8;
368 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
369 	offset += 2;
370 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
371 	offset += 2;
372 
373 	if (!parse_elements(&pbody, p, offset))
374 		return 0;
375 
376 	printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
377 	fn_print(pbody.ssid.ssid, NULL);
378 	printf(") ");
379 	PRINT_RATES(pbody);
380 	printf(" CH: %u%s", pbody.ds.channel,
381 	    CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
382 
383 	return 1;
384 }
385 
386 static int handle_atim(u_int16_t fc, const struct mgmt_header_t *pmh,
387     const u_char *p)
388 {
389 	/* the frame body for ATIM is null. */
390 	printf("ATIM");
391 	return 1;
392 }
393 
394 static int handle_disassoc(u_int16_t fc, const struct mgmt_header_t *pmh,
395     const u_char *p)
396 {
397 	struct mgmt_body_t  pbody;
398 	int offset = 0;
399 
400 	memset(&pbody, 0, sizeof(pbody));
401 
402 	if (!TTEST2(*p, 2))
403 		return 0;
404 	pbody.reason_code = EXTRACT_LE_16BITS(p);
405 	offset += 2;
406 
407 	printf("%s: %s", subtype_text[FC_SUBTYPE(fc)],
408 	    pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
409 
410 	return 1;
411 }
412 
413 static int handle_auth(u_int16_t fc, const struct mgmt_header_t *pmh,
414     const u_char *p)
415 {
416 	struct mgmt_body_t  pbody;
417 	int offset = 0;
418 
419 	memset(&pbody, 0, sizeof(pbody));
420 
421 	if (!TTEST2(*p, 6))
422 		return 0;
423 	pbody.auth_alg = EXTRACT_LE_16BITS(p);
424 	offset += 2;
425 	pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
426 	offset += 2;
427 	pbody.status_code = EXTRACT_LE_16BITS(p + offset);
428 	offset += 2;
429 
430 	if (!parse_elements(&pbody,p,offset))
431 		return 0;
432 
433 	if ((pbody.auth_alg == 1) &&
434 	    ((pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3))) {
435 		printf("%s (%s)-%x [Challenge Text] %s",
436 			subtype_text[FC_SUBTYPE(fc)],
437 			pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" ,
438 			pbody.auth_trans_seq_num,
439 			 ((pbody.auth_trans_seq_num % 2) ?
440 				(pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : "" ));
441 	} else {
442 		printf("%s (%s)-%x: %s",
443 		    subtype_text[FC_SUBTYPE(fc)],
444 		    pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" ,
445 		    pbody.auth_trans_seq_num,
446 		    ((pbody.auth_trans_seq_num % 2) ? (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a")  : ""));
447 	}
448 
449 	return 1;
450 }
451 
452 static int handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh,
453     const u_char *p)
454 {
455 	struct mgmt_body_t  pbody;
456 	int offset = 0;
457 
458 	memset(&pbody, 0, sizeof(pbody));
459 
460 	if (!TTEST2(*p, 2))
461 		return 0;
462 	pbody.reason_code = EXTRACT_LE_16BITS(p);
463 	offset += 2;
464 
465 	if (eflag) {
466 		printf("%s: %s",
467 		    subtype_text[FC_SUBTYPE(fc)],
468 		    pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
469 	} else {
470 		printf("%s (%s): %s",
471 		    subtype_text[FC_SUBTYPE(fc)], etheraddr_string(pmh->sa),
472 		    pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
473 	}
474 
475 	return 1;
476 }
477 
478 
479 /*********************************************************************************
480  * Print Body funcs
481  *********************************************************************************/
482 
483 
484 static int mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
485     const u_char *p, u_int length)
486 {
487 	switch (FC_SUBTYPE(fc)) {
488 	case ST_ASSOC_REQUEST:
489 		return (handle_assoc_request(fc, pmh, p));
490 	case ST_ASSOC_RESPONSE:
491 		return (handle_assoc_response(fc, pmh, p));
492 	case ST_REASSOC_REQUEST:
493 		return (handle_reassoc_request(fc, pmh, p));
494 	case ST_REASSOC_RESPONSE:
495 		return (handle_reassoc_response(fc, pmh, p));
496 	case ST_PROBE_REQUEST:
497 		return (handle_probe_request(fc, pmh, p));
498 	case ST_PROBE_RESPONSE:
499 		return (handle_probe_response(fc, pmh, p));
500 	case ST_BEACON:
501 		return (handle_beacon(fc, pmh, p));
502 	case ST_ATIM:
503 		return (handle_atim(fc, pmh, p));
504 	case ST_DISASSOC:
505 		return (handle_disassoc(fc, pmh, p));
506 	case ST_AUTH:
507 		if (!TTEST2(*p, 3))
508 			return 0;
509 		if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
510 			printf("Authentication (Shared-Key)-3 ");
511 			return (wep_print(p, length));
512 		}
513 		else
514 			return (handle_auth(fc, pmh, p));
515 	case ST_DEAUTH:
516 		return (handle_deauth(fc, pmh, p));
517 		break;
518 	default:
519 		printf("Unhandled Managment subtype(%x)",
520 		    FC_SUBTYPE(fc));
521 		return 1;
522 	}
523 }
524 
525 
526 /*********************************************************************************
527  * Handles printing all the control frame types
528  *********************************************************************************/
529 
530 static int ctrl_body_print(u_int16_t fc,const u_char *p, u_int length)
531 {
532 	switch (FC_SUBTYPE(fc)) {
533 	case CTRL_PS_POLL:
534 		if (!TTEST2(*p, CTRL_PS_POLL_LEN))
535 			return 0;
536 		printf("Power Save-Poll AID(%x)",
537 		    EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
538 		break;
539 	case CTRL_RTS:
540 		if (!TTEST2(*p, CTRL_RTS_LEN))
541 			return 0;
542 		if (eflag)
543 			printf("Request-To-Send");
544 		else
545 			printf("Request-To-Send TA:%s ",
546 			    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
547 		break;
548 	case CTRL_CTS:
549 		if (!TTEST2(*p, CTRL_CTS_LEN))
550 			return 0;
551 		if (eflag)
552 			printf("Clear-To-Send");
553 		else
554 			printf("Clear-To-Send RA:%s ",
555 			    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
556 		break;
557 	case CTRL_ACK:
558 		if (!TTEST2(*p, CTRL_ACK_LEN))
559 			return 0;
560 		if (eflag)
561 			printf("Acknowledgment");
562 		else
563 			printf("Acknowledgment RA:%s ",
564 			    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
565 		break;
566 	case CTRL_CF_END:
567 		if (!TTEST2(*p, CTRL_END_LEN))
568 			return 0;
569 		if (eflag)
570 			printf("CF-End");
571 		else
572 			printf("CF-End RA:%s ",
573 			    etheraddr_string(((const struct ctrl_end_t *)p)->ra));
574 		break;
575 	case CTRL_END_ACK:
576 		if (!TTEST2(*p, CTRL_END_ACK_LEN))
577 			return 0;
578 		if (eflag)
579 			printf("CF-End+CF-Ack");
580 		else
581 			printf("CF-End+CF-Ack RA:%s ",
582 			    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
583 		break;
584 	default:
585 		printf("(B) Unknown Ctrl Subtype");
586 	}
587 	return 1;
588 }
589 
590 
591 
592 /*
593  * Print Header funcs
594  */
595 
596 /*
597  *  Data Frame - Address field contents
598  *
599  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
600  *    0    |  0      |  DA    | SA     | BSSID  | n/a
601  *    0    |  1      |  DA    | BSSID  | SA     | n/a
602  *    1    |  0      |  BSSID | SA     | DA     | n/a
603  *    1    |  1      |  RA    | TA     | DA     | SA
604  */
605 
606 static void data_header_print(u_int16_t fc,const u_char *p, u_int length)
607 {
608 #define ADDR1  (p + 4)
609 #define ADDR2  (p + 10)
610 #define ADDR3  (p + 16)
611 #define ADDR4  (p + 24)
612 
613 	if (!FC_TO_DS(fc)) {
614 		if (!FC_FROM_DS(fc))
615 			printf("DA:%s SA:%s BSSID:%s ",
616 			    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
617 			    etheraddr_string(ADDR3));
618 		else
619 			printf("DA:%s BSSID:%s SA:%s ",
620 			    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
621 			    etheraddr_string(ADDR3));
622 	} else {
623 		if (!FC_FROM_DS(fc))
624 			printf("BSSID:%s SA:%s DA:%s ",
625 			    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
626 			    etheraddr_string(ADDR3));
627 		else
628 			printf("RA:%s TA:%s DA:%s SA:%s ",
629 			    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
630 			    etheraddr_string(ADDR3), etheraddr_string(ADDR4));
631 	}
632 
633 #undef ADDR1
634 #undef ADDR2
635 #undef ADDR3
636 #undef ADDR4
637 }
638 
639 
640 static void mgmt_header_print(const u_char *p, u_int length)
641 {
642 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
643 
644 	printf("BSSID:%s DA:%s SA:%s ",
645 	    etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
646 	    etheraddr_string((hp)->sa));
647 }
648 
649 static void ctrl_header_print(u_int16_t fc,const u_char *p, u_int length)
650 {
651 	switch (FC_SUBTYPE(fc)) {
652 	case CTRL_PS_POLL:
653 		printf("BSSID:%s TA:%s ",
654 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
655 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
656 		break;
657 	case CTRL_RTS:
658 		printf("RA:%s TA:%s ",
659 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
660 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
661 		break;
662 	case CTRL_CTS:
663 		printf("RA:%s ",
664 		    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
665 		break;
666 	case CTRL_ACK:
667 		printf("RA:%s ",
668 		    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
669 		break;
670 	case CTRL_CF_END:
671 		printf("RA:%s BSSID:%s ",
672 		    etheraddr_string(((const struct ctrl_end_t *)p)->ra),
673 		    etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
674 		break;
675 	case CTRL_END_ACK:
676 		printf("RA:%s BSSID:%s ",
677 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
678 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
679 		break;
680 	default:
681 		printf("(H) Unknown Ctrl Subtype");
682 	}
683 }
684 
685 static int GetHeaderLength(u_int16_t fc)
686 {
687 	int iLength=0;
688 
689 	switch (FC_TYPE(fc)) {
690 	case T_MGMT:
691 		iLength = MGMT_HEADER_LEN;
692 		break;
693 	case T_CTRL:
694 		switch (FC_SUBTYPE(fc)) {
695 		case CTRL_PS_POLL:
696 			iLength = CTRL_PS_POLL_LEN;
697 			break;
698 		case CTRL_RTS:
699 			iLength = CTRL_RTS_LEN;
700 			break;
701 		case CTRL_CTS:
702 			iLength = CTRL_CTS_LEN;
703 			break;
704 		case CTRL_ACK:
705 			iLength = CTRL_ACK_LEN;
706 			break;
707 		case CTRL_CF_END:
708 			iLength = CTRL_END_LEN;
709 			break;
710 		case CTRL_END_ACK:
711 			iLength = CTRL_END_ACK_LEN;
712 			break;
713 		default:
714 			iLength = 0;
715 			break;
716 		}
717 		break;
718 	case T_DATA:
719 		if (FC_TO_DS(fc) && FC_FROM_DS(fc))
720 			iLength = 30;
721 		else
722 			iLength = 24;
723 		break;
724 	default:
725 		printf("unknown IEEE802.11 frame type (%d)",
726 		    FC_TYPE(fc));
727 		break;
728 	}
729 
730 	return iLength;
731 }
732 
733 /*
734  * Print the 802.11 MAC header
735  */
736 static inline void
737 ieee_802_11_print(u_int16_t fc, const u_char *p, u_int length)
738 {
739 	switch (FC_TYPE(fc)) {
740 	case T_MGMT:
741 		mgmt_header_print(p, length);
742 		break;
743 
744 	case T_CTRL:
745 		ctrl_header_print(fc, p, length);
746 		break;
747 
748 	case T_DATA:
749 		data_header_print(fc, p, length);
750 		break;
751 
752 	default:
753 		printf("(header) unknown IEEE802.11 frame type (%d)",
754 		    FC_TYPE(fc));
755 		break;
756 	}
757 }
758 
759 /*
760  * This is the top level routine of the printer.  'p' is the points
761  * to the ether header of the packet, 'h->tv' is the timestamp,
762  * 'h->length' is the length of the packet off the wire, and 'h->caplen'
763  * is the number of bytes actually captured.
764  */
765 void
766 ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
767 {
768 	u_int caplen = h->caplen;
769 	u_int length = h->len;
770 	u_int16_t fc;
771 	u_int HEADER_LENGTH;
772 	u_short extracted_ethertype;
773 
774 	++infodelay;
775 	ts_print(&h->ts);
776 
777 	if (caplen < IEEE802_11_FC_LEN) {
778 		printf("[|802.11]");
779 		goto out;
780 	}
781 
782 	fc=EXTRACT_LE_16BITS(p);
783 
784 	if (eflag)
785 		ieee_802_11_print(fc, p, length);
786 
787 	/*
788 	 * Some printers want to get back at the ethernet addresses,
789 	 * and/or check that they're not walking off the end of the packet.
790 	 * Rather than pass them all the way down, we set these globals.
791 	 */
792 	packetp = p;
793 	snapend = p + caplen;
794 
795 	HEADER_LENGTH=GetHeaderLength(fc);
796 
797 	length -= HEADER_LENGTH;
798 	caplen -= HEADER_LENGTH;
799 	p += HEADER_LENGTH;
800 
801 	switch (FC_TYPE(fc)) {
802 	case T_MGMT:
803 		if (!mgmt_body_print(fc, (const struct mgmt_header_t *)packetp,
804 		    p, length)) {
805 			printf("[|802.11]");
806 			goto out;
807 		}
808 		break;
809 
810 	case T_CTRL:
811 		if (!ctrl_body_print(fc, p - HEADER_LENGTH,
812 		    length + HEADER_LENGTH)) {
813 			printf("[|802.11]");
814 			goto out;
815 		}
816 		break;
817 
818 	case T_DATA:
819 		/* There may be a problem w/ AP not having this bit set */
820  		if (FC_WEP(fc)) {
821 			if (!wep_print(p,length)) {
822 				printf("[|802.11]");
823 				goto out;
824 			}
825 		} else {
826 			if (llc_print(p, length, caplen, packetp + 10,
827 			    packetp + 4, &extracted_ethertype) == 0) {
828 				/*
829 				 * Some kinds of LLC packet we cannot
830 				 * handle intelligently
831 				 */
832 				if (!eflag)
833 					ieee_802_11_print(fc, p - HEADER_LENGTH,
834 					    length + HEADER_LENGTH);
835 				if (extracted_ethertype) {
836 					printf("(LLC %s) ",
837 					    etherproto_string(htons(extracted_ethertype)));
838 				}
839 				if (!xflag && !qflag)
840 					default_print(p, caplen);
841 			}
842 		}
843 		break;
844 
845 	default:
846 		printf("(body) unhandled IEEE802.11 frame type (%d)",
847 		    FC_TYPE(fc));
848 		break;
849 	}
850 
851 	if (xflag)
852 		default_print(p, caplen);
853  out:
854 	putchar('\n');
855 	--infodelay;
856 	if (infoprint)
857 		info(0);
858 }
859