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