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