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.26 2003-11-27 02:18:53 guy Exp $ (LBL)";
32 #include <tcpdump-stdinc.h>
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "ethertype.h"
44 #include "ieee802_11.h"
46 #define PRINT_RATES(p) \
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("*"); \
55 if (p.rates.length != 0) \
59 static const char *auth_alg_text
[]={"Open System","Shared Key","EAP"};
60 static const char *subtype_text
[]={
78 static const char *status_text
[] = {
80 "Unspecified failure", /* 1 */
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 */
103 static const char *reason_text
[] = {
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 */
118 wep_print(const u_char
*p
)
122 if (!TTEST2(*p
, IEEE802_11_IV_LEN
+ IEEE802_11_KID_LEN
))
124 iv
= EXTRACT_LE_32BITS(p
);
126 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv
), IV_PAD(iv
),
133 parse_elements(struct mgmt_body_t
*pbody
, const u_char
*p
, int offset
)
136 if (!TTEST2(*(p
+ offset
), 1))
138 switch (*(p
+ offset
)) {
140 if (!TTEST2(*(p
+ offset
), 2))
142 memcpy(&pbody
->ssid
, p
+ offset
, 2);
144 if (pbody
->ssid
.length
<= 0)
146 if (!TTEST2(*(p
+ offset
), pbody
->ssid
.length
))
148 memcpy(&pbody
->ssid
.ssid
, p
+ offset
,
150 offset
+= pbody
->ssid
.length
;
151 pbody
->ssid
.ssid
[pbody
->ssid
.length
] = '\0';
154 if (!TTEST2(*(p
+ offset
), 2))
156 memcpy(&pbody
->challenge
, p
+ offset
, 2);
158 if (pbody
->challenge
.length
<= 0)
160 if (!TTEST2(*(p
+ offset
), pbody
->challenge
.length
))
162 memcpy(&pbody
->challenge
.text
, p
+ offset
,
163 pbody
->challenge
.length
);
164 offset
+= pbody
->challenge
.length
;
165 pbody
->challenge
.text
[pbody
->challenge
.length
] = '\0';
168 if (!TTEST2(*(p
+ offset
), 2))
170 memcpy(&(pbody
->rates
), p
+ offset
, 2);
172 if (pbody
->rates
.length
<= 0)
174 if (!TTEST2(*(p
+ offset
), pbody
->rates
.length
))
176 memcpy(&pbody
->rates
.rate
, p
+ offset
,
177 pbody
->rates
.length
);
178 offset
+= pbody
->rates
.length
;
181 if (!TTEST2(*(p
+ offset
), 3))
183 memcpy(&pbody
->ds
, p
+ offset
, 3);
187 if (!TTEST2(*(p
+ offset
), 8))
189 memcpy(&pbody
->cf
, p
+ offset
, 8);
193 if (!TTEST2(*(p
+ offset
), 2))
195 memcpy(&pbody
->tim
, p
+ offset
, 2);
197 if (!TTEST2(*(p
+ offset
), 3))
199 memcpy(&pbody
->tim
.count
, p
+ offset
, 3);
202 if (pbody
->tim
.length
<= 3)
204 if (!TTEST2(*(p
+ offset
), pbody
->tim
.length
- 3))
206 memcpy(pbody
->tim
.bitmap
, p
+ (pbody
->tim
.length
- 3),
207 (pbody
->tim
.length
- 3));
208 offset
+= pbody
->tim
.length
- 3;
212 printf("(1) unhandled element_id (%d) ",
215 offset
+= *(p
+ offset
+ 1) + 2;
222 /*********************************************************************************
223 * Print Handle functions for the management frame types
224 *********************************************************************************/
227 handle_beacon(u_int16_t fc
, const u_char
*p
)
229 struct mgmt_body_t pbody
;
232 memset(&pbody
, 0, sizeof(pbody
));
234 if (!TTEST2(*p
, IEEE802_11_TSTAMP_LEN
+ IEEE802_11_BCNINT_LEN
+
235 IEEE802_11_CAPINFO_LEN
))
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
))
248 fn_print(pbody
.ssid
.ssid
, NULL
);
251 printf(" %s CH: %u%s",
252 CAPABILITY_ESS(pbody
.capability_info
) ? "ESS" : "IBSS",
254 CAPABILITY_PRIVACY(pbody
.capability_info
) ? ", PRIVACY" : "" );
260 handle_assoc_request(u_int16_t fc
, const u_char
*p
)
262 struct mgmt_body_t pbody
;
265 memset(&pbody
, 0, sizeof(pbody
));
267 if (!TTEST2(*p
, IEEE802_11_CAPINFO_LEN
+ IEEE802_11_LISTENINT_LEN
))
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
))
278 fn_print(pbody
.ssid
.ssid
, NULL
);
285 handle_assoc_response(u_int16_t fc
, const u_char
*p
)
287 struct mgmt_body_t pbody
;
290 memset(&pbody
, 0, sizeof(pbody
));
292 if (!TTEST2(*p
, IEEE802_11_CAPINFO_LEN
+ IEEE802_11_STATUS_LEN
+
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
))
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"));
313 handle_reassoc_request(u_int16_t fc
, const u_char
*p
)
315 struct mgmt_body_t pbody
;
318 memset(&pbody
, 0, sizeof(pbody
));
320 if (!TTEST2(*p
, IEEE802_11_CAPINFO_LEN
+ IEEE802_11_LISTENINT_LEN
+
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
))
334 fn_print(pbody
.ssid
.ssid
, NULL
);
335 printf(") AP : %s", etheraddr_string( pbody
.ap
));
341 handle_reassoc_response(u_int16_t fc
, const u_char
*p
)
343 /* Same as a Association Reponse */
344 return handle_assoc_response(fc
, p
);
348 handle_probe_request(u_int16_t fc
, const u_char
*p
)
350 struct mgmt_body_t pbody
;
353 memset(&pbody
, 0, sizeof(pbody
));
355 if (!parse_elements(&pbody
, p
, offset
))
359 fn_print(pbody
.ssid
.ssid
, NULL
);
367 handle_probe_response(u_int16_t fc
, const u_char
*p
)
369 struct mgmt_body_t pbody
;
372 memset(&pbody
, 0, sizeof(pbody
));
374 if (!TTEST2(*p
, IEEE802_11_TSTAMP_LEN
+ IEEE802_11_BCNINT_LEN
+
375 IEEE802_11_CAPINFO_LEN
))
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
))
389 fn_print(pbody
.ssid
.ssid
, NULL
);
392 printf(" CH: %u%s", pbody
.ds
.channel
,
393 CAPABILITY_PRIVACY(pbody
.capability_info
) ? ", PRIVACY" : "" );
401 /* the frame body for ATIM is null. */
406 handle_disassoc(u_int16_t fc
, const u_char
*p
)
408 struct mgmt_body_t pbody
;
410 memset(&pbody
, 0, sizeof(pbody
));
412 if (!TTEST2(*p
, IEEE802_11_REASON_LEN
))
414 pbody
.reason_code
= EXTRACT_LE_16BITS(p
);
417 (pbody
.reason_code
< 10) ? reason_text
[pbody
.reason_code
]
424 handle_auth(u_int16_t fc
, 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
< 4) ? auth_alg_text
[pbody
.auth_alg
]
449 pbody
.auth_trans_seq_num
,
450 ((pbody
.auth_trans_seq_num
% 2)
451 ? ((pbody
.status_code
< 19)
452 ? status_text
[pbody
.status_code
]
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
]
468 handle_deauth(u_int16_t fc
, const struct mgmt_header_t
*pmh
,
471 struct mgmt_body_t pbody
;
473 const char *reason
= NULL
;
475 memset(&pbody
, 0, sizeof(pbody
));
477 if (!TTEST2(*p
, IEEE802_11_REASON_LEN
))
479 pbody
.reason_code
= EXTRACT_LE_16BITS(p
);
480 offset
+= IEEE802_11_REASON_LEN
;
482 reason
= (pbody
.reason_code
< 10) ? reason_text
[pbody
.reason_code
]
486 printf(": %s", reason
);
488 printf(" (%s): %s", etheraddr_string(pmh
->sa
), reason
);
494 /*********************************************************************************
496 *********************************************************************************/
500 mgmt_body_print(u_int16_t fc
, const struct mgmt_header_t
*pmh
,
503 printf("%s", subtype_text
[FC_SUBTYPE(fc
)]);
505 switch (FC_SUBTYPE(fc
)) {
506 case ST_ASSOC_REQUEST
:
507 return handle_assoc_request(fc
, p
);
508 case ST_ASSOC_RESPONSE
:
509 return handle_assoc_response(fc
, p
);
510 case ST_REASSOC_REQUEST
:
511 return handle_reassoc_request(fc
, p
);
512 case ST_REASSOC_RESPONSE
:
513 return handle_reassoc_response(fc
, p
);
514 case ST_PROBE_REQUEST
:
515 return handle_probe_request(fc
, p
);
516 case ST_PROBE_RESPONSE
:
517 return handle_probe_response(fc
, p
);
519 return handle_beacon(fc
, p
);
521 return handle_atim();
523 return handle_disassoc(fc
, p
);
527 if ((p
[0] == 0 ) && (p
[1] == 0) && (p
[2] == 0)) {
528 printf("Authentication (Shared-Key)-3 ");
531 return handle_auth(fc
, p
);
533 return handle_deauth(fc
, pmh
, p
);
536 printf("Unhandled Management subtype(%x)",
543 /*********************************************************************************
544 * Handles printing all the control frame types
545 *********************************************************************************/
548 ctrl_body_print(u_int16_t fc
, const u_char
*p
)
550 switch (FC_SUBTYPE(fc
)) {
552 printf("Power Save-Poll");
553 if (!TTEST2(*p
, CTRL_PS_POLL_HDRLEN
))
556 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t
*)p
)->aid
)));
559 printf("Request-To-Send");
560 if (!TTEST2(*p
, CTRL_RTS_HDRLEN
))
564 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ta
));
567 printf("Clear-To-Send");
568 if (!TTEST2(*p
, CTRL_CTS_HDRLEN
))
572 etheraddr_string(((const struct ctrl_cts_t
*)p
)->ra
));
575 printf("Acknowledgment");
576 if (!TTEST2(*p
, CTRL_ACK_HDRLEN
))
580 etheraddr_string(((const struct ctrl_ack_t
*)p
)->ra
));
584 if (!TTEST2(*p
, CTRL_END_HDRLEN
))
588 etheraddr_string(((const struct ctrl_end_t
*)p
)->ra
));
591 printf("CF-End+CF-Ack");
592 if (!TTEST2(*p
, CTRL_END_ACK_HDRLEN
))
596 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->ra
));
599 printf("Unknown Ctrl Subtype");
609 * Data Frame - Address field contents
611 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
612 * 0 | 0 | DA | SA | BSSID | n/a
613 * 0 | 1 | DA | BSSID | SA | n/a
614 * 1 | 0 | BSSID | SA | DA | n/a
615 * 1 | 1 | RA | TA | DA | SA
619 data_header_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
620 const u_int8_t
**dstp
)
622 switch (FC_SUBTYPE(fc
)) {
626 case DATA_DATA_CF_ACK
:
627 case DATA_NODATA_CF_ACK
:
630 case DATA_DATA_CF_POLL
:
631 case DATA_NODATA_CF_POLL
:
634 case DATA_DATA_CF_ACK_POLL
:
635 case DATA_NODATA_CF_ACK_POLL
:
636 printf("CF Ack/Poll ");
640 #define ADDR1 (p + 4)
641 #define ADDR2 (p + 10)
642 #define ADDR3 (p + 16)
643 #define ADDR4 (p + 24)
645 if (!FC_TO_DS(fc
) && !FC_FROM_DS(fc
)) {
652 printf("DA:%s SA:%s BSSID:%s ",
653 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
654 etheraddr_string(ADDR3
));
655 } else if (!FC_TO_DS(fc
) && FC_FROM_DS(fc
)) {
662 printf("DA:%s BSSID:%s SA:%s ",
663 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
664 etheraddr_string(ADDR3
));
665 } else if (FC_TO_DS(fc
) && !FC_FROM_DS(fc
)) {
672 printf("BSSID:%s SA:%s DA:%s ",
673 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
674 etheraddr_string(ADDR3
));
675 } else if (FC_TO_DS(fc
) && FC_FROM_DS(fc
)) {
682 printf("RA:%s TA:%s DA:%s SA:%s ",
683 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
684 etheraddr_string(ADDR3
), etheraddr_string(ADDR4
));
694 mgmt_header_print(const u_char
*p
, const u_int8_t
**srcp
,
695 const u_int8_t
**dstp
)
697 const struct mgmt_header_t
*hp
= (const struct mgmt_header_t
*) p
;
706 printf("BSSID:%s DA:%s SA:%s ",
707 etheraddr_string((hp
)->bssid
), etheraddr_string((hp
)->da
),
708 etheraddr_string((hp
)->sa
));
712 ctrl_header_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
713 const u_int8_t
**dstp
)
722 switch (FC_SUBTYPE(fc
)) {
724 printf("BSSID:%s TA:%s ",
725 etheraddr_string(((const struct ctrl_ps_poll_t
*)p
)->bssid
),
726 etheraddr_string(((const struct ctrl_ps_poll_t
*)p
)->ta
));
729 printf("RA:%s TA:%s ",
730 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ra
),
731 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ta
));
735 etheraddr_string(((const struct ctrl_cts_t
*)p
)->ra
));
739 etheraddr_string(((const struct ctrl_ack_t
*)p
)->ra
));
742 printf("RA:%s BSSID:%s ",
743 etheraddr_string(((const struct ctrl_end_t
*)p
)->ra
),
744 etheraddr_string(((const struct ctrl_end_t
*)p
)->bssid
));
747 printf("RA:%s BSSID:%s ",
748 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->ra
),
749 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->bssid
));
752 printf("(H) Unknown Ctrl Subtype");
758 extract_header_length(u_int16_t fc
)
760 switch (FC_TYPE(fc
)) {
764 switch (FC_SUBTYPE(fc
)) {
766 return CTRL_PS_POLL_HDRLEN
;
768 return CTRL_RTS_HDRLEN
;
770 return CTRL_CTS_HDRLEN
;
772 return CTRL_ACK_HDRLEN
;
774 return CTRL_END_HDRLEN
;
776 return CTRL_END_ACK_HDRLEN
;
781 return (FC_TO_DS(fc
) && FC_FROM_DS(fc
)) ? 30 : 24;
783 printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc
));
789 * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
790 * to point to the source and destination MAC addresses in any case if
791 * "srcp" and "dstp" aren't null.
794 ieee_802_11_hdr_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
795 const u_int8_t
**dstp
)
798 if (FC_MORE_DATA(fc
))
799 printf("More Data ");
800 if (FC_MORE_FLAG(fc
))
801 printf("More Fragments ");
802 if (FC_POWER_MGMT(fc
))
807 printf("Strictly Ordered ");
809 printf("WEP Encrypted ");
810 if (FC_TYPE(fc
) != T_CTRL
|| FC_SUBTYPE(fc
) != CTRL_PS_POLL
)
813 &((const struct mgmt_header_t
*)p
)->duration
));
816 switch (FC_TYPE(fc
)) {
818 mgmt_header_print(p
, srcp
, dstp
);
821 ctrl_header_print(fc
, p
, srcp
, dstp
);
824 data_header_print(fc
, p
, srcp
, dstp
);
827 printf("(header) unknown IEEE802.11 frame type (%d)",
836 ieee802_11_print(const u_char
*p
, u_int length
, u_int caplen
)
840 const u_int8_t
*src
, *dst
;
841 u_short extracted_ethertype
;
843 if (caplen
< IEEE802_11_FC_LEN
) {
848 fc
= EXTRACT_LE_16BITS(p
);
849 hdrlen
= extract_header_length(fc
);
851 if (caplen
< hdrlen
) {
856 ieee_802_11_hdr_print(fc
, p
, &src
, &dst
);
859 * Go past the 802.11 header.
865 switch (FC_TYPE(fc
)) {
867 if (!mgmt_body_print(fc
,
868 (const struct mgmt_header_t
*)(p
- hdrlen
), p
)) {
874 if (!ctrl_body_print(fc
, p
- hdrlen
)) {
880 /* There may be a problem w/ AP not having this bit set */
886 } else if (llc_print(p
, length
, caplen
, dst
, src
,
887 &extracted_ethertype
) == 0) {
889 * Some kinds of LLC packet we cannot
890 * handle intelligently
893 ieee_802_11_hdr_print(fc
, p
- hdrlen
, NULL
,
895 if (extracted_ethertype
)
898 htons(extracted_ethertype
)));
899 if (!xflag
&& !qflag
)
900 default_print(p
, caplen
);
904 printf("unknown 802.11 frame type (%d)", FC_TYPE(fc
));
912 * This is the top level routine of the printer. 'p' points
913 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
914 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
915 * is the number of bytes actually captured.
918 ieee802_11_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
920 return ieee802_11_print(p
, h
->len
, h
->caplen
);
924 ieee802_11_radio_print(const u_char
*p
, u_int length
, u_int caplen
)
926 u_int32_t caphdr_len
;
928 caphdr_len
= EXTRACT_32BITS(p
+ 4);
929 if (caphdr_len
< 8) {
931 * Yow! The capture header length is claimed not
932 * to be large enough to include even the version
933 * cookie or capture header length!
939 if (caplen
< caphdr_len
) {
944 return caphdr_len
+ ieee802_11_print(p
+ caphdr_len
,
945 length
- caphdr_len
, caplen
- caphdr_len
);
948 #define PRISM_HDR_LEN 144
950 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
953 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
954 * containing information such as radio information, which we
957 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
958 * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
959 * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
960 * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
961 * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
962 * the first 4 bytes of the header are used to indicate which it is).
965 prism_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
967 u_int caplen
= h
->caplen
;
968 u_int length
= h
->len
;
975 if (EXTRACT_32BITS(p
) == WLANCAP_MAGIC_COOKIE_V1
)
976 return ieee802_11_radio_print(p
, length
, caplen
);
978 if (caplen
< PRISM_HDR_LEN
) {
983 return PRISM_HDR_LEN
+ ieee802_11_print(p
+ PRISM_HDR_LEN
,
984 length
- PRISM_HDR_LEN
, caplen
- PRISM_HDR_LEN
);
988 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
989 * header, containing information such as radio information, which we
993 ieee802_11_radio_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
995 u_int caplen
= h
->caplen
;
996 u_int length
= h
->len
;
1003 return ieee802_11_radio_print(p
, length
, caplen
);