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
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.
24 static const char rcsid
[] _U_
=
25 "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.37 2005-10-17 07:58:57 guy Exp $ (LBL)";
32 #include <tcpdump-stdinc.h>
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "ethertype.h"
46 #include "ieee802_11.h"
47 #include "ieee802_11_radio.h"
49 #define PRINT_RATE(_sep, _r, _suf) \
50 printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
51 #define PRINT_RATES(p) \
54 const char *sep = " ["; \
55 for (z = 0; z < p.rates.length ; z++) { \
56 PRINT_RATE(sep, p.rates.rate[z], \
57 (p.rates.rate[z] & 0x80 ? "*" : "")); \
60 if (p.rates.length != 0) \
64 static const char *auth_alg_text
[]={"Open System","Shared Key","EAP"};
65 #define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0])
67 static const char *status_text
[] = {
69 "Unspecified failure", /* 1 */
78 "Cannot Support all requested capabilities in the Capability Information field", /* 10 */
79 "Reassociation denied due to inability to confirm that association exists", /* 11 */
80 "Association denied due to reason outside the scope of the standard", /* 12 */
81 "Responding station does not support the specified authentication algorithm ", /* 13 */
82 "Received an Authentication frame with authentication transaction " \
83 "sequence number out of expected sequence", /* 14 */
84 "Authentication rejected because of challenge failure", /* 15 */
85 "Authentication rejected due to timeout waiting for next frame in sequence", /* 16 */
86 "Association denied because AP is unable to handle additional associated stations", /* 17 */
87 "Association denied due to requesting station not supporting all of the " \
88 "data rates in BSSBasicRateSet parameter", /* 18 */
90 #define NUM_STATUSES (sizeof status_text / sizeof status_text[0])
92 static const char *reason_text
[] = {
94 "Unspecified reason", /* 1 */
95 "Previous authentication no longer valid", /* 2 */
96 "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
97 "Disassociated due to inactivity", /* 4 */
98 "Disassociated because AP is unable to handle all currently associated stations", /* 5 */
99 "Class 2 frame received from nonauthenticated station", /* 6 */
100 "Class 3 frame received from nonassociated station", /* 7 */
101 "Disassociated because sending station is leaving (or has left) BSS", /* 8 */
102 "Station requesting (re)association is not authenticated with responding station", /* 9 */
104 #define NUM_REASONS (sizeof reason_text / sizeof reason_text[0])
107 wep_print(const u_char
*p
)
111 if (!TTEST2(*p
, IEEE802_11_IV_LEN
+ IEEE802_11_KID_LEN
))
113 iv
= EXTRACT_LE_32BITS(p
);
115 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv
), IV_PAD(iv
),
122 parse_elements(struct mgmt_body_t
*pbody
, const u_char
*p
, int offset
)
125 if (!TTEST2(*(p
+ offset
), 1))
127 switch (*(p
+ offset
)) {
129 if (!TTEST2(*(p
+ offset
), 2))
131 memcpy(&pbody
->ssid
, p
+ offset
, 2);
133 if (pbody
->ssid
.length
<= 0)
135 if (pbody
->ssid
.length
> 32)
137 if (!TTEST2(*(p
+ offset
), pbody
->ssid
.length
))
139 memcpy(&pbody
->ssid
.ssid
, p
+ offset
,
141 offset
+= pbody
->ssid
.length
;
142 pbody
->ssid
.ssid
[pbody
->ssid
.length
] = '\0';
145 if (!TTEST2(*(p
+ offset
), 2))
147 memcpy(&pbody
->challenge
, p
+ offset
, 2);
149 if (pbody
->challenge
.length
<= 0)
151 if (pbody
->challenge
.length
> 253)
153 if (!TTEST2(*(p
+ offset
), pbody
->challenge
.length
))
155 memcpy(&pbody
->challenge
.text
, p
+ offset
,
156 pbody
->challenge
.length
);
157 offset
+= pbody
->challenge
.length
;
158 pbody
->challenge
.text
[pbody
->challenge
.length
] = '\0';
161 if (!TTEST2(*(p
+ offset
), 2))
163 memcpy(&(pbody
->rates
), p
+ offset
, 2);
165 if (pbody
->rates
.length
<= 0)
167 if (pbody
->rates
.length
> 8)
169 if (!TTEST2(*(p
+ offset
), pbody
->rates
.length
))
171 memcpy(&pbody
->rates
.rate
, p
+ offset
,
172 pbody
->rates
.length
);
173 offset
+= pbody
->rates
.length
;
176 if (!TTEST2(*(p
+ offset
), 3))
178 memcpy(&pbody
->ds
, p
+ offset
, 3);
182 if (!TTEST2(*(p
+ offset
), 8))
184 memcpy(&pbody
->cf
, p
+ offset
, 8);
188 if (!TTEST2(*(p
+ offset
), 2))
190 memcpy(&pbody
->tim
, p
+ offset
, 2);
192 if (!TTEST2(*(p
+ offset
), 3))
194 memcpy(&pbody
->tim
.count
, p
+ offset
, 3);
197 if (pbody
->tim
.length
<= 3)
199 if (pbody
->rates
.length
> 251)
201 if (!TTEST2(*(p
+ offset
), pbody
->tim
.length
- 3))
203 memcpy(pbody
->tim
.bitmap
, p
+ (pbody
->tim
.length
- 3),
204 (pbody
->tim
.length
- 3));
205 offset
+= pbody
->tim
.length
- 3;
209 printf("(1) unhandled element_id (%d) ",
212 offset
+= *(p
+ offset
+ 1) + 2;
219 /*********************************************************************************
220 * Print Handle functions for the management frame types
221 *********************************************************************************/
224 handle_beacon(const u_char
*p
)
226 struct mgmt_body_t pbody
;
229 memset(&pbody
, 0, sizeof(pbody
));
231 if (!TTEST2(*p
, IEEE802_11_TSTAMP_LEN
+ IEEE802_11_BCNINT_LEN
+
232 IEEE802_11_CAPINFO_LEN
))
234 memcpy(&pbody
.timestamp
, p
, IEEE802_11_TSTAMP_LEN
);
235 offset
+= IEEE802_11_TSTAMP_LEN
;
236 pbody
.beacon_interval
= EXTRACT_LE_16BITS(p
+offset
);
237 offset
+= IEEE802_11_BCNINT_LEN
;
238 pbody
.capability_info
= EXTRACT_LE_16BITS(p
+offset
);
239 offset
+= IEEE802_11_CAPINFO_LEN
;
241 if (!parse_elements(&pbody
, p
, offset
))
245 fn_print(pbody
.ssid
.ssid
, NULL
);
248 printf(" %s CH: %u%s",
249 CAPABILITY_ESS(pbody
.capability_info
) ? "ESS" : "IBSS",
251 CAPABILITY_PRIVACY(pbody
.capability_info
) ? ", PRIVACY" : "" );
257 handle_assoc_request(const u_char
*p
)
259 struct mgmt_body_t pbody
;
262 memset(&pbody
, 0, sizeof(pbody
));
264 if (!TTEST2(*p
, IEEE802_11_CAPINFO_LEN
+ IEEE802_11_LISTENINT_LEN
))
266 pbody
.capability_info
= EXTRACT_LE_16BITS(p
);
267 offset
+= IEEE802_11_CAPINFO_LEN
;
268 pbody
.listen_interval
= EXTRACT_LE_16BITS(p
+offset
);
269 offset
+= IEEE802_11_LISTENINT_LEN
;
271 if (!parse_elements(&pbody
, p
, offset
))
275 fn_print(pbody
.ssid
.ssid
, NULL
);
282 handle_assoc_response(const u_char
*p
)
284 struct mgmt_body_t pbody
;
287 memset(&pbody
, 0, sizeof(pbody
));
289 if (!TTEST2(*p
, IEEE802_11_CAPINFO_LEN
+ IEEE802_11_STATUS_LEN
+
292 pbody
.capability_info
= EXTRACT_LE_16BITS(p
);
293 offset
+= IEEE802_11_CAPINFO_LEN
;
294 pbody
.status_code
= EXTRACT_LE_16BITS(p
+offset
);
295 offset
+= IEEE802_11_STATUS_LEN
;
296 pbody
.aid
= EXTRACT_LE_16BITS(p
+offset
);
297 offset
+= IEEE802_11_AID_LEN
;
299 if (!parse_elements(&pbody
, p
, offset
))
302 printf(" AID(%x) :%s: %s", ((u_int16_t
)(pbody
.aid
<< 2 )) >> 2 ,
303 CAPABILITY_PRIVACY(pbody
.capability_info
) ? " PRIVACY " : "",
304 (pbody
.status_code
< NUM_STATUSES
305 ? status_text
[pbody
.status_code
]
312 handle_reassoc_request(const u_char
*p
)
314 struct mgmt_body_t pbody
;
317 memset(&pbody
, 0, sizeof(pbody
));
319 if (!TTEST2(*p
, IEEE802_11_CAPINFO_LEN
+ IEEE802_11_LISTENINT_LEN
+
322 pbody
.capability_info
= EXTRACT_LE_16BITS(p
);
323 offset
+= IEEE802_11_CAPINFO_LEN
;
324 pbody
.listen_interval
= EXTRACT_LE_16BITS(p
+offset
);
325 offset
+= IEEE802_11_LISTENINT_LEN
;
326 memcpy(&pbody
.ap
, p
+offset
, IEEE802_11_AP_LEN
);
327 offset
+= IEEE802_11_AP_LEN
;
329 if (!parse_elements(&pbody
, p
, offset
))
333 fn_print(pbody
.ssid
.ssid
, NULL
);
334 printf(") AP : %s", etheraddr_string( pbody
.ap
));
340 handle_reassoc_response(const u_char
*p
)
342 /* Same as a Association Reponse */
343 return handle_assoc_response(p
);
347 handle_probe_request(const u_char
*p
)
349 struct mgmt_body_t pbody
;
352 memset(&pbody
, 0, sizeof(pbody
));
354 if (!parse_elements(&pbody
, p
, offset
))
358 fn_print(pbody
.ssid
.ssid
, NULL
);
366 handle_probe_response(const u_char
*p
)
368 struct mgmt_body_t pbody
;
371 memset(&pbody
, 0, sizeof(pbody
));
373 if (!TTEST2(*p
, IEEE802_11_TSTAMP_LEN
+ IEEE802_11_BCNINT_LEN
+
374 IEEE802_11_CAPINFO_LEN
))
377 memcpy(&pbody
.timestamp
, p
, IEEE802_11_TSTAMP_LEN
);
378 offset
+= IEEE802_11_TSTAMP_LEN
;
379 pbody
.beacon_interval
= EXTRACT_LE_16BITS(p
+offset
);
380 offset
+= IEEE802_11_BCNINT_LEN
;
381 pbody
.capability_info
= EXTRACT_LE_16BITS(p
+offset
);
382 offset
+= IEEE802_11_CAPINFO_LEN
;
384 if (!parse_elements(&pbody
, p
, offset
))
388 fn_print(pbody
.ssid
.ssid
, NULL
);
391 printf(" CH: %u%s", pbody
.ds
.channel
,
392 CAPABILITY_PRIVACY(pbody
.capability_info
) ? ", PRIVACY" : "" );
400 /* the frame body for ATIM is null. */
405 handle_disassoc(const u_char
*p
)
407 struct mgmt_body_t pbody
;
409 memset(&pbody
, 0, sizeof(pbody
));
411 if (!TTEST2(*p
, IEEE802_11_REASON_LEN
))
413 pbody
.reason_code
= EXTRACT_LE_16BITS(p
);
416 (pbody
.reason_code
< NUM_REASONS
)
417 ? reason_text
[pbody
.reason_code
]
424 handle_auth(const u_char
*p
)
426 struct mgmt_body_t pbody
;
429 memset(&pbody
, 0, sizeof(pbody
));
433 pbody
.auth_alg
= EXTRACT_LE_16BITS(p
);
435 pbody
.auth_trans_seq_num
= EXTRACT_LE_16BITS(p
+ offset
);
437 pbody
.status_code
= EXTRACT_LE_16BITS(p
+ offset
);
440 if (!parse_elements(&pbody
, p
, offset
))
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
< NUM_AUTH_ALGS
)
448 ? auth_alg_text
[pbody
.auth_alg
]
450 pbody
.auth_trans_seq_num
,
451 ((pbody
.auth_trans_seq_num
% 2)
452 ? ((pbody
.status_code
< NUM_STATUSES
)
453 ? status_text
[pbody
.status_code
]
457 printf(" (%s)-%x: %s",
458 (pbody
.auth_alg
< NUM_AUTH_ALGS
)
459 ? auth_alg_text
[pbody
.auth_alg
]
461 pbody
.auth_trans_seq_num
,
462 (pbody
.auth_trans_seq_num
% 2)
463 ? ((pbody
.status_code
< NUM_STATUSES
)
464 ? status_text
[pbody
.status_code
]
472 handle_deauth(const struct mgmt_header_t
*pmh
, const u_char
*p
)
474 struct mgmt_body_t pbody
;
476 const char *reason
= NULL
;
478 memset(&pbody
, 0, sizeof(pbody
));
480 if (!TTEST2(*p
, IEEE802_11_REASON_LEN
))
482 pbody
.reason_code
= EXTRACT_LE_16BITS(p
);
483 offset
+= IEEE802_11_REASON_LEN
;
485 reason
= (pbody
.reason_code
< NUM_REASONS
)
486 ? reason_text
[pbody
.reason_code
]
490 printf(": %s", reason
);
492 printf(" (%s): %s", etheraddr_string(pmh
->sa
), reason
);
498 /*********************************************************************************
500 *********************************************************************************/
504 mgmt_body_print(u_int16_t fc
, const struct mgmt_header_t
*pmh
,
507 switch (FC_SUBTYPE(fc
)) {
508 case ST_ASSOC_REQUEST
:
509 printf("Assoc Request");
510 return handle_assoc_request(p
);
511 case ST_ASSOC_RESPONSE
:
512 printf("Assoc Response");
513 return handle_assoc_response(p
);
514 case ST_REASSOC_REQUEST
:
515 printf("ReAssoc Request");
516 return handle_reassoc_request(p
);
517 case ST_REASSOC_RESPONSE
:
518 printf("ReAssoc Response");
519 return handle_reassoc_response(p
);
520 case ST_PROBE_REQUEST
:
521 printf("Probe Request");
522 return handle_probe_request(p
);
523 case ST_PROBE_RESPONSE
:
524 printf("Probe Response");
525 return handle_probe_response(p
);
528 return handle_beacon(p
);
531 return handle_atim();
533 printf("Disassociation");
534 return handle_disassoc(p
);
536 printf("Authentication");
539 if ((p
[0] == 0 ) && (p
[1] == 0) && (p
[2] == 0)) {
540 printf("Authentication (Shared-Key)-3 ");
543 return handle_auth(p
);
545 printf("DeAuthentication");
546 return handle_deauth(pmh
, p
);
549 printf("Unhandled Management subtype(%x)",
556 /*********************************************************************************
557 * Handles printing all the control frame types
558 *********************************************************************************/
561 ctrl_body_print(u_int16_t fc
, const u_char
*p
)
563 switch (FC_SUBTYPE(fc
)) {
565 printf("Power Save-Poll");
566 if (!TTEST2(*p
, CTRL_PS_POLL_HDRLEN
))
569 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t
*)p
)->aid
)));
572 printf("Request-To-Send");
573 if (!TTEST2(*p
, CTRL_RTS_HDRLEN
))
577 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ta
));
580 printf("Clear-To-Send");
581 if (!TTEST2(*p
, CTRL_CTS_HDRLEN
))
585 etheraddr_string(((const struct ctrl_cts_t
*)p
)->ra
));
588 printf("Acknowledgment");
589 if (!TTEST2(*p
, CTRL_ACK_HDRLEN
))
593 etheraddr_string(((const struct ctrl_ack_t
*)p
)->ra
));
597 if (!TTEST2(*p
, CTRL_END_HDRLEN
))
601 etheraddr_string(((const struct ctrl_end_t
*)p
)->ra
));
604 printf("CF-End+CF-Ack");
605 if (!TTEST2(*p
, CTRL_END_ACK_HDRLEN
))
609 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->ra
));
612 printf("Unknown Ctrl Subtype");
622 * Data Frame - Address field contents
624 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
625 * 0 | 0 | DA | SA | BSSID | n/a
626 * 0 | 1 | DA | BSSID | SA | n/a
627 * 1 | 0 | BSSID | SA | DA | n/a
628 * 1 | 1 | RA | TA | DA | SA
632 data_header_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
633 const u_int8_t
**dstp
)
635 switch (FC_SUBTYPE(fc
)) {
639 case DATA_DATA_CF_ACK
:
640 case DATA_NODATA_CF_ACK
:
643 case DATA_DATA_CF_POLL
:
644 case DATA_NODATA_CF_POLL
:
647 case DATA_DATA_CF_ACK_POLL
:
648 case DATA_NODATA_CF_ACK_POLL
:
649 printf("CF Ack/Poll ");
653 #define ADDR1 (p + 4)
654 #define ADDR2 (p + 10)
655 #define ADDR3 (p + 16)
656 #define ADDR4 (p + 24)
658 if (!FC_TO_DS(fc
) && !FC_FROM_DS(fc
)) {
665 printf("DA:%s SA:%s BSSID:%s ",
666 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
667 etheraddr_string(ADDR3
));
668 } else if (!FC_TO_DS(fc
) && FC_FROM_DS(fc
)) {
675 printf("DA:%s BSSID:%s SA:%s ",
676 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
677 etheraddr_string(ADDR3
));
678 } else if (FC_TO_DS(fc
) && !FC_FROM_DS(fc
)) {
685 printf("BSSID:%s SA:%s DA:%s ",
686 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
687 etheraddr_string(ADDR3
));
688 } else if (FC_TO_DS(fc
) && FC_FROM_DS(fc
)) {
695 printf("RA:%s TA:%s DA:%s SA:%s ",
696 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
697 etheraddr_string(ADDR3
), etheraddr_string(ADDR4
));
707 mgmt_header_print(const u_char
*p
, const u_int8_t
**srcp
,
708 const u_int8_t
**dstp
)
710 const struct mgmt_header_t
*hp
= (const struct mgmt_header_t
*) p
;
719 printf("BSSID:%s DA:%s SA:%s ",
720 etheraddr_string((hp
)->bssid
), etheraddr_string((hp
)->da
),
721 etheraddr_string((hp
)->sa
));
725 ctrl_header_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
726 const u_int8_t
**dstp
)
735 switch (FC_SUBTYPE(fc
)) {
737 printf("BSSID:%s TA:%s ",
738 etheraddr_string(((const struct ctrl_ps_poll_t
*)p
)->bssid
),
739 etheraddr_string(((const struct ctrl_ps_poll_t
*)p
)->ta
));
742 printf("RA:%s TA:%s ",
743 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ra
),
744 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ta
));
748 etheraddr_string(((const struct ctrl_cts_t
*)p
)->ra
));
752 etheraddr_string(((const struct ctrl_ack_t
*)p
)->ra
));
755 printf("RA:%s BSSID:%s ",
756 etheraddr_string(((const struct ctrl_end_t
*)p
)->ra
),
757 etheraddr_string(((const struct ctrl_end_t
*)p
)->bssid
));
760 printf("RA:%s BSSID:%s ",
761 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->ra
),
762 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->bssid
));
765 printf("(H) Unknown Ctrl Subtype");
771 extract_header_length(u_int16_t fc
)
773 switch (FC_TYPE(fc
)) {
777 switch (FC_SUBTYPE(fc
)) {
779 return CTRL_PS_POLL_HDRLEN
;
781 return CTRL_RTS_HDRLEN
;
783 return CTRL_CTS_HDRLEN
;
785 return CTRL_ACK_HDRLEN
;
787 return CTRL_END_HDRLEN
;
789 return CTRL_END_ACK_HDRLEN
;
794 return (FC_TO_DS(fc
) && FC_FROM_DS(fc
)) ? 30 : 24;
796 printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc
));
802 * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
803 * to point to the source and destination MAC addresses in any case if
804 * "srcp" and "dstp" aren't null.
807 ieee_802_11_hdr_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
808 const u_int8_t
**dstp
)
811 if (FC_MORE_DATA(fc
))
812 printf("More Data ");
813 if (FC_MORE_FLAG(fc
))
814 printf("More Fragments ");
815 if (FC_POWER_MGMT(fc
))
820 printf("Strictly Ordered ");
822 printf("WEP Encrypted ");
823 if (FC_TYPE(fc
) != T_CTRL
|| FC_SUBTYPE(fc
) != CTRL_PS_POLL
)
826 &((const struct mgmt_header_t
*)p
)->duration
));
829 switch (FC_TYPE(fc
)) {
831 mgmt_header_print(p
, srcp
, dstp
);
834 ctrl_header_print(fc
, p
, srcp
, dstp
);
837 data_header_print(fc
, p
, srcp
, dstp
);
840 printf("(header) unknown IEEE802.11 frame type (%d)",
849 ieee802_11_print(const u_char
*p
, u_int length
, u_int caplen
)
853 const u_int8_t
*src
, *dst
;
854 u_short extracted_ethertype
;
856 if (caplen
< IEEE802_11_FC_LEN
) {
861 fc
= EXTRACT_LE_16BITS(p
);
862 hdrlen
= extract_header_length(fc
);
864 if (caplen
< hdrlen
) {
869 ieee_802_11_hdr_print(fc
, p
, &src
, &dst
);
872 * Go past the 802.11 header.
878 switch (FC_TYPE(fc
)) {
880 if (!mgmt_body_print(fc
,
881 (const struct mgmt_header_t
*)(p
- hdrlen
), p
)) {
887 if (!ctrl_body_print(fc
, p
- hdrlen
)) {
893 /* There may be a problem w/ AP not having this bit set */
899 } else if (llc_print(p
, length
, caplen
, dst
, src
,
900 &extracted_ethertype
) == 0) {
902 * Some kinds of LLC packet we cannot
903 * handle intelligently
906 ieee_802_11_hdr_print(fc
, p
- hdrlen
, NULL
,
908 if (extracted_ethertype
)
911 htons(extracted_ethertype
)));
912 if (!suppress_default_print
)
913 default_print(p
, caplen
);
917 printf("unknown 802.11 frame type (%d)", FC_TYPE(fc
));
925 * This is the top level routine of the printer. 'p' points
926 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
927 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
928 * is the number of bytes actually captured.
931 ieee802_11_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
933 return ieee802_11_print(p
, h
->len
, h
->caplen
);
937 print_radiotap_field(struct cpack_state
*s
, u_int32_t bit
)
950 case IEEE80211_RADIOTAP_FLAGS
:
951 case IEEE80211_RADIOTAP_RATE
:
952 case IEEE80211_RADIOTAP_DB_ANTSIGNAL
:
953 case IEEE80211_RADIOTAP_DB_ANTNOISE
:
954 case IEEE80211_RADIOTAP_ANTENNA
:
955 rc
= cpack_uint8(s
, &u
.u8
);
957 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL
:
958 case IEEE80211_RADIOTAP_DBM_ANTNOISE
:
959 rc
= cpack_int8(s
, &u
.i8
);
961 case IEEE80211_RADIOTAP_CHANNEL
:
962 rc
= cpack_uint16(s
, &u
.u16
);
965 rc
= cpack_uint16(s
, &u2
.u16
);
967 case IEEE80211_RADIOTAP_FHSS
:
968 case IEEE80211_RADIOTAP_LOCK_QUALITY
:
969 case IEEE80211_RADIOTAP_TX_ATTENUATION
:
970 rc
= cpack_uint16(s
, &u
.u16
);
972 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION
:
973 rc
= cpack_uint8(s
, &u
.u8
);
975 case IEEE80211_RADIOTAP_DBM_TX_POWER
:
976 rc
= cpack_int8(s
, &u
.i8
);
978 case IEEE80211_RADIOTAP_TSFT
:
979 rc
= cpack_uint64(s
, &u
.u64
);
982 /* this bit indicates a field whose
983 * size we do not know, so we cannot
986 printf("[0x%08x] ", bit
);
996 case IEEE80211_RADIOTAP_CHANNEL
:
997 printf("%u MHz ", u
.u16
);
999 printf("(0x%04x) ", u2
.u16
);
1001 case IEEE80211_RADIOTAP_FHSS
:
1002 printf("fhset %d fhpat %d ", u
.u16
& 0xff, (u
.u16
>> 8) & 0xff);
1004 case IEEE80211_RADIOTAP_RATE
:
1005 PRINT_RATE("", u
.u8
, " Mb/s ");
1007 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL
:
1008 printf("%ddB signal ", u
.i8
);
1010 case IEEE80211_RADIOTAP_DBM_ANTNOISE
:
1011 printf("%ddB noise ", u
.i8
);
1013 case IEEE80211_RADIOTAP_DB_ANTSIGNAL
:
1014 printf("%ddB signal ", u
.u8
);
1016 case IEEE80211_RADIOTAP_DB_ANTNOISE
:
1017 printf("%ddB noise ", u
.u8
);
1019 case IEEE80211_RADIOTAP_LOCK_QUALITY
:
1020 printf("%u sq ", u
.u16
);
1022 case IEEE80211_RADIOTAP_TX_ATTENUATION
:
1023 printf("%d tx power ", -(int)u
.u16
);
1025 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION
:
1026 printf("%ddB tx power ", -(int)u
.u8
);
1028 case IEEE80211_RADIOTAP_DBM_TX_POWER
:
1029 printf("%ddBm tx power ", u
.i8
);
1031 case IEEE80211_RADIOTAP_FLAGS
:
1032 if (u
.u8
& IEEE80211_RADIOTAP_F_CFP
)
1034 if (u
.u8
& IEEE80211_RADIOTAP_F_SHORTPRE
)
1035 printf("short preamble ");
1036 if (u
.u8
& IEEE80211_RADIOTAP_F_WEP
)
1038 if (u
.u8
& IEEE80211_RADIOTAP_F_FRAG
)
1039 printf("fragmented ");
1041 case IEEE80211_RADIOTAP_ANTENNA
:
1042 printf("antenna %d ", u
.u8
);
1044 case IEEE80211_RADIOTAP_TSFT
:
1045 printf("%" PRIu64
"us tsft ", u
.u64
);
1052 ieee802_11_radio_print(const u_char
*p
, u_int length
, u_int caplen
)
1054 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
1055 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
1056 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
1057 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
1058 #define BITNO_2(x) (((x) & 2) ? 1 : 0)
1059 #define BIT(n) (1 << n)
1060 #define IS_EXTENDED(__p) \
1061 (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
1063 struct cpack_state cpacker
;
1064 struct ieee80211_radiotap_header
*hdr
;
1065 u_int32_t present
, next_present
;
1066 u_int32_t
*presentp
, *last_presentp
;
1067 enum ieee80211_radiotap_type bit
;
1072 if (caplen
< sizeof(*hdr
)) {
1073 printf("[|802.11]");
1077 hdr
= (struct ieee80211_radiotap_header
*)p
;
1079 len
= EXTRACT_LE_16BITS(&hdr
->it_len
);
1082 printf("[|802.11]");
1085 for (last_presentp
= &hdr
->it_present
;
1086 IS_EXTENDED(last_presentp
) &&
1087 (u_char
*)(last_presentp
+ 1) <= p
+ len
;
1090 /* are there more bitmap extensions than bytes in header? */
1091 if (IS_EXTENDED(last_presentp
)) {
1092 printf("[|802.11]");
1096 iter
= (u_char
*)(last_presentp
+ 1);
1098 if (cpack_init(&cpacker
, (u_int8_t
*)iter
, len
- (iter
- p
)) != 0) {
1100 printf("[|802.11]");
1104 for (bit0
= 0, presentp
= &hdr
->it_present
; presentp
<= last_presentp
;
1105 presentp
++, bit0
+= 32) {
1106 for (present
= EXTRACT_LE_32BITS(presentp
); present
;
1107 present
= next_present
) {
1108 /* clear the least significant bit that is set */
1109 next_present
= present
& (present
- 1);
1111 /* extract the least significant bit that is set */
1112 bit
= (enum ieee80211_radiotap_type
)
1113 (bit0
+ BITNO_32(present
^ next_present
));
1115 if (print_radiotap_field(&cpacker
, bit
) != 0)
1120 return len
+ ieee802_11_print(p
+ len
, length
- len
, caplen
- len
);
1130 ieee802_11_avs_radio_print(const u_char
*p
, u_int length
, u_int caplen
)
1132 u_int32_t caphdr_len
;
1134 caphdr_len
= EXTRACT_32BITS(p
+ 4);
1135 if (caphdr_len
< 8) {
1137 * Yow! The capture header length is claimed not
1138 * to be large enough to include even the version
1139 * cookie or capture header length!
1141 printf("[|802.11]");
1145 if (caplen
< caphdr_len
) {
1146 printf("[|802.11]");
1150 return caphdr_len
+ ieee802_11_print(p
+ caphdr_len
,
1151 length
- caphdr_len
, caplen
- caphdr_len
);
1154 #define PRISM_HDR_LEN 144
1156 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
1159 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
1160 * containing information such as radio information, which we
1163 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
1164 * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
1165 * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
1166 * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
1167 * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
1168 * the first 4 bytes of the header are used to indicate which it is).
1171 prism_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
1173 u_int caplen
= h
->caplen
;
1174 u_int length
= h
->len
;
1177 printf("[|802.11]");
1181 if (EXTRACT_32BITS(p
) == WLANCAP_MAGIC_COOKIE_V1
)
1182 return ieee802_11_avs_radio_print(p
, length
, caplen
);
1184 if (caplen
< PRISM_HDR_LEN
) {
1185 printf("[|802.11]");
1189 return PRISM_HDR_LEN
+ ieee802_11_print(p
+ PRISM_HDR_LEN
,
1190 length
- PRISM_HDR_LEN
, caplen
- PRISM_HDR_LEN
);
1194 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
1195 * header, containing information such as radio information, which we
1199 ieee802_11_radio_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
1201 u_int caplen
= h
->caplen
;
1202 u_int length
= h
->len
;
1205 printf("[|802.11]");
1209 return ieee802_11_radio_print(p
, length
, caplen
);