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