Instead of using the non-standard conforming %+ format string,
[dragonfly.git] / contrib / tcpdump-3.8.3 / 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.22.2.6 2003/12/10 09:52:33 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 "ieee802_11.h"
45
46 #define PRINT_RATES(p) \
47 do { \
48         int z; \
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("*"); \
53                 sep = " "; \
54         } \
55         if (p.rates.length != 0) \
56                 printf(" Mbit]"); \
57 } while (0)
58
59 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
60 static const char *subtype_text[]={
61         "Assoc Request",
62         "Assoc Response",
63         "ReAssoc Request",
64         "ReAssoc Response",
65         "Probe Request",
66         "Probe Response",
67         "",
68         "",
69         "Beacon",
70         "ATIM",
71         "Disassociation",
72         "Authentication",
73         "DeAuthentication",
74         "",
75         ""
76 };
77
78 static const char *status_text[] = {
79         "Succesful",  /*  0  */
80         "Unspecified failure",  /*  1  */
81         "Reserved",       /*  2  */
82         "Reserved",       /*  3  */
83         "Reserved",       /*  4  */
84         "Reserved",       /*  5  */
85         "Reserved",       /*  6  */
86         "Reserved",       /*  7  */
87         "Reserved",       /*  8  */
88         "Reserved",       /*  9  */
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 */
100         NULL
101 };
102
103 static const char *reason_text[] = {
104         "Reserved", /* 0 */
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 */
114         NULL
115 };
116
117 static int
118 wep_print(const u_char *p)
119 {
120         u_int32_t iv;
121
122         if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
123                 return 0;
124         iv = EXTRACT_LE_32BITS(p);
125
126         printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
127             IV_KEYID(iv));
128
129         return 1;
130 }
131
132 static int
133 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
134 {
135         for (;;) {
136                 if (!TTEST2(*(p + offset), 1))
137                         return 1;
138                 switch (*(p + offset)) {
139                 case E_SSID:
140                         if (!TTEST2(*(p + offset), 2))
141                                 return 0;
142                         memcpy(&pbody->ssid, p + offset, 2);
143                         offset += 2;
144                         if (pbody->ssid.length <= 0)
145                                 break;
146                         if (!TTEST2(*(p + offset), pbody->ssid.length))
147                                 return 0;
148                         memcpy(&pbody->ssid.ssid, p + offset,
149                             pbody->ssid.length);
150                         offset += pbody->ssid.length;
151                         pbody->ssid.ssid[pbody->ssid.length] = '\0';
152                         break;
153                 case E_CHALLENGE:
154                         if (!TTEST2(*(p + offset), 2))
155                                 return 0;
156                         memcpy(&pbody->challenge, p + offset, 2);
157                         offset += 2;
158                         if (pbody->challenge.length <= 0)
159                                 break;
160                         if (!TTEST2(*(p + offset), pbody->challenge.length))
161                                 return 0;
162                         memcpy(&pbody->challenge.text, p + offset,
163                             pbody->challenge.length);
164                         offset += pbody->challenge.length;
165                         pbody->challenge.text[pbody->challenge.length] = '\0';
166                         break;
167                 case E_RATES:
168                         if (!TTEST2(*(p + offset), 2))
169                                 return 0;
170                         memcpy(&(pbody->rates), p + offset, 2);
171                         offset += 2;
172                         if (pbody->rates.length <= 0)
173                                 break;
174                         if (!TTEST2(*(p + offset), pbody->rates.length))
175                                 return 0;
176                         memcpy(&pbody->rates.rate, p + offset,
177                             pbody->rates.length);
178                         offset += pbody->rates.length;
179                         break;
180                 case E_DS:
181                         if (!TTEST2(*(p + offset), 3))
182                                 return 0;
183                         memcpy(&pbody->ds, p + offset, 3);
184                         offset += 3;
185                         break;
186                 case E_CF:
187                         if (!TTEST2(*(p + offset), 8))
188                                 return 0;
189                         memcpy(&pbody->cf, p + offset, 8);
190                         offset += 8;
191                         break;
192                 case E_TIM:
193                         if (!TTEST2(*(p + offset), 2))
194                                 return 0;
195                         memcpy(&pbody->tim, p + offset, 2);
196                         offset += 2;
197                         if (!TTEST2(*(p + offset), 3))
198                                 return 0;
199                         memcpy(&pbody->tim.count, p + offset, 3);
200                         offset += 3;
201
202                         if (pbody->tim.length <= 3)
203                                 break;
204                         if (!TTEST2(*(p + offset), pbody->tim.length - 3))
205                                 return 0;
206                         memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
207                             (pbody->tim.length - 3));
208                         offset += pbody->tim.length - 3;
209                         break;
210                 default:
211 #if 0
212                         printf("(1) unhandled element_id (%d)  ",
213                             *(p + offset) );
214 #endif
215                         offset += *(p + offset + 1) + 2;
216                         break;
217                 }
218         }
219         return 1;
220 }
221
222 /*********************************************************************************
223  * Print Handle functions for the management frame types
224  *********************************************************************************/
225
226 static int
227 handle_beacon(const u_char *p)
228 {
229         struct mgmt_body_t pbody;
230         int offset = 0;
231
232         memset(&pbody, 0, sizeof(pbody));
233
234         if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
235             IEEE802_11_CAPINFO_LEN))
236                 return 0;
237         memcpy(&pbody.timestamp, p, 8);
238         offset += IEEE802_11_TSTAMP_LEN;
239         pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
240         offset += IEEE802_11_BCNINT_LEN;
241         pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
242         offset += IEEE802_11_CAPINFO_LEN;
243
244         if (!parse_elements(&pbody, p, offset))
245                 return 0;
246
247         printf(" (");
248         fn_print(pbody.ssid.ssid, NULL);
249         printf(")");
250         PRINT_RATES(pbody);
251         printf(" %s CH: %u%s",
252             CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS",
253             pbody.ds.channel,
254             CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
255
256         return 1;
257 }
258
259 static int
260 handle_assoc_request(const u_char *p)
261 {
262         struct mgmt_body_t pbody;
263         int offset = 0;
264
265         memset(&pbody, 0, sizeof(pbody));
266
267         if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
268                 return 0;
269         pbody.capability_info = EXTRACT_LE_16BITS(p);
270         offset += IEEE802_11_CAPINFO_LEN;
271         pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
272         offset += IEEE802_11_LISTENINT_LEN;
273
274         if (!parse_elements(&pbody, p, offset))
275                 return 0;
276
277         printf(" (");
278         fn_print(pbody.ssid.ssid, NULL);
279         printf(")");
280         PRINT_RATES(pbody);
281         return 1;
282 }
283
284 static int
285 handle_assoc_response(const u_char *p)
286 {
287         struct mgmt_body_t pbody;
288         int offset = 0;
289
290         memset(&pbody, 0, sizeof(pbody));
291
292         if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
293             IEEE802_11_AID_LEN))
294                 return 0;
295         pbody.capability_info = EXTRACT_LE_16BITS(p);
296         offset += IEEE802_11_CAPINFO_LEN;
297         pbody.status_code = EXTRACT_LE_16BITS(p+offset);
298         offset += IEEE802_11_STATUS_LEN;
299         pbody.aid = EXTRACT_LE_16BITS(p+offset);
300         offset += IEEE802_11_AID_LEN;
301
302         if (!parse_elements(&pbody, p, offset))
303                 return 0;
304
305         printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
306             CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
307             (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a"));
308
309         return 1;
310 }
311
312 static int
313 handle_reassoc_request(const u_char *p)
314 {
315         struct mgmt_body_t pbody;
316         int offset = 0;
317
318         memset(&pbody, 0, sizeof(pbody));
319
320         if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
321             IEEE802_11_AP_LEN))
322                 return 0;
323         pbody.capability_info = EXTRACT_LE_16BITS(p);
324         offset += IEEE802_11_CAPINFO_LEN;
325         pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
326         offset += IEEE802_11_LISTENINT_LEN;
327         memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
328         offset += IEEE802_11_AP_LEN;
329
330         if (!parse_elements(&pbody, p, offset))
331                 return 0;
332
333         printf(" (");
334         fn_print(pbody.ssid.ssid, NULL);
335         printf(") AP : %s", etheraddr_string( pbody.ap ));
336
337         return 1;
338 }
339
340 static int
341 handle_reassoc_response(const u_char *p)
342 {
343         /* Same as a Association Reponse */
344         return handle_assoc_response(p);
345 }
346
347 static int
348 handle_probe_request(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 (!parse_elements(&pbody, p, offset))
356                 return 0;
357
358         printf(" (");
359         fn_print(pbody.ssid.ssid, NULL);
360         printf(")");
361         PRINT_RATES(pbody);
362
363         return 1;
364 }
365
366 static int
367 handle_probe_response(const u_char *p)
368 {
369         struct mgmt_body_t  pbody;
370         int offset = 0;
371
372         memset(&pbody, 0, sizeof(pbody));
373
374         if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
375             IEEE802_11_CAPINFO_LEN))
376                 return 0;
377
378         memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
379         offset += IEEE802_11_TSTAMP_LEN;
380         pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
381         offset += IEEE802_11_BCNINT_LEN;
382         pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
383         offset += IEEE802_11_CAPINFO_LEN;
384
385         if (!parse_elements(&pbody, p, offset))
386                 return 0;
387
388         printf(" (");
389         fn_print(pbody.ssid.ssid, NULL);
390         printf(") ");
391         PRINT_RATES(pbody);
392         printf(" CH: %u%s", pbody.ds.channel,
393             CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
394
395         return 1;
396 }
397
398 static int
399 handle_atim(void)
400 {
401         /* the frame body for ATIM is null. */
402         return 1;
403 }
404
405 static int
406 handle_disassoc(const u_char *p)
407 {
408         struct mgmt_body_t  pbody;
409
410         memset(&pbody, 0, sizeof(pbody));
411
412         if (!TTEST2(*p, IEEE802_11_REASON_LEN))
413                 return 0;
414         pbody.reason_code = EXTRACT_LE_16BITS(p);
415
416         printf(": %s",
417             (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
418                                      : "Reserved" );
419
420         return 1;
421 }
422
423 static int
424 handle_auth(const u_char *p)
425 {
426         struct mgmt_body_t  pbody;
427         int offset = 0;
428
429         memset(&pbody, 0, sizeof(pbody));
430
431         if (!TTEST2(*p, 6))
432                 return 0;
433         pbody.auth_alg = EXTRACT_LE_16BITS(p);
434         offset += 2;
435         pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
436         offset += 2;
437         pbody.status_code = EXTRACT_LE_16BITS(p + offset);
438         offset += 2;
439
440         if (!parse_elements(&pbody, p, offset))
441                 return 0;
442
443         if ((pbody.auth_alg == 1) &&
444             ((pbody.auth_trans_seq_num == 2) ||
445              (pbody.auth_trans_seq_num == 3))) {
446                 printf(" (%s)-%x [Challenge Text] %s",
447                     (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg]
448                                          : "Reserved",
449                     pbody.auth_trans_seq_num,
450                     ((pbody.auth_trans_seq_num % 2)
451                         ? ((pbody.status_code < 19)
452                                ? status_text[pbody.status_code]
453                                : "n/a") : ""));
454                 return 1;
455         }
456         printf(" (%s)-%x: %s",
457             (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg] : "Reserved",
458             pbody.auth_trans_seq_num,
459             (pbody.auth_trans_seq_num % 2)
460                 ? ((pbody.status_code < 19) ? status_text[pbody.status_code]
461                                             : "n/a")
462                 : "");
463
464         return 1;
465 }
466
467 static int
468 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
469 {
470         struct mgmt_body_t  pbody;
471         int offset = 0;
472         const char *reason = NULL;
473
474         memset(&pbody, 0, sizeof(pbody));
475
476         if (!TTEST2(*p, IEEE802_11_REASON_LEN))
477                 return 0;
478         pbody.reason_code = EXTRACT_LE_16BITS(p);
479         offset += IEEE802_11_REASON_LEN;
480
481         reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
482                                           : "Reserved";
483
484         if (eflag) {
485                 printf(": %s", reason);
486         } else {
487                 printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
488         }
489         return 1;
490 }
491
492
493 /*********************************************************************************
494  * Print Body funcs
495  *********************************************************************************/
496
497
498 static int
499 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
500     const u_char *p)
501 {
502         printf("%s", subtype_text[FC_SUBTYPE(fc)]);
503
504         switch (FC_SUBTYPE(fc)) {
505         case ST_ASSOC_REQUEST:
506                 return handle_assoc_request(p);
507         case ST_ASSOC_RESPONSE:
508                 return handle_assoc_response(p);
509         case ST_REASSOC_REQUEST:
510                 return handle_reassoc_request(p);
511         case ST_REASSOC_RESPONSE:
512                 return handle_reassoc_response(p);
513         case ST_PROBE_REQUEST:
514                 return handle_probe_request(p);
515         case ST_PROBE_RESPONSE:
516                 return handle_probe_response(p);
517         case ST_BEACON:
518                 return handle_beacon(p);
519         case ST_ATIM:
520                 return handle_atim();
521         case ST_DISASSOC:
522                 return handle_disassoc(p);
523         case ST_AUTH:
524                 if (!TTEST2(*p, 3))
525                         return 0;
526                 if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
527                         printf("Authentication (Shared-Key)-3 ");
528                         return wep_print(p);
529                 }
530                 return handle_auth(p);
531         case ST_DEAUTH:
532                 return handle_deauth(pmh, p);
533                 break;
534         default:
535                 printf("Unhandled Management subtype(%x)",
536                     FC_SUBTYPE(fc));
537                 return 1;
538         }
539 }
540
541
542 /*********************************************************************************
543  * Handles printing all the control frame types
544  *********************************************************************************/
545
546 static int
547 ctrl_body_print(u_int16_t fc, const u_char *p)
548 {
549         switch (FC_SUBTYPE(fc)) {
550         case CTRL_PS_POLL:
551                 printf("Power Save-Poll");
552                 if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
553                         return 0;
554                 printf(" AID(%x)",
555                     EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
556                 break;
557         case CTRL_RTS:
558                 printf("Request-To-Send");
559                 if (!TTEST2(*p, CTRL_RTS_HDRLEN))
560                         return 0;
561                 if (!eflag)
562                         printf(" TA:%s ",
563                             etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
564                 break;
565         case CTRL_CTS:
566                 printf("Clear-To-Send");
567                 if (!TTEST2(*p, CTRL_CTS_HDRLEN))
568                         return 0;
569                 if (!eflag)
570                         printf(" RA:%s ",
571                             etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
572                 break;
573         case CTRL_ACK:
574                 printf("Acknowledgment");
575                 if (!TTEST2(*p, CTRL_ACK_HDRLEN))
576                         return 0;
577                 if (!eflag)
578                         printf(" RA:%s ",
579                             etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
580                 break;
581         case CTRL_CF_END:
582                 printf("CF-End");
583                 if (!TTEST2(*p, CTRL_END_HDRLEN))
584                         return 0;
585                 if (!eflag)
586                         printf(" RA:%s ",
587                             etheraddr_string(((const struct ctrl_end_t *)p)->ra));
588                 break;
589         case CTRL_END_ACK:
590                 printf("CF-End+CF-Ack");
591                 if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
592                         return 0;
593                 if (!eflag)
594                         printf(" RA:%s ",
595                             etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
596                 break;
597         default:
598                 printf("Unknown Ctrl Subtype");
599         }
600         return 1;
601 }
602
603 /*
604  * Print Header funcs
605  */
606
607 /*
608  *  Data Frame - Address field contents
609  *
610  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
611  *    0    |  0      |  DA    | SA     | BSSID  | n/a
612  *    0    |  1      |  DA    | BSSID  | SA     | n/a
613  *    1    |  0      |  BSSID | SA     | DA     | n/a
614  *    1    |  1      |  RA    | TA     | DA     | SA
615  */
616
617 static void
618 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
619     const u_int8_t **dstp)
620 {
621         switch (FC_SUBTYPE(fc)) {
622         case DATA_DATA:
623         case DATA_NODATA:
624                 break;
625         case DATA_DATA_CF_ACK:
626         case DATA_NODATA_CF_ACK:
627                 printf("CF Ack ");
628                 break;
629         case DATA_DATA_CF_POLL:
630         case DATA_NODATA_CF_POLL:
631                 printf("CF Poll ");
632                 break;
633         case DATA_DATA_CF_ACK_POLL:
634         case DATA_NODATA_CF_ACK_POLL:
635                 printf("CF Ack/Poll ");
636                 break;
637         }
638
639 #define ADDR1  (p + 4)
640 #define ADDR2  (p + 10)
641 #define ADDR3  (p + 16)
642 #define ADDR4  (p + 24)
643
644         if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
645                 if (srcp != NULL)
646                         *srcp = ADDR2;
647                 if (dstp != NULL)
648                         *dstp = ADDR1;
649                 if (!eflag)
650                         return;
651                 printf("DA:%s SA:%s BSSID:%s ",
652                     etheraddr_string(ADDR1), etheraddr_string(ADDR2),
653                     etheraddr_string(ADDR3));
654         } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
655                 if (srcp != NULL)
656                         *srcp = ADDR3;
657                 if (dstp != NULL)
658                         *dstp = ADDR1;
659                 if (!eflag)
660                         return;
661                 printf("DA:%s BSSID:%s SA:%s ",
662                     etheraddr_string(ADDR1), etheraddr_string(ADDR2),
663                     etheraddr_string(ADDR3));
664         } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
665                 if (srcp != NULL)
666                         *srcp = ADDR2;
667                 if (dstp != NULL)
668                         *dstp = ADDR3;
669                 if (!eflag)
670                         return;
671                 printf("BSSID:%s SA:%s DA:%s ",
672                     etheraddr_string(ADDR1), etheraddr_string(ADDR2),
673                     etheraddr_string(ADDR3));
674         } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
675                 if (srcp != NULL)
676                         *srcp = ADDR4;
677                 if (dstp != NULL)
678                         *dstp = ADDR3;
679                 if (!eflag)
680                         return;
681                 printf("RA:%s TA:%s DA:%s SA:%s ",
682                     etheraddr_string(ADDR1), etheraddr_string(ADDR2),
683                     etheraddr_string(ADDR3), etheraddr_string(ADDR4));
684         }
685
686 #undef ADDR1
687 #undef ADDR2
688 #undef ADDR3
689 #undef ADDR4
690 }
691
692 static void
693 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
694     const u_int8_t **dstp)
695 {
696         const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
697
698         if (srcp != NULL)
699                 *srcp = hp->sa;
700         if (dstp != NULL)
701                 *dstp = hp->da;
702         if (!eflag)
703                 return;
704
705         printf("BSSID:%s DA:%s SA:%s ",
706             etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
707             etheraddr_string((hp)->sa));
708 }
709
710 static void
711 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
712     const u_int8_t **dstp)
713 {
714         if (srcp != NULL)
715                 *srcp = NULL;
716         if (dstp != NULL)
717                 *dstp = NULL;
718         if (!eflag)
719                 return;
720
721         switch (FC_SUBTYPE(fc)) {
722         case CTRL_PS_POLL:
723                 printf("BSSID:%s TA:%s ",
724                     etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
725                     etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
726                 break;
727         case CTRL_RTS:
728                 printf("RA:%s TA:%s ",
729                     etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
730                     etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
731                 break;
732         case CTRL_CTS:
733                 printf("RA:%s ",
734                     etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
735                 break;
736         case CTRL_ACK:
737                 printf("RA:%s ",
738                     etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
739                 break;
740         case CTRL_CF_END:
741                 printf("RA:%s BSSID:%s ",
742                     etheraddr_string(((const struct ctrl_end_t *)p)->ra),
743                     etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
744                 break;
745         case CTRL_END_ACK:
746                 printf("RA:%s BSSID:%s ",
747                     etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
748                     etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
749                 break;
750         default:
751                 printf("(H) Unknown Ctrl Subtype");
752                 break;
753         }
754 }
755
756 static int
757 extract_header_length(u_int16_t fc)
758 {
759         switch (FC_TYPE(fc)) {
760         case T_MGMT:
761                 return MGMT_HDRLEN;
762         case T_CTRL:
763                 switch (FC_SUBTYPE(fc)) {
764                 case CTRL_PS_POLL:
765                         return CTRL_PS_POLL_HDRLEN;
766                 case CTRL_RTS:
767                         return CTRL_RTS_HDRLEN;
768                 case CTRL_CTS:
769                         return CTRL_CTS_HDRLEN;
770                 case CTRL_ACK:
771                         return CTRL_ACK_HDRLEN;
772                 case CTRL_CF_END:
773                         return CTRL_END_HDRLEN;
774                 case CTRL_END_ACK:
775                         return CTRL_END_ACK_HDRLEN;
776                 default:
777                         return 0;
778                 }
779         case T_DATA:
780                 return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
781         default:
782                 printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
783                 return 0;
784         }
785 }
786
787 /*
788  * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
789  * to point to the source and destination MAC addresses in any case if
790  * "srcp" and "dstp" aren't null.
791  */
792 static inline void
793 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
794     const u_int8_t **dstp)
795 {
796         if (vflag) {
797                 if (FC_MORE_DATA(fc))
798                         printf("More Data ");
799                 if (FC_MORE_FLAG(fc))
800                         printf("More Fragments ");
801                 if (FC_POWER_MGMT(fc))
802                         printf("Pwr Mgmt ");
803                 if (FC_RETRY(fc))
804                         printf("Retry ");
805                 if (FC_ORDER(fc))
806                         printf("Strictly Ordered ");
807                 if (FC_WEP(fc))
808                         printf("WEP Encrypted ");
809                 if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
810                         printf("%dus ",
811                             EXTRACT_LE_16BITS(
812                                 &((const struct mgmt_header_t *)p)->duration));
813         }
814
815         switch (FC_TYPE(fc)) {
816         case T_MGMT:
817                 mgmt_header_print(p, srcp, dstp);
818                 break;
819         case T_CTRL:
820                 ctrl_header_print(fc, p, srcp, dstp);
821                 break;
822         case T_DATA:
823                 data_header_print(fc, p, srcp, dstp);
824                 break;
825         default:
826                 printf("(header) unknown IEEE802.11 frame type (%d)",
827                     FC_TYPE(fc));
828                 *srcp = NULL;
829                 *dstp = NULL;
830                 break;
831         }
832 }
833
834 static u_int
835 ieee802_11_print(const u_char *p, u_int length, u_int caplen)
836 {
837         u_int16_t fc;
838         u_int hdrlen;
839         const u_int8_t *src, *dst;
840         u_short extracted_ethertype;
841
842         if (caplen < IEEE802_11_FC_LEN) {
843                 printf("[|802.11]");
844                 return caplen;
845         }
846
847         fc = EXTRACT_LE_16BITS(p);
848         hdrlen = extract_header_length(fc);
849
850         if (caplen < hdrlen) {
851                 printf("[|802.11]");
852                 return hdrlen;
853         }
854
855         ieee_802_11_hdr_print(fc, p, &src, &dst);
856
857         /*
858          * Go past the 802.11 header.
859          */
860         length -= hdrlen;
861         caplen -= hdrlen;
862         p += hdrlen;
863
864         switch (FC_TYPE(fc)) {
865         case T_MGMT:
866                 if (!mgmt_body_print(fc,
867                     (const struct mgmt_header_t *)(p - hdrlen), p)) {
868                         printf("[|802.11]");
869                         return hdrlen;
870                 }
871                 break;
872         case T_CTRL:
873                 if (!ctrl_body_print(fc, p - hdrlen)) {
874                         printf("[|802.11]");
875                         return hdrlen;
876                 }
877                 break;
878         case T_DATA:
879                 /* There may be a problem w/ AP not having this bit set */
880                 if (FC_WEP(fc)) {
881                         if (!wep_print(p)) {
882                                 printf("[|802.11]");
883                                 return hdrlen;
884                         }
885                 } else if (llc_print(p, length, caplen, dst, src,
886                     &extracted_ethertype) == 0) {
887                         /*
888                          * Some kinds of LLC packet we cannot
889                          * handle intelligently
890                          */
891                         if (!eflag)
892                                 ieee_802_11_hdr_print(fc, p - hdrlen, NULL,
893                                     NULL);
894                         if (extracted_ethertype)
895                                 printf("(LLC %s) ",
896                                     etherproto_string(
897                                         htons(extracted_ethertype)));
898                         if (!xflag && !qflag)
899                                 default_print(p, caplen);
900                 }
901                 break;
902         default:
903                 printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
904                 break;
905         }
906
907         return hdrlen;
908 }
909
910 /*
911  * This is the top level routine of the printer.  'p' points
912  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
913  * 'h->length' is the length of the packet off the wire, and 'h->caplen'
914  * is the number of bytes actually captured.
915  */
916 u_int
917 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
918 {
919         return ieee802_11_print(p, h->len, h->caplen);
920 }
921
922 static u_int
923 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
924 {
925         u_int32_t caphdr_len;
926
927         caphdr_len = EXTRACT_32BITS(p + 4);
928         if (caphdr_len < 8) {
929                 /*
930                  * Yow!  The capture header length is claimed not
931                  * to be large enough to include even the version
932                  * cookie or capture header length!
933                  */
934                 printf("[|802.11]");
935                 return caplen;
936         }
937
938         if (caplen < caphdr_len) {
939                 printf("[|802.11]");
940                 return caplen;
941         }
942
943         return caphdr_len + ieee802_11_print(p + caphdr_len,
944             length - caphdr_len, caplen - caphdr_len);
945 }
946
947 #define PRISM_HDR_LEN           144
948
949 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
950
951 /*
952  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
953  * containing information such as radio information, which we
954  * currently ignore.
955  *
956  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
957  * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
958  * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
959  * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
960  * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
961  * the first 4 bytes of the header are used to indicate which it is).
962  */
963 u_int
964 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
965 {
966         u_int caplen = h->caplen;
967         u_int length = h->len;
968
969         if (caplen < 4) {
970                 printf("[|802.11]");
971                 return caplen;
972         }
973
974         if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
975                 return ieee802_11_radio_print(p, length, caplen);
976
977         if (caplen < PRISM_HDR_LEN) {
978                 printf("[|802.11]");
979                 return caplen;
980         }
981
982         return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
983             length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN);
984 }
985
986 /*
987  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
988  * header, containing information such as radio information, which we
989  * currently ignore.
990  */
991 u_int
992 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
993 {
994         u_int caplen = h->caplen;
995         u_int length = h->len;
996
997         if (caplen < 8) {
998                 printf("[|802.11]");
999                 return caplen;
1000         }
1001
1002         return ieee802_11_radio_print(p, length, caplen);
1003 }