nfe_init() should be called with softc not ifnet
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-802_11.c
blob56462c9448c4acec5bd5c8c391b633582d034fbd
1 /*
2 * Copyright (c) 2001
3 * Fortress Technologies, Inc. All rights reserved.
4 * Charlie Lenahan (clenahan@fortresstech.com)
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.
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
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
32 #include <tcpdump-stdinc.h>
34 #include <stdio.h>
35 #include <pcap.h>
36 #include <string.h>
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "ethertype.h"
42 #include "extract.h"
44 #include "ieee802_11.h"
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)
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 "",
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
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
117 static int
118 wep_print(const u_char *p)
120 u_int32_t iv;
122 if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
123 return 0;
124 iv = EXTRACT_LE_32BITS(p);
126 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
127 IV_KEYID(iv));
129 return 1;
132 static int
133 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
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;
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;
219 return 1;
222 /*********************************************************************************
223 * Print Handle functions for the management frame types
224 *********************************************************************************/
226 static int
227 handle_beacon(const u_char *p)
229 struct mgmt_body_t pbody;
230 int offset = 0;
232 memset(&pbody, 0, sizeof(pbody));
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;
244 if (!parse_elements(&pbody, p, offset))
245 return 0;
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" : "" );
256 return 1;
259 static int
260 handle_assoc_request(const u_char *p)
262 struct mgmt_body_t pbody;
263 int offset = 0;
265 memset(&pbody, 0, sizeof(pbody));
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;
274 if (!parse_elements(&pbody, p, offset))
275 return 0;
277 printf(" (");
278 fn_print(pbody.ssid.ssid, NULL);
279 printf(")");
280 PRINT_RATES(pbody);
281 return 1;
284 static int
285 handle_assoc_response(const u_char *p)
287 struct mgmt_body_t pbody;
288 int offset = 0;
290 memset(&pbody, 0, sizeof(pbody));
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;
302 if (!parse_elements(&pbody, p, offset))
303 return 0;
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"));
309 return 1;
312 static int
313 handle_reassoc_request(const u_char *p)
315 struct mgmt_body_t pbody;
316 int offset = 0;
318 memset(&pbody, 0, sizeof(pbody));
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;
330 if (!parse_elements(&pbody, p, offset))
331 return 0;
333 printf(" (");
334 fn_print(pbody.ssid.ssid, NULL);
335 printf(") AP : %s", etheraddr_string( pbody.ap ));
337 return 1;
340 static int
341 handle_reassoc_response(const u_char *p)
343 /* Same as a Association Reponse */
344 return handle_assoc_response(p);
347 static int
348 handle_probe_request(const u_char *p)
350 struct mgmt_body_t pbody;
351 int offset = 0;
353 memset(&pbody, 0, sizeof(pbody));
355 if (!parse_elements(&pbody, p, offset))
356 return 0;
358 printf(" (");
359 fn_print(pbody.ssid.ssid, NULL);
360 printf(")");
361 PRINT_RATES(pbody);
363 return 1;
366 static int
367 handle_probe_response(const u_char *p)
369 struct mgmt_body_t pbody;
370 int offset = 0;
372 memset(&pbody, 0, sizeof(pbody));
374 if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
375 IEEE802_11_CAPINFO_LEN))
376 return 0;
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;
385 if (!parse_elements(&pbody, p, offset))
386 return 0;
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" : "" );
395 return 1;
398 static int
399 handle_atim(void)
401 /* the frame body for ATIM is null. */
402 return 1;
405 static int
406 handle_disassoc(const u_char *p)
408 struct mgmt_body_t pbody;
410 memset(&pbody, 0, sizeof(pbody));
412 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
413 return 0;
414 pbody.reason_code = EXTRACT_LE_16BITS(p);
416 printf(": %s",
417 (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
418 : "Reserved" );
420 return 1;
423 static int
424 handle_auth(const u_char *p)
426 struct mgmt_body_t pbody;
427 int offset = 0;
429 memset(&pbody, 0, sizeof(pbody));
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;
440 if (!parse_elements(&pbody, p, offset))
441 return 0;
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;
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 : "");
464 return 1;
467 static int
468 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
470 struct mgmt_body_t pbody;
471 int offset = 0;
472 const char *reason = NULL;
474 memset(&pbody, 0, sizeof(pbody));
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;
481 reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
482 : "Reserved";
484 if (eflag) {
485 printf(": %s", reason);
486 } else {
487 printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
489 return 1;
493 /*********************************************************************************
494 * Print Body funcs
495 *********************************************************************************/
498 static int
499 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
500 const u_char *p)
502 printf("%s", subtype_text[FC_SUBTYPE(fc)]);
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);
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;
542 /*********************************************************************************
543 * Handles printing all the control frame types
544 *********************************************************************************/
546 static int
547 ctrl_body_print(u_int16_t fc, const u_char *p)
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");
600 return 1;
604 * Print Header funcs
608 * Data Frame - Address field contents
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
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)
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;
639 #define ADDR1 (p + 4)
640 #define ADDR2 (p + 10)
641 #define ADDR3 (p + 16)
642 #define ADDR4 (p + 24)
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));
686 #undef ADDR1
687 #undef ADDR2
688 #undef ADDR3
689 #undef ADDR4
692 static void
693 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
694 const u_int8_t **dstp)
696 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
698 if (srcp != NULL)
699 *srcp = hp->sa;
700 if (dstp != NULL)
701 *dstp = hp->da;
702 if (!eflag)
703 return;
705 printf("BSSID:%s DA:%s SA:%s ",
706 etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
707 etheraddr_string((hp)->sa));
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)
714 if (srcp != NULL)
715 *srcp = NULL;
716 if (dstp != NULL)
717 *dstp = NULL;
718 if (!eflag)
719 return;
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;
756 static int
757 extract_header_length(u_int16_t fc)
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;
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;
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.
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)
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));
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;
834 static u_int
835 ieee802_11_print(const u_char *p, u_int length, u_int caplen)
837 u_int16_t fc;
838 u_int hdrlen;
839 const u_int8_t *src, *dst;
840 u_short extracted_ethertype;
842 if (caplen < IEEE802_11_FC_LEN) {
843 printf("[|802.11]");
844 return caplen;
847 fc = EXTRACT_LE_16BITS(p);
848 hdrlen = extract_header_length(fc);
850 if (caplen < hdrlen) {
851 printf("[|802.11]");
852 return hdrlen;
855 ieee_802_11_hdr_print(fc, p, &src, &dst);
858 * Go past the 802.11 header.
860 length -= hdrlen;
861 caplen -= hdrlen;
862 p += hdrlen;
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;
871 break;
872 case T_CTRL:
873 if (!ctrl_body_print(fc, p - hdrlen)) {
874 printf("[|802.11]");
875 return hdrlen;
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;
885 } else if (llc_print(p, length, caplen, dst, src,
886 &extracted_ethertype) == 0) {
888 * Some kinds of LLC packet we cannot
889 * handle intelligently
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);
901 break;
902 default:
903 printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
904 break;
907 return hdrlen;
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.
916 u_int
917 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
919 return ieee802_11_print(p, h->len, h->caplen);
922 static u_int
923 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
925 u_int32_t caphdr_len;
927 caphdr_len = EXTRACT_32BITS(p + 4);
928 if (caphdr_len < 8) {
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!
934 printf("[|802.11]");
935 return caplen;
938 if (caplen < caphdr_len) {
939 printf("[|802.11]");
940 return caplen;
943 return caphdr_len + ieee802_11_print(p + caphdr_len,
944 length - caphdr_len, caplen - caphdr_len);
947 #define PRISM_HDR_LEN 144
949 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
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.
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).
963 u_int
964 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
966 u_int caplen = h->caplen;
967 u_int length = h->len;
969 if (caplen < 4) {
970 printf("[|802.11]");
971 return caplen;
974 if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
975 return ieee802_11_radio_print(p, length, caplen);
977 if (caplen < PRISM_HDR_LEN) {
978 printf("[|802.11]");
979 return caplen;
982 return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
983 length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN);
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.
991 u_int
992 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
994 u_int caplen = h->caplen;
995 u_int length = h->len;
997 if (caplen < 8) {
998 printf("[|802.11]");
999 return caplen;
1002 return ieee802_11_radio_print(p, length, caplen);