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
[] =
25 "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.20 2003-02-04 05:53:22 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 */
117 static int wep_print(const u_char
*p
)
123 iv
= EXTRACT_LE_32BITS(p
);
125 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv
), IV_PAD(iv
),
132 static int parse_elements(struct mgmt_body_t
*pbody
,const u_char
*p
,int offset
)
135 if (!TTEST2(*(p
+ offset
), 1))
137 switch (*(p
+ offset
)) {
139 if (!TTEST2(*(p
+offset
), 2))
141 memcpy(&(pbody
->ssid
),p
+offset
,2); offset
+= 2;
142 if (pbody
->ssid
.length
> 0)
144 if (!TTEST2(*(p
+offset
), pbody
->ssid
.length
))
146 memcpy(&(pbody
->ssid
.ssid
),p
+offset
,pbody
->ssid
.length
); offset
+= pbody
->ssid
.length
;
147 pbody
->ssid
.ssid
[pbody
->ssid
.length
]='\0';
151 if (!TTEST2(*(p
+offset
), 2))
153 memcpy(&(pbody
->challenge
),p
+offset
,2); offset
+= 2;
154 if (pbody
->challenge
.length
> 0)
156 if (!TTEST2(*(p
+offset
), pbody
->challenge
.length
))
158 memcpy(&(pbody
->challenge
.text
),p
+offset
,pbody
->challenge
.length
); offset
+= pbody
->challenge
.length
;
159 pbody
->challenge
.text
[pbody
->challenge
.length
]='\0';
163 if (!TTEST2(*(p
+offset
), 2))
165 memcpy(&(pbody
->rates
),p
+offset
,2); offset
+= 2;
166 if (pbody
->rates
.length
> 0) {
167 if (!TTEST2(*(p
+offset
), pbody
->rates
.length
))
169 memcpy(&(pbody
->rates
.rate
),p
+offset
,pbody
->rates
.length
); offset
+= pbody
->rates
.length
;
173 if (!TTEST2(*(p
+offset
), 3))
175 memcpy(&(pbody
->ds
),p
+offset
,3); offset
+=3;
178 if (!TTEST2(*(p
+offset
), 8))
180 memcpy(&(pbody
->cf
),p
+offset
,8); offset
+=8;
183 if (!TTEST2(*(p
+offset
), 2))
185 memcpy(&(pbody
->tim
),p
+offset
,2); offset
+=2;
186 if (!TTEST2(*(p
+offset
), 3))
188 memcpy(&(pbody
->tim
.count
),p
+offset
,3); offset
+=3;
190 if ((pbody
->tim
.length
-3) > 0)
192 if (!TTEST2(*(p
+offset
), pbody
->tim
.length
-3))
194 memcpy((pbody
->tim
.bitmap
),p
+(pbody
->tim
.length
-3),(pbody
->tim
.length
-3));
195 offset
+= pbody
->tim
.length
-3;
201 printf("(1) unhandled element_id (%d) ", *(p
+offset
) );
203 offset
+= *(p
+offset
+1) + 2;
210 /*********************************************************************************
211 * Print Handle functions for the management frame types
212 *********************************************************************************/
214 static int handle_beacon(u_int16_t fc
, const u_char
*p
)
216 struct mgmt_body_t pbody
;
219 memset(&pbody
, 0, sizeof(pbody
));
223 memcpy(&pbody
.timestamp
, p
, 8);
225 pbody
.beacon_interval
= EXTRACT_LE_16BITS(p
+offset
);
227 pbody
.capability_info
= EXTRACT_LE_16BITS(p
+offset
);
230 if (!parse_elements(&pbody
,p
,offset
))
233 printf("%s (", subtype_text
[FC_SUBTYPE(fc
)]);
234 fn_print(pbody
.ssid
.ssid
, NULL
);
237 printf(" %s CH: %u%s",
238 CAPABILITY_ESS(pbody
.capability_info
) ? "ESS" : "IBSS",
240 CAPABILITY_PRIVACY(pbody
.capability_info
) ? ", PRIVACY" : "" );
245 static int handle_assoc_request(u_int16_t fc
, const u_char
*p
)
247 struct mgmt_body_t pbody
;
250 memset(&pbody
, 0, sizeof(pbody
));
254 pbody
.capability_info
= EXTRACT_LE_16BITS(p
);
256 pbody
.listen_interval
= EXTRACT_LE_16BITS(p
+offset
);
259 if (!parse_elements(&pbody
,p
,offset
))
262 printf("%s (", subtype_text
[FC_SUBTYPE(fc
)]);
263 fn_print(pbody
.ssid
.ssid
, NULL
);
269 static int handle_assoc_response(u_int16_t fc
, const u_char
*p
)
271 struct mgmt_body_t pbody
;
274 memset(&pbody
, 0, sizeof(pbody
));
278 pbody
.capability_info
= EXTRACT_LE_16BITS(p
);
280 pbody
.status_code
= EXTRACT_LE_16BITS(p
+offset
);
282 pbody
.aid
= EXTRACT_LE_16BITS(p
+offset
);
285 if (!parse_elements(&pbody
,p
,offset
))
288 printf("%s AID(%x) :%s: %s", subtype_text
[FC_SUBTYPE(fc
)],
289 ((u_int16_t
)(pbody
.aid
<< 2 )) >> 2 ,
290 CAPABILITY_PRIVACY(pbody
.capability_info
) ? " PRIVACY " : "",
291 (pbody
.status_code
< 19 ? status_text
[pbody
.status_code
] : "n/a"));
297 static int handle_reassoc_request(u_int16_t fc
, const u_char
*p
)
299 struct mgmt_body_t pbody
;
302 memset(&pbody
, 0, sizeof(pbody
));
306 pbody
.capability_info
= EXTRACT_LE_16BITS(p
);
308 pbody
.listen_interval
= EXTRACT_LE_16BITS(p
+offset
);
310 memcpy(&pbody
.ap
,p
+offset
,6);
313 if (!parse_elements(&pbody
,p
,offset
))
316 printf("%s (", subtype_text
[FC_SUBTYPE(fc
)]);
317 fn_print(pbody
.ssid
.ssid
, NULL
);
318 printf(") AP : %s", etheraddr_string( pbody
.ap
));
323 static int handle_reassoc_response(u_int16_t fc
, const u_char
*p
)
325 /* Same as a Association Reponse */
326 return handle_assoc_response(fc
, p
);
329 static int handle_probe_request(u_int16_t fc
, const u_char
*p
)
331 struct mgmt_body_t pbody
;
334 memset(&pbody
, 0, sizeof(pbody
));
336 if (!parse_elements(&pbody
, p
, offset
))
339 printf("%s (", subtype_text
[FC_SUBTYPE(fc
)]);
340 fn_print(pbody
.ssid
.ssid
, NULL
);
347 static int handle_probe_response(u_int16_t fc
, const u_char
*p
)
349 struct mgmt_body_t pbody
;
352 memset(&pbody
, 0, sizeof(pbody
));
356 memcpy(&pbody
.timestamp
,p
,8);
358 pbody
.beacon_interval
= EXTRACT_LE_16BITS(p
+offset
);
360 pbody
.capability_info
= EXTRACT_LE_16BITS(p
+offset
);
363 if (!parse_elements(&pbody
, p
, offset
))
366 printf("%s (", subtype_text
[FC_SUBTYPE(fc
)]);
367 fn_print(pbody
.ssid
.ssid
, NULL
);
370 printf(" CH: %u%s", pbody
.ds
.channel
,
371 CAPABILITY_PRIVACY(pbody
.capability_info
) ? ", PRIVACY" : "" );
376 static int handle_atim(void)
378 /* the frame body for ATIM is null. */
383 static int handle_disassoc(u_int16_t fc
, const u_char
*p
)
385 struct mgmt_body_t pbody
;
388 memset(&pbody
, 0, sizeof(pbody
));
392 pbody
.reason_code
= EXTRACT_LE_16BITS(p
);
395 printf("%s: %s", subtype_text
[FC_SUBTYPE(fc
)],
396 pbody
.reason_code
< 10 ? reason_text
[pbody
.reason_code
] : "Reserved" );
401 static int handle_auth(u_int16_t fc
, const u_char
*p
)
403 struct mgmt_body_t pbody
;
406 memset(&pbody
, 0, sizeof(pbody
));
410 pbody
.auth_alg
= EXTRACT_LE_16BITS(p
);
412 pbody
.auth_trans_seq_num
= EXTRACT_LE_16BITS(p
+ offset
);
414 pbody
.status_code
= EXTRACT_LE_16BITS(p
+ offset
);
417 if (!parse_elements(&pbody
,p
,offset
))
420 if ((pbody
.auth_alg
== 1) &&
421 ((pbody
.auth_trans_seq_num
== 2) || (pbody
.auth_trans_seq_num
== 3))) {
422 printf("%s (%s)-%x [Challenge Text] %s",
423 subtype_text
[FC_SUBTYPE(fc
)],
424 pbody
.auth_alg
< 4 ? auth_alg_text
[pbody
.auth_alg
] : "Reserved" ,
425 pbody
.auth_trans_seq_num
,
426 ((pbody
.auth_trans_seq_num
% 2) ?
427 (pbody
.status_code
< 19 ? status_text
[pbody
.status_code
] : "n/a") : "" ));
429 printf("%s (%s)-%x: %s",
430 subtype_text
[FC_SUBTYPE(fc
)],
431 pbody
.auth_alg
< 4 ? auth_alg_text
[pbody
.auth_alg
] : "Reserved" ,
432 pbody
.auth_trans_seq_num
,
433 ((pbody
.auth_trans_seq_num
% 2) ? (pbody
.status_code
< 19 ? status_text
[pbody
.status_code
] : "n/a") : ""));
439 static int handle_deauth(u_int16_t fc
, const struct mgmt_header_t
*pmh
,
442 struct mgmt_body_t pbody
;
445 memset(&pbody
, 0, sizeof(pbody
));
449 pbody
.reason_code
= EXTRACT_LE_16BITS(p
);
454 subtype_text
[FC_SUBTYPE(fc
)],
455 pbody
.reason_code
< 10 ? reason_text
[pbody
.reason_code
] : "Reserved" );
457 printf("%s (%s): %s",
458 subtype_text
[FC_SUBTYPE(fc
)], etheraddr_string(pmh
->sa
),
459 pbody
.reason_code
< 10 ? reason_text
[pbody
.reason_code
] : "Reserved" );
466 /*********************************************************************************
468 *********************************************************************************/
471 static int mgmt_body_print(u_int16_t fc
, const struct mgmt_header_t
*pmh
,
474 switch (FC_SUBTYPE(fc
)) {
475 case ST_ASSOC_REQUEST
:
476 return (handle_assoc_request(fc
, p
));
477 case ST_ASSOC_RESPONSE
:
478 return (handle_assoc_response(fc
, p
));
479 case ST_REASSOC_REQUEST
:
480 return (handle_reassoc_request(fc
, p
));
481 case ST_REASSOC_RESPONSE
:
482 return (handle_reassoc_response(fc
, p
));
483 case ST_PROBE_REQUEST
:
484 return (handle_probe_request(fc
, p
));
485 case ST_PROBE_RESPONSE
:
486 return (handle_probe_response(fc
, p
));
488 return (handle_beacon(fc
, p
));
490 return (handle_atim());
492 return (handle_disassoc(fc
, p
));
496 if ((p
[0] == 0 ) && (p
[1] == 0) && (p
[2] == 0)) {
497 printf("Authentication (Shared-Key)-3 ");
498 return (wep_print(p
));
501 return (handle_auth(fc
, p
));
503 return (handle_deauth(fc
, pmh
, p
));
506 printf("Unhandled Managment subtype(%x)",
513 /*********************************************************************************
514 * Handles printing all the control frame types
515 *********************************************************************************/
517 static int ctrl_body_print(u_int16_t fc
, const u_char
*p
)
519 switch (FC_SUBTYPE(fc
)) {
521 if (!TTEST2(*p
, CTRL_PS_POLL_LEN
))
523 printf("Power Save-Poll AID(%x)",
524 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t
*)p
)->aid
)));
527 if (!TTEST2(*p
, CTRL_RTS_LEN
))
530 printf("Request-To-Send");
532 printf("Request-To-Send TA:%s ",
533 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ta
));
536 if (!TTEST2(*p
, CTRL_CTS_LEN
))
539 printf("Clear-To-Send");
541 printf("Clear-To-Send RA:%s ",
542 etheraddr_string(((const struct ctrl_cts_t
*)p
)->ra
));
545 if (!TTEST2(*p
, CTRL_ACK_LEN
))
548 printf("Acknowledgment");
550 printf("Acknowledgment RA:%s ",
551 etheraddr_string(((const struct ctrl_ack_t
*)p
)->ra
));
554 if (!TTEST2(*p
, CTRL_END_LEN
))
559 printf("CF-End RA:%s ",
560 etheraddr_string(((const struct ctrl_end_t
*)p
)->ra
));
563 if (!TTEST2(*p
, CTRL_END_ACK_LEN
))
566 printf("CF-End+CF-Ack");
568 printf("CF-End+CF-Ack RA:%s ",
569 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->ra
));
572 printf("(B) Unknown Ctrl Subtype");
584 * Data Frame - Address field contents
586 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
587 * 0 | 0 | DA | SA | BSSID | n/a
588 * 0 | 1 | DA | BSSID | SA | n/a
589 * 1 | 0 | BSSID | SA | DA | n/a
590 * 1 | 1 | RA | TA | DA | SA
594 data_header_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
595 const u_int8_t
**dstp
)
597 switch (FC_SUBTYPE(fc
)) {
601 case DATA_DATA_CF_ACK
:
602 case DATA_NODATA_CF_ACK
:
605 case DATA_DATA_CF_POLL
:
606 case DATA_NODATA_CF_POLL
:
609 case DATA_DATA_CF_ACK_POLL
:
610 case DATA_NODATA_CF_ACK_POLL
:
611 printf("CF Ack/Poll ");
615 #define ADDR1 (p + 4)
616 #define ADDR2 (p + 10)
617 #define ADDR3 (p + 16)
618 #define ADDR4 (p + 24)
621 if (!FC_FROM_DS(fc
)) {
628 printf("DA:%s SA:%s BSSID:%s ",
629 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
630 etheraddr_string(ADDR3
));
638 printf("DA:%s BSSID:%s SA:%s ",
639 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
640 etheraddr_string(ADDR3
));
643 if (!FC_FROM_DS(fc
)) {
650 printf("BSSID:%s SA:%s DA:%s ",
651 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
652 etheraddr_string(ADDR3
));
660 printf("RA:%s TA:%s DA:%s SA:%s ",
661 etheraddr_string(ADDR1
), etheraddr_string(ADDR2
),
662 etheraddr_string(ADDR3
), etheraddr_string(ADDR4
));
674 mgmt_header_print(const u_char
*p
, const u_int8_t
**srcp
,
675 const u_int8_t
**dstp
)
677 const struct mgmt_header_t
*hp
= (const struct mgmt_header_t
*) p
;
686 printf("BSSID:%s DA:%s SA:%s ",
687 etheraddr_string((hp
)->bssid
), etheraddr_string((hp
)->da
),
688 etheraddr_string((hp
)->sa
));
692 ctrl_header_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
693 const u_int8_t
**dstp
)
702 switch (FC_SUBTYPE(fc
)) {
704 printf("BSSID:%s TA:%s ",
705 etheraddr_string(((const struct ctrl_ps_poll_t
*)p
)->bssid
),
706 etheraddr_string(((const struct ctrl_ps_poll_t
*)p
)->ta
));
709 printf("RA:%s TA:%s ",
710 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ra
),
711 etheraddr_string(((const struct ctrl_rts_t
*)p
)->ta
));
715 etheraddr_string(((const struct ctrl_cts_t
*)p
)->ra
));
719 etheraddr_string(((const struct ctrl_ack_t
*)p
)->ra
));
722 printf("RA:%s BSSID:%s ",
723 etheraddr_string(((const struct ctrl_end_t
*)p
)->ra
),
724 etheraddr_string(((const struct ctrl_end_t
*)p
)->bssid
));
727 printf("RA:%s BSSID:%s ",
728 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->ra
),
729 etheraddr_string(((const struct ctrl_end_ack_t
*)p
)->bssid
));
732 printf("(H) Unknown Ctrl Subtype");
737 static int GetHeaderLength(u_int16_t fc
)
741 switch (FC_TYPE(fc
)) {
743 iLength
= MGMT_HEADER_LEN
;
746 switch (FC_SUBTYPE(fc
)) {
748 iLength
= CTRL_PS_POLL_LEN
;
751 iLength
= CTRL_RTS_LEN
;
754 iLength
= CTRL_CTS_LEN
;
757 iLength
= CTRL_ACK_LEN
;
760 iLength
= CTRL_END_LEN
;
763 iLength
= CTRL_END_ACK_LEN
;
771 if (FC_TO_DS(fc
) && FC_FROM_DS(fc
))
777 printf("unknown IEEE802.11 frame type (%d)",
786 * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
787 * to point to the source and destination MAC addresses in any case if
788 * "srcp" and "dstp" aren't null.
791 ieee_802_11_hdr_print(u_int16_t fc
, const u_char
*p
, const u_int8_t
**srcp
,
792 const u_int8_t
**dstp
)
795 if (FC_MORE_DATA(fc
))
796 printf("More Data ");
797 if (FC_MORE_FLAG(fc
))
798 printf("More Fragments ");
799 if (FC_POWER_MGMT(fc
))
804 printf("Strictly Ordered ");
806 printf("WEP Encrypted ");
809 switch (FC_TYPE(fc
)) {
811 mgmt_header_print(p
, srcp
, dstp
);
815 ctrl_header_print(fc
, p
, srcp
, dstp
);
819 data_header_print(fc
, p
, srcp
, dstp
);
823 printf("(header) unknown IEEE802.11 frame type (%d)",
832 ieee802_11_print(const u_char
*p
, u_int length
, u_int caplen
)
836 const u_int8_t
*src
, *dst
;
837 u_short extracted_ethertype
;
839 if (caplen
< IEEE802_11_FC_LEN
) {
844 fc
= EXTRACT_LE_16BITS(p
);
845 HEADER_LENGTH
= GetHeaderLength(fc
);
847 if (caplen
< HEADER_LENGTH
) {
849 return HEADER_LENGTH
;
852 ieee_802_11_hdr_print(fc
, p
, &src
, &dst
);
855 * Go past the 802.11 header.
857 length
-= HEADER_LENGTH
;
858 caplen
-= HEADER_LENGTH
;
861 switch (FC_TYPE(fc
)) {
863 if (!mgmt_body_print(fc
,
864 (const struct mgmt_header_t
*)(p
- HEADER_LENGTH
), p
)) {
866 return HEADER_LENGTH
;
871 if (!ctrl_body_print(fc
, p
- HEADER_LENGTH
)) {
873 return HEADER_LENGTH
;
878 /* There may be a problem w/ AP not having this bit set */
882 return HEADER_LENGTH
;
885 if (llc_print(p
, length
, caplen
, dst
, src
,
886 &extracted_ethertype
) == 0) {
888 * Some kinds of LLC packet we cannot
889 * handle intelligently
892 ieee_802_11_hdr_print(fc
, p
- HEADER_LENGTH
,
894 if (extracted_ethertype
) {
896 etherproto_string(htons(extracted_ethertype
)));
898 if (!xflag
&& !qflag
)
899 default_print(p
, caplen
);
905 printf("(body) unhandled IEEE802.11 frame type (%d)",
910 return HEADER_LENGTH
;
914 * This is the top level routine of the printer. 'p' points
915 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
916 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
917 * is the number of bytes actually captured.
920 ieee802_11_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
922 return ieee802_11_print(p
, h
->len
, h
->caplen
);
926 ieee802_11_radio_print(const u_char
*p
, u_int length
, u_int caplen
)
928 u_int32_t caphdr_len
;
930 caphdr_len
= EXTRACT_32BITS(p
+ 4);
931 if (caphdr_len
< 8) {
933 * Yow! The capture header length is claimed not
934 * to be large enough to include even the version
935 * cookie or capture header length!
941 if (caplen
< caphdr_len
) {
946 return caphdr_len
+ ieee802_11_print(p
+ caphdr_len
,
947 length
- caphdr_len
, caplen
- caphdr_len
);
950 #define PRISM_HDR_LEN 144
952 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
955 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
956 * containing information such as radio information, which we
959 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
960 * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
961 * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
962 * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
963 * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
964 * the first 4 bytes of the header are used to indicate which it is).
967 prism_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
969 u_int caplen
= h
->caplen
;
970 u_int length
= h
->len
;
978 msgcode
= EXTRACT_32BITS(p
);
979 if (msgcode
== WLANCAP_MAGIC_COOKIE_V1
)
980 return ieee802_11_radio_print(p
, length
, caplen
);
982 if (caplen
< PRISM_HDR_LEN
) {
987 return PRISM_HDR_LEN
+ ieee802_11_print(p
+ PRISM_HDR_LEN
,
988 length
- PRISM_HDR_LEN
, caplen
- PRISM_HDR_LEN
);
993 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
994 * header, containing information such as radio information, which we
998 ieee802_11_radio_if_print(const struct pcap_pkthdr
*h
, const u_char
*p
)
1000 u_int caplen
= h
->caplen
;
1001 u_int length
= h
->len
;
1004 printf("[|802.11]");
1008 return ieee802_11_radio_print(p
, length
, caplen
);