Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / tcpdump / print-802_11.c
blob4c9569b487676b17026c508a6215e6ecd56633ed
1 /* $NetBSD$ */
3 /*
4 * Copyright (c) 2001
5 * Fortress Technologies, Inc. All rights reserved.
6 * Charlie Lenahan (clenahan@fortresstech.com)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that: (1) source code distributions
10 * retain the above copyright notice and this paragraph in its entirety, (2)
11 * distributions including binary code include the above copyright notice and
12 * this paragraph in its entirety in the documentation or other materials
13 * provided with the distribution, and (3) all advertising materials mentioning
14 * features or use of this software display the following acknowledgement:
15 * ``This product includes software developed by the University of California,
16 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17 * the University nor the names of its contributors may be used to endorse
18 * or promote products derived from this software without specific prior
19 * written permission.
20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 #include <sys/cdefs.h>
26 #ifndef lint
27 #if 0
28 static const char rcsid[] _U_ =
29 "@(#) Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.15 2007/07/22 23:14:14 guy Exp (LBL)";
30 #else
31 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
32 #endif
33 #endif
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
39 #include <tcpdump-stdinc.h>
41 #include <stdio.h>
42 #include <pcap.h>
43 #include <string.h>
45 #include "interface.h"
46 #include "addrtoname.h"
47 #include "ethertype.h"
49 #include "extract.h"
51 #include "cpack.h"
53 #include "ieee802_11.h"
54 #include "ieee802_11_radio.h"
56 #define PRINT_SSID(p) \
57 switch (p.ssid_status) { \
58 case TRUNCATED: \
59 return 0; \
60 case PRESENT: \
61 printf(" ("); \
62 fn_print(p.ssid.ssid, NULL); \
63 printf(")"); \
64 break; \
65 case NOT_PRESENT: \
66 break; \
69 #define PRINT_RATE(_sep, _r, _suf) \
70 printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
71 #define PRINT_RATES(p) \
72 switch (p.rates_status) { \
73 case TRUNCATED: \
74 return 0; \
75 case PRESENT: \
76 do { \
77 int z; \
78 const char *sep = " ["; \
79 for (z = 0; z < p.rates.length ; z++) { \
80 PRINT_RATE(sep, p.rates.rate[z], \
81 (p.rates.rate[z] & 0x80 ? "*" : "")); \
82 sep = " "; \
83 } \
84 if (p.rates.length != 0) \
85 printf(" Mbit]"); \
86 } while (0); \
87 break; \
88 case NOT_PRESENT: \
89 break; \
92 #define PRINT_DS_CHANNEL(p) \
93 switch (p.ds_status) { \
94 case TRUNCATED: \
95 return 0; \
96 case PRESENT: \
97 printf(" CH: %u", p.ds.channel); \
98 break; \
99 case NOT_PRESENT: \
100 break; \
102 printf("%s", \
103 CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "" );
105 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
106 #define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0])
108 static const char *status_text[] = {
109 "Succesful", /* 0 */
110 "Unspecified failure", /* 1 */
111 "Reserved", /* 2 */
112 "Reserved", /* 3 */
113 "Reserved", /* 4 */
114 "Reserved", /* 5 */
115 "Reserved", /* 6 */
116 "Reserved", /* 7 */
117 "Reserved", /* 8 */
118 "Reserved", /* 9 */
119 "Cannot Support all requested capabilities in the Capability Information field", /* 10 */
120 "Reassociation denied due to inability to confirm that association exists", /* 11 */
121 "Association denied due to reason outside the scope of the standard", /* 12 */
122 "Responding station does not support the specified authentication algorithm ", /* 13 */
123 "Received an Authentication frame with authentication transaction " \
124 "sequence number out of expected sequence", /* 14 */
125 "Authentication rejected because of challenge failure", /* 15 */
126 "Authentication rejected due to timeout waiting for next frame in sequence", /* 16 */
127 "Association denied because AP is unable to handle additional associated stations", /* 17 */
128 "Association denied due to requesting station not supporting all of the " \
129 "data rates in BSSBasicRateSet parameter", /* 18 */
131 #define NUM_STATUSES (sizeof status_text / sizeof status_text[0])
133 static const char *reason_text[] = {
134 "Reserved", /* 0 */
135 "Unspecified reason", /* 1 */
136 "Previous authentication no longer valid", /* 2 */
137 "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
138 "Disassociated due to inactivity", /* 4 */
139 "Disassociated because AP is unable to handle all currently associated stations", /* 5 */
140 "Class 2 frame received from nonauthenticated station", /* 6 */
141 "Class 3 frame received from nonassociated station", /* 7 */
142 "Disassociated because sending station is leaving (or has left) BSS", /* 8 */
143 "Station requesting (re)association is not authenticated with responding station", /* 9 */
145 #define NUM_REASONS (sizeof reason_text / sizeof reason_text[0])
147 static int
148 wep_print(const u_char *p)
150 u_int32_t iv;
152 if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
153 return 0;
154 iv = EXTRACT_LE_32BITS(p);
156 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
157 IV_KEYID(iv));
159 return 1;
162 static void
163 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
166 * We haven't seen any elements yet.
168 pbody->challenge_status = NOT_PRESENT;
169 pbody->ssid_status = NOT_PRESENT;
170 pbody->rates_status = NOT_PRESENT;
171 pbody->ds_status = NOT_PRESENT;
172 pbody->cf_status = NOT_PRESENT;
173 pbody->tim_status = NOT_PRESENT;
175 for (;;) {
176 if (!TTEST2(*(p + offset), 1))
177 return;
178 switch (*(p + offset)) {
179 case E_SSID:
180 /* Present, possibly truncated */
181 pbody->ssid_status = TRUNCATED;
182 if (!TTEST2(*(p + offset), 2))
183 return;
184 memcpy(&pbody->ssid, p + offset, 2);
185 offset += 2;
186 if (pbody->ssid.length != 0) {
187 if (pbody->ssid.length >
188 sizeof(pbody->ssid.ssid) - 1)
189 return;
190 if (!TTEST2(*(p + offset), pbody->ssid.length))
191 return;
192 memcpy(&pbody->ssid.ssid, p + offset,
193 pbody->ssid.length);
194 offset += pbody->ssid.length;
196 pbody->ssid.ssid[pbody->ssid.length] = '\0';
197 /* Present and not truncated */
198 pbody->ssid_status = PRESENT;
199 break;
200 case E_CHALLENGE:
201 /* Present, possibly truncated */
202 pbody->challenge_status = TRUNCATED;
203 if (!TTEST2(*(p + offset), 2))
204 return;
205 memcpy(&pbody->challenge, p + offset, 2);
206 offset += 2;
207 if (pbody->challenge.length != 0) {
208 if (pbody->challenge.length >
209 sizeof(pbody->challenge.text) - 1)
210 return;
211 if (!TTEST2(*(p + offset), pbody->challenge.length))
212 return;
213 memcpy(&pbody->challenge.text, p + offset,
214 pbody->challenge.length);
215 offset += pbody->challenge.length;
217 pbody->challenge.text[pbody->challenge.length] = '\0';
218 /* Present and not truncated */
219 pbody->challenge_status = PRESENT;
220 break;
221 case E_RATES:
222 /* Present, possibly truncated */
223 pbody->rates_status = TRUNCATED;
224 if (!TTEST2(*(p + offset), 2))
225 return;
226 memcpy(&(pbody->rates), p + offset, 2);
227 offset += 2;
228 if (pbody->rates.length != 0) {
229 if (pbody->rates.length > sizeof pbody->rates.rate)
230 return;
231 if (!TTEST2(*(p + offset), pbody->rates.length))
232 return;
233 memcpy(&pbody->rates.rate, p + offset,
234 pbody->rates.length);
235 offset += pbody->rates.length;
237 /* Present and not truncated */
238 pbody->rates_status = PRESENT;
239 break;
240 case E_DS:
241 /* Present, possibly truncated */
242 pbody->ds_status = TRUNCATED;
243 if (!TTEST2(*(p + offset), 3))
244 return;
245 memcpy(&pbody->ds, p + offset, 3);
246 offset += 3;
247 /* Present and not truncated */
248 pbody->ds_status = PRESENT;
249 break;
250 case E_CF:
251 /* Present, possibly truncated */
252 pbody->cf_status = TRUNCATED;
253 if (!TTEST2(*(p + offset), 8))
254 return;
255 memcpy(&pbody->cf, p + offset, 8);
256 offset += 8;
257 /* Present and not truncated */
258 pbody->cf_status = PRESENT;
259 break;
260 case E_TIM:
261 /* Present, possibly truncated */
262 pbody->tim_status = TRUNCATED;
263 if (!TTEST2(*(p + offset), 2))
264 return;
265 memcpy(&pbody->tim, p + offset, 2);
266 offset += 2;
267 if (!TTEST2(*(p + offset), 3))
268 return;
269 memcpy(&pbody->tim.count, p + offset, 3);
270 offset += 3;
272 if (pbody->tim.length <= 3)
273 break;
274 if (pbody->tim.length - 3 > sizeof pbody->tim.bitmap)
275 return;
276 if (!TTEST2(*(p + offset), pbody->tim.length - 3))
277 return;
278 memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
279 (pbody->tim.length - 3));
280 offset += pbody->tim.length - 3;
281 /* Present and not truncated */
282 pbody->tim_status = PRESENT;
283 break;
284 default:
285 #if 0
286 printf("(1) unhandled element_id (%d) ",
287 *(p + offset) );
288 #endif
289 if (!TTEST2(*(p + offset), 2))
290 return;
291 if (!TTEST2(*(p + offset + 2), *(p + offset + 1)))
292 return;
293 offset += *(p + offset + 1) + 2;
294 break;
299 /*********************************************************************************
300 * Print Handle functions for the management frame types
301 *********************************************************************************/
303 static int
304 handle_beacon(const u_char *p)
306 struct mgmt_body_t pbody;
307 int offset = 0;
309 memset(&pbody, 0, sizeof(pbody));
311 if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
312 IEEE802_11_CAPINFO_LEN))
313 return 0;
314 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
315 offset += IEEE802_11_TSTAMP_LEN;
316 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
317 offset += IEEE802_11_BCNINT_LEN;
318 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
319 offset += IEEE802_11_CAPINFO_LEN;
321 parse_elements(&pbody, p, offset);
323 PRINT_SSID(pbody);
324 PRINT_RATES(pbody);
325 printf(" %s",
326 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
327 PRINT_DS_CHANNEL(pbody);
329 return 1;
332 static int
333 handle_assoc_request(const u_char *p)
335 struct mgmt_body_t pbody;
336 int offset = 0;
338 memset(&pbody, 0, sizeof(pbody));
340 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
341 return 0;
342 pbody.capability_info = EXTRACT_LE_16BITS(p);
343 offset += IEEE802_11_CAPINFO_LEN;
344 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
345 offset += IEEE802_11_LISTENINT_LEN;
347 parse_elements(&pbody, p, offset);
349 PRINT_SSID(pbody);
350 PRINT_RATES(pbody);
351 return 1;
354 static int
355 handle_assoc_response(const u_char *p)
357 struct mgmt_body_t pbody;
358 int offset = 0;
360 memset(&pbody, 0, sizeof(pbody));
362 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
363 IEEE802_11_AID_LEN))
364 return 0;
365 pbody.capability_info = EXTRACT_LE_16BITS(p);
366 offset += IEEE802_11_CAPINFO_LEN;
367 pbody.status_code = EXTRACT_LE_16BITS(p+offset);
368 offset += IEEE802_11_STATUS_LEN;
369 pbody.aid = EXTRACT_LE_16BITS(p+offset);
370 offset += IEEE802_11_AID_LEN;
372 parse_elements(&pbody, p, offset);
374 printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
375 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
376 (pbody.status_code < NUM_STATUSES
377 ? status_text[pbody.status_code]
378 : "n/a"));
380 return 1;
383 static int
384 handle_reassoc_request(const u_char *p)
386 struct mgmt_body_t pbody;
387 int offset = 0;
389 memset(&pbody, 0, sizeof(pbody));
391 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
392 IEEE802_11_AP_LEN))
393 return 0;
394 pbody.capability_info = EXTRACT_LE_16BITS(p);
395 offset += IEEE802_11_CAPINFO_LEN;
396 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
397 offset += IEEE802_11_LISTENINT_LEN;
398 memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
399 offset += IEEE802_11_AP_LEN;
401 parse_elements(&pbody, p, offset);
403 PRINT_SSID(pbody);
404 printf(" AP : %s", etheraddr_string( pbody.ap ));
406 return 1;
409 static int
410 handle_reassoc_response(const u_char *p)
412 /* Same as a Association Reponse */
413 return handle_assoc_response(p);
416 static int
417 handle_probe_request(const u_char *p)
419 struct mgmt_body_t pbody;
420 int offset = 0;
422 memset(&pbody, 0, sizeof(pbody));
424 parse_elements(&pbody, p, offset);
426 PRINT_SSID(pbody);
427 PRINT_RATES(pbody);
429 return 1;
432 static int
433 handle_probe_response(const u_char *p)
435 struct mgmt_body_t pbody;
436 int offset = 0;
438 memset(&pbody, 0, sizeof(pbody));
440 if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
441 IEEE802_11_CAPINFO_LEN))
442 return 0;
444 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
445 offset += IEEE802_11_TSTAMP_LEN;
446 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
447 offset += IEEE802_11_BCNINT_LEN;
448 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
449 offset += IEEE802_11_CAPINFO_LEN;
451 parse_elements(&pbody, p, offset);
453 PRINT_SSID(pbody);
454 PRINT_RATES(pbody);
455 PRINT_DS_CHANNEL(pbody);
457 return 1;
460 static int
461 handle_atim(void)
463 /* the frame body for ATIM is null. */
464 return 1;
467 static int
468 handle_disassoc(const u_char *p)
470 struct mgmt_body_t pbody;
472 memset(&pbody, 0, sizeof(pbody));
474 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
475 return 0;
476 pbody.reason_code = EXTRACT_LE_16BITS(p);
478 printf(": %s",
479 (pbody.reason_code < NUM_REASONS)
480 ? reason_text[pbody.reason_code]
481 : "Reserved" );
483 return 1;
486 static int
487 handle_auth(const u_char *p)
489 struct mgmt_body_t pbody;
490 int offset = 0;
492 memset(&pbody, 0, sizeof(pbody));
494 if (!TTEST2(*p, 6))
495 return 0;
496 pbody.auth_alg = EXTRACT_LE_16BITS(p);
497 offset += 2;
498 pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
499 offset += 2;
500 pbody.status_code = EXTRACT_LE_16BITS(p + offset);
501 offset += 2;
503 parse_elements(&pbody, p, offset);
505 if ((pbody.auth_alg == 1) &&
506 ((pbody.auth_trans_seq_num == 2) ||
507 (pbody.auth_trans_seq_num == 3))) {
508 printf(" (%s)-%x [Challenge Text] %s",
509 (pbody.auth_alg < NUM_AUTH_ALGS)
510 ? auth_alg_text[pbody.auth_alg]
511 : "Reserved",
512 pbody.auth_trans_seq_num,
513 ((pbody.auth_trans_seq_num % 2)
514 ? ((pbody.status_code < NUM_STATUSES)
515 ? status_text[pbody.status_code]
516 : "n/a") : ""));
517 return 1;
519 printf(" (%s)-%x: %s",
520 (pbody.auth_alg < NUM_AUTH_ALGS)
521 ? auth_alg_text[pbody.auth_alg]
522 : "Reserved",
523 pbody.auth_trans_seq_num,
524 (pbody.auth_trans_seq_num % 2)
525 ? ((pbody.status_code < NUM_STATUSES)
526 ? status_text[pbody.status_code]
527 : "n/a")
528 : "");
530 return 1;
533 static int
534 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
536 struct mgmt_body_t pbody;
537 int offset = 0;
538 const char *reason = NULL;
540 memset(&pbody, 0, sizeof(pbody));
542 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
543 return 0;
544 pbody.reason_code = EXTRACT_LE_16BITS(p);
545 offset += IEEE802_11_REASON_LEN;
547 reason = (pbody.reason_code < NUM_REASONS)
548 ? reason_text[pbody.reason_code]
549 : "Reserved";
551 if (eflag) {
552 printf(": %s", reason);
553 } else {
554 printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
556 return 1;
560 /*********************************************************************************
561 * Print Body funcs
562 *********************************************************************************/
565 static int
566 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
567 const u_char *p)
569 switch (FC_SUBTYPE(fc)) {
570 case ST_ASSOC_REQUEST:
571 printf("Assoc Request");
572 return handle_assoc_request(p);
573 case ST_ASSOC_RESPONSE:
574 printf("Assoc Response");
575 return handle_assoc_response(p);
576 case ST_REASSOC_REQUEST:
577 printf("ReAssoc Request");
578 return handle_reassoc_request(p);
579 case ST_REASSOC_RESPONSE:
580 printf("ReAssoc Response");
581 return handle_reassoc_response(p);
582 case ST_PROBE_REQUEST:
583 printf("Probe Request");
584 return handle_probe_request(p);
585 case ST_PROBE_RESPONSE:
586 printf("Probe Response");
587 return handle_probe_response(p);
588 case ST_BEACON:
589 printf("Beacon");
590 return handle_beacon(p);
591 case ST_ATIM:
592 printf("ATIM");
593 return handle_atim();
594 case ST_DISASSOC:
595 printf("Disassociation");
596 return handle_disassoc(p);
597 case ST_AUTH:
598 printf("Authentication");
599 if (!TTEST2(*p, 3))
600 return 0;
601 if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
602 printf("Authentication (Shared-Key)-3 ");
603 return wep_print(p);
605 return handle_auth(p);
606 case ST_DEAUTH:
607 printf("DeAuthentication");
608 return handle_deauth(pmh, p);
609 break;
610 default:
611 printf("Unhandled Management subtype(%x)",
612 FC_SUBTYPE(fc));
613 return 1;
618 /*********************************************************************************
619 * Handles printing all the control frame types
620 *********************************************************************************/
622 static int
623 ctrl_body_print(u_int16_t fc, const u_char *p)
625 switch (FC_SUBTYPE(fc)) {
626 case CTRL_PS_POLL:
627 printf("Power Save-Poll");
628 if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
629 return 0;
630 printf(" AID(%x)",
631 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
632 break;
633 case CTRL_RTS:
634 printf("Request-To-Send");
635 if (!TTEST2(*p, CTRL_RTS_HDRLEN))
636 return 0;
637 if (!eflag)
638 printf(" TA:%s ",
639 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
640 break;
641 case CTRL_CTS:
642 printf("Clear-To-Send");
643 if (!TTEST2(*p, CTRL_CTS_HDRLEN))
644 return 0;
645 if (!eflag)
646 printf(" RA:%s ",
647 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
648 break;
649 case CTRL_ACK:
650 printf("Acknowledgment");
651 if (!TTEST2(*p, CTRL_ACK_HDRLEN))
652 return 0;
653 if (!eflag)
654 printf(" RA:%s ",
655 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
656 break;
657 case CTRL_CF_END:
658 printf("CF-End");
659 if (!TTEST2(*p, CTRL_END_HDRLEN))
660 return 0;
661 if (!eflag)
662 printf(" RA:%s ",
663 etheraddr_string(((const struct ctrl_end_t *)p)->ra));
664 break;
665 case CTRL_END_ACK:
666 printf("CF-End+CF-Ack");
667 if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
668 return 0;
669 if (!eflag)
670 printf(" RA:%s ",
671 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
672 break;
673 default:
674 printf("Unknown Ctrl Subtype");
676 return 1;
680 * Print Header funcs
684 * Data Frame - Address field contents
686 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
687 * 0 | 0 | DA | SA | BSSID | n/a
688 * 0 | 1 | DA | BSSID | SA | n/a
689 * 1 | 0 | BSSID | SA | DA | n/a
690 * 1 | 1 | RA | TA | DA | SA
693 static void
694 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
695 const u_int8_t **dstp)
697 u_int subtype = FC_SUBTYPE(fc);
699 if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
700 DATA_FRAME_IS_QOS(subtype)) {
701 printf("CF ");
702 if (DATA_FRAME_IS_CF_ACK(subtype)) {
703 if (DATA_FRAME_IS_CF_POLL(subtype))
704 printf("Ack/Poll");
705 else
706 printf("Ack");
707 } else {
708 if (DATA_FRAME_IS_CF_POLL(subtype))
709 printf("Poll");
711 if (DATA_FRAME_IS_QOS(subtype))
712 printf("+QoS");
713 printf(" ");
716 #define ADDR1 (p + 4)
717 #define ADDR2 (p + 10)
718 #define ADDR3 (p + 16)
719 #define ADDR4 (p + 24)
721 if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
722 if (srcp != NULL)
723 *srcp = ADDR2;
724 if (dstp != NULL)
725 *dstp = ADDR1;
726 if (!eflag)
727 return;
728 printf("DA:%s SA:%s BSSID:%s ",
729 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
730 etheraddr_string(ADDR3));
731 } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
732 if (srcp != NULL)
733 *srcp = ADDR3;
734 if (dstp != NULL)
735 *dstp = ADDR1;
736 if (!eflag)
737 return;
738 printf("DA:%s BSSID:%s SA:%s ",
739 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
740 etheraddr_string(ADDR3));
741 } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
742 if (srcp != NULL)
743 *srcp = ADDR2;
744 if (dstp != NULL)
745 *dstp = ADDR3;
746 if (!eflag)
747 return;
748 printf("BSSID:%s SA:%s DA:%s ",
749 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
750 etheraddr_string(ADDR3));
751 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
752 if (srcp != NULL)
753 *srcp = ADDR4;
754 if (dstp != NULL)
755 *dstp = ADDR3;
756 if (!eflag)
757 return;
758 printf("RA:%s TA:%s DA:%s SA:%s ",
759 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
760 etheraddr_string(ADDR3), etheraddr_string(ADDR4));
763 #undef ADDR1
764 #undef ADDR2
765 #undef ADDR3
766 #undef ADDR4
769 static void
770 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
771 const u_int8_t **dstp)
773 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
775 if (srcp != NULL)
776 *srcp = hp->sa;
777 if (dstp != NULL)
778 *dstp = hp->da;
779 if (!eflag)
780 return;
782 printf("BSSID:%s DA:%s SA:%s ",
783 etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
784 etheraddr_string((hp)->sa));
787 static void
788 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
789 const u_int8_t **dstp)
791 if (srcp != NULL)
792 *srcp = NULL;
793 if (dstp != NULL)
794 *dstp = NULL;
795 if (!eflag)
796 return;
798 switch (FC_SUBTYPE(fc)) {
799 case CTRL_PS_POLL:
800 printf("BSSID:%s TA:%s ",
801 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
802 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
803 break;
804 case CTRL_RTS:
805 printf("RA:%s TA:%s ",
806 etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
807 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
808 break;
809 case CTRL_CTS:
810 printf("RA:%s ",
811 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
812 break;
813 case CTRL_ACK:
814 printf("RA:%s ",
815 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
816 break;
817 case CTRL_CF_END:
818 printf("RA:%s BSSID:%s ",
819 etheraddr_string(((const struct ctrl_end_t *)p)->ra),
820 etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
821 break;
822 case CTRL_END_ACK:
823 printf("RA:%s BSSID:%s ",
824 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
825 etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
826 break;
827 default:
828 printf("(H) Unknown Ctrl Subtype");
829 break;
833 static int
834 extract_header_length(u_int16_t fc)
836 int len;
838 switch (FC_TYPE(fc)) {
839 case T_MGMT:
840 return MGMT_HDRLEN;
841 case T_CTRL:
842 switch (FC_SUBTYPE(fc)) {
843 case CTRL_PS_POLL:
844 return CTRL_PS_POLL_HDRLEN;
845 case CTRL_RTS:
846 return CTRL_RTS_HDRLEN;
847 case CTRL_CTS:
848 return CTRL_CTS_HDRLEN;
849 case CTRL_ACK:
850 return CTRL_ACK_HDRLEN;
851 case CTRL_CF_END:
852 return CTRL_END_HDRLEN;
853 case CTRL_END_ACK:
854 return CTRL_END_ACK_HDRLEN;
855 default:
856 return 0;
858 case T_DATA:
859 len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
860 if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
861 len += 2;
862 return len;
863 default:
864 printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
865 return 0;
870 * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
871 * to point to the source and destination MAC addresses in any case if
872 * "srcp" and "dstp" aren't null.
874 static inline void
875 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
876 const u_int8_t **dstp)
878 if (vflag) {
879 if (FC_MORE_DATA(fc))
880 printf("More Data ");
881 if (FC_MORE_FLAG(fc))
882 printf("More Fragments ");
883 if (FC_POWER_MGMT(fc))
884 printf("Pwr Mgmt ");
885 if (FC_RETRY(fc))
886 printf("Retry ");
887 if (FC_ORDER(fc))
888 printf("Strictly Ordered ");
889 if (FC_WEP(fc))
890 printf("WEP Encrypted ");
891 if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
892 printf("%dus ",
893 EXTRACT_LE_16BITS(
894 &((const struct mgmt_header_t *)p)->duration));
897 switch (FC_TYPE(fc)) {
898 case T_MGMT:
899 mgmt_header_print(p, srcp, dstp);
900 break;
901 case T_CTRL:
902 ctrl_header_print(fc, p, srcp, dstp);
903 break;
904 case T_DATA:
905 data_header_print(fc, p, srcp, dstp);
906 break;
907 default:
908 printf("(header) unknown IEEE802.11 frame type (%d)",
909 FC_TYPE(fc));
910 *srcp = NULL;
911 *dstp = NULL;
912 break;
916 #ifndef roundup2
917 #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
918 #endif
920 static u_int
921 ieee802_11_print(const u_char *p, u_int length, u_int caplen, int pad)
923 u_int16_t fc;
924 u_int hdrlen;
925 const u_int8_t *src, *dst;
926 u_short extracted_ethertype;
928 if (caplen < IEEE802_11_FC_LEN) {
929 printf("[|802.11]");
930 return caplen;
933 fc = EXTRACT_LE_16BITS(p);
934 hdrlen = extract_header_length(fc);
935 if (pad)
936 hdrlen = roundup2(hdrlen, 4);
938 if (caplen < hdrlen) {
939 printf("[|802.11]");
940 return hdrlen;
943 ieee_802_11_hdr_print(fc, p, &src, &dst);
946 * Go past the 802.11 header.
948 length -= hdrlen;
949 caplen -= hdrlen;
950 p += hdrlen;
952 switch (FC_TYPE(fc)) {
953 case T_MGMT:
954 if (!mgmt_body_print(fc,
955 (const struct mgmt_header_t *)(p - hdrlen), p)) {
956 printf("[|802.11]");
957 return hdrlen;
959 break;
960 case T_CTRL:
961 if (!ctrl_body_print(fc, p - hdrlen)) {
962 printf("[|802.11]");
963 return hdrlen;
965 break;
966 case T_DATA:
967 if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
968 return hdrlen; /* no-data frame */
969 /* There may be a problem w/ AP not having this bit set */
970 if (FC_WEP(fc)) {
971 if (!wep_print(p)) {
972 printf("[|802.11]");
973 return hdrlen;
975 } else if (llc_print(p, length, caplen, dst, src,
976 &extracted_ethertype) == 0) {
978 * Some kinds of LLC packet we cannot
979 * handle intelligently
981 if (!eflag)
982 ieee_802_11_hdr_print(fc, p - hdrlen, NULL,
983 NULL);
984 if (extracted_ethertype)
985 printf("(LLC %s) ",
986 etherproto_string(
987 htons(extracted_ethertype)));
988 if (!suppress_default_print)
989 default_print(p, caplen);
991 break;
992 default:
993 printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
994 break;
997 return hdrlen;
1001 * This is the top level routine of the printer. 'p' points
1002 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
1003 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
1004 * is the number of bytes actually captured.
1006 u_int
1007 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
1009 return ieee802_11_print(p, h->len, h->caplen, 0);
1012 static int
1013 print_radiotap_field(struct cpack_state *s, u_int32_t bit, int *pad)
1015 union {
1016 int8_t i8;
1017 u_int8_t u8;
1018 int16_t i16;
1019 u_int16_t u16;
1020 u_int32_t u32;
1021 u_int64_t u64;
1022 } u, u2;
1023 int rc;
1025 switch (bit) {
1026 case IEEE80211_RADIOTAP_FLAGS:
1027 rc = cpack_uint8(s, &u.u8);
1028 if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD)
1029 *pad = 1;
1030 break;
1031 case IEEE80211_RADIOTAP_RATE:
1032 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1033 case IEEE80211_RADIOTAP_DB_ANTNOISE:
1034 case IEEE80211_RADIOTAP_ANTENNA:
1035 rc = cpack_uint8(s, &u.u8);
1036 break;
1037 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1038 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1039 rc = cpack_int8(s, &u.i8);
1040 break;
1041 case IEEE80211_RADIOTAP_CHANNEL:
1042 rc = cpack_uint16(s, &u.u16);
1043 if (rc != 0)
1044 break;
1045 rc = cpack_uint16(s, &u2.u16);
1046 break;
1047 case IEEE80211_RADIOTAP_FHSS:
1048 case IEEE80211_RADIOTAP_LOCK_QUALITY:
1049 case IEEE80211_RADIOTAP_TX_ATTENUATION:
1050 rc = cpack_uint16(s, &u.u16);
1051 break;
1052 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1053 rc = cpack_uint8(s, &u.u8);
1054 break;
1055 case IEEE80211_RADIOTAP_DBM_TX_POWER:
1056 rc = cpack_int8(s, &u.i8);
1057 break;
1058 case IEEE80211_RADIOTAP_TSFT:
1059 rc = cpack_uint64(s, &u.u64);
1060 break;
1061 default:
1062 /* this bit indicates a field whose
1063 * size we do not know, so we cannot
1064 * proceed.
1066 printf("[0x%08x] ", bit);
1067 return -1;
1070 if (rc != 0) {
1071 printf("[|802.11]");
1072 return rc;
1075 switch (bit) {
1076 case IEEE80211_RADIOTAP_CHANNEL:
1077 printf("%u MHz ", u.u16);
1078 if (u2.u16 != 0)
1079 printf("(0x%04x) ", u2.u16);
1080 break;
1081 case IEEE80211_RADIOTAP_FHSS:
1082 printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
1083 break;
1084 case IEEE80211_RADIOTAP_RATE:
1085 PRINT_RATE("", u.u8, " Mb/s ");
1086 break;
1087 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1088 printf("%ddB signal ", u.i8);
1089 break;
1090 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1091 printf("%ddB noise ", u.i8);
1092 break;
1093 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1094 printf("%ddB signal ", u.u8);
1095 break;
1096 case IEEE80211_RADIOTAP_DB_ANTNOISE:
1097 printf("%ddB noise ", u.u8);
1098 break;
1099 case IEEE80211_RADIOTAP_LOCK_QUALITY:
1100 printf("%u sq ", u.u16);
1101 break;
1102 case IEEE80211_RADIOTAP_TX_ATTENUATION:
1103 printf("%d tx power ", -(int)u.u16);
1104 break;
1105 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1106 printf("%ddB tx power ", -(int)u.u8);
1107 break;
1108 case IEEE80211_RADIOTAP_DBM_TX_POWER:
1109 printf("%ddBm tx power ", u.i8);
1110 break;
1111 case IEEE80211_RADIOTAP_FLAGS:
1112 if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
1113 printf("cfp ");
1114 if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
1115 printf("short preamble ");
1116 if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
1117 printf("wep ");
1118 if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
1119 printf("fragmented ");
1120 if (u.u8 & IEEE80211_RADIOTAP_F_BADFCS)
1121 printf("bad-fcs ");
1122 break;
1123 case IEEE80211_RADIOTAP_ANTENNA:
1124 printf("antenna %d ", u.u8);
1125 break;
1126 case IEEE80211_RADIOTAP_TSFT:
1127 printf("%" PRIu64 "us tsft ", u.u64);
1128 break;
1130 return 0;
1133 static u_int
1134 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
1136 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
1137 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
1138 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
1139 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
1140 #define BITNO_2(x) (((x) & 2) ? 1 : 0)
1141 #define BIT(n) (1 << n)
1142 #define IS_EXTENDED(__p) \
1143 (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
1145 struct cpack_state cpacker;
1146 struct ieee80211_radiotap_header *hdr;
1147 u_int32_t present, next_present;
1148 u_int32_t *presentp, *last_presentp;
1149 enum ieee80211_radiotap_type bit;
1150 int bit0;
1151 const u_char *iter;
1152 u_int len;
1153 int pad;
1155 if (caplen < sizeof(*hdr)) {
1156 printf("[|802.11]");
1157 return caplen;
1160 hdr = (struct ieee80211_radiotap_header *)p;
1162 len = EXTRACT_LE_16BITS(&hdr->it_len);
1164 if (caplen < len) {
1165 printf("[|802.11]");
1166 return caplen;
1168 for (last_presentp = &hdr->it_present;
1169 IS_EXTENDED(last_presentp) &&
1170 (u_char*)(last_presentp + 1) <= p + len;
1171 last_presentp++);
1173 /* are there more bitmap extensions than bytes in header? */
1174 if (IS_EXTENDED(last_presentp)) {
1175 printf("[|802.11]");
1176 return caplen;
1179 iter = (u_char*)(last_presentp + 1);
1181 if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
1182 /* XXX */
1183 printf("[|802.11]");
1184 return caplen;
1187 /* Assume no Atheros padding between 802.11 header and body */
1188 pad = 0;
1189 for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
1190 presentp++, bit0 += 32) {
1191 for (present = EXTRACT_LE_32BITS(presentp); present;
1192 present = next_present) {
1193 /* clear the least significant bit that is set */
1194 next_present = present & (present - 1);
1196 /* extract the least significant bit that is set */
1197 bit = (enum ieee80211_radiotap_type)
1198 (bit0 + BITNO_32(present ^ next_present));
1200 if (print_radiotap_field(&cpacker, bit, &pad) != 0)
1201 goto out;
1204 out:
1205 return len + ieee802_11_print(p + len, length - len, caplen - len, pad);
1206 #undef BITNO_32
1207 #undef BITNO_16
1208 #undef BITNO_8
1209 #undef BITNO_4
1210 #undef BITNO_2
1211 #undef BIT
1214 static u_int
1215 ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
1217 u_int32_t caphdr_len;
1219 caphdr_len = EXTRACT_32BITS(p + 4);
1220 if (caphdr_len < 8) {
1222 * Yow! The capture header length is claimed not
1223 * to be large enough to include even the version
1224 * cookie or capture header length!
1226 printf("[|802.11]");
1227 return caplen;
1230 if (caplen < caphdr_len) {
1231 printf("[|802.11]");
1232 return caplen;
1235 return caphdr_len + ieee802_11_print(p + caphdr_len,
1236 length - caphdr_len, caplen - caphdr_len, 0);
1239 #define PRISM_HDR_LEN 144
1241 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
1244 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
1245 * containing information such as radio information, which we
1246 * currently ignore.
1248 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
1249 * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
1250 * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
1251 * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
1252 * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
1253 * the first 4 bytes of the header are used to indicate which it is).
1255 u_int
1256 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
1258 u_int caplen = h->caplen;
1259 u_int length = h->len;
1261 if (caplen < 4) {
1262 printf("[|802.11]");
1263 return caplen;
1266 if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
1267 return ieee802_11_avs_radio_print(p, length, caplen);
1269 if (caplen < PRISM_HDR_LEN) {
1270 printf("[|802.11]");
1271 return caplen;
1274 return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
1275 length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN, 0);
1279 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
1280 * header, containing information such as radio information, which we
1281 * currently ignore.
1283 u_int
1284 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
1286 u_int caplen = h->caplen;
1287 u_int length = h->len;
1289 if (caplen < 8) {
1290 printf("[|802.11]");
1291 return caplen;
1294 return ieee802_11_radio_print(p, length, caplen);