]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_11.c
Print the subtype of management frames *before* parsing the body, so
[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.26 2003-11-27 02:18:53 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 "RESERVED",
68 "RESERVED",
69 "Beacon",
70 "ATIM",
71 "Disassociation",
72 "Authentication",
73 "DeAuthentication",
74 "RESERVED",
75 "RESERVED"
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(u_int16_t fc, 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(u_int16_t fc, 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(u_int16_t fc, 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(u_int16_t fc, 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(u_int16_t fc, const u_char *p)
342 {
343 /* Same as a Association Reponse */
344 return handle_assoc_response(fc, p);
345 }
346
347 static int
348 handle_probe_request(u_int16_t fc, 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(u_int16_t fc, 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(u_int16_t fc, 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(u_int16_t fc, 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(u_int16_t fc, const struct mgmt_header_t *pmh,
469 const u_char *p)
470 {
471 struct mgmt_body_t pbody;
472 int offset = 0;
473 const char *reason = NULL;
474
475 memset(&pbody, 0, sizeof(pbody));
476
477 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
478 return 0;
479 pbody.reason_code = EXTRACT_LE_16BITS(p);
480 offset += IEEE802_11_REASON_LEN;
481
482 reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
483 : "Reserved";
484
485 if (eflag) {
486 printf(": %s", reason);
487 } else {
488 printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
489 }
490 return 1;
491 }
492
493
494 /*********************************************************************************
495 * Print Body funcs
496 *********************************************************************************/
497
498
499 static int
500 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
501 const u_char *p)
502 {
503 printf("%s", subtype_text[FC_SUBTYPE(fc)]);
504
505 switch (FC_SUBTYPE(fc)) {
506 case ST_ASSOC_REQUEST:
507 return handle_assoc_request(fc, p);
508 case ST_ASSOC_RESPONSE:
509 return handle_assoc_response(fc, p);
510 case ST_REASSOC_REQUEST:
511 return handle_reassoc_request(fc, p);
512 case ST_REASSOC_RESPONSE:
513 return handle_reassoc_response(fc, p);
514 case ST_PROBE_REQUEST:
515 return handle_probe_request(fc, p);
516 case ST_PROBE_RESPONSE:
517 return handle_probe_response(fc, p);
518 case ST_BEACON:
519 return handle_beacon(fc, p);
520 case ST_ATIM:
521 return handle_atim();
522 case ST_DISASSOC:
523 return handle_disassoc(fc, p);
524 case ST_AUTH:
525 if (!TTEST2(*p, 3))
526 return 0;
527 if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
528 printf("Authentication (Shared-Key)-3 ");
529 return wep_print(p);
530 }
531 return handle_auth(fc, p);
532 case ST_DEAUTH:
533 return handle_deauth(fc, pmh, p);
534 break;
535 default:
536 printf("Unhandled Management subtype(%x)",
537 FC_SUBTYPE(fc));
538 return 1;
539 }
540 }
541
542
543 /*********************************************************************************
544 * Handles printing all the control frame types
545 *********************************************************************************/
546
547 static int
548 ctrl_body_print(u_int16_t fc, const u_char *p)
549 {
550 switch (FC_SUBTYPE(fc)) {
551 case CTRL_PS_POLL:
552 printf("Power Save-Poll");
553 if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
554 return 0;
555 printf(" AID(%x)",
556 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
557 break;
558 case CTRL_RTS:
559 printf("Request-To-Send");
560 if (!TTEST2(*p, CTRL_RTS_HDRLEN))
561 return 0;
562 if (!eflag)
563 printf(" TA:%s ",
564 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
565 break;
566 case CTRL_CTS:
567 printf("Clear-To-Send");
568 if (!TTEST2(*p, CTRL_CTS_HDRLEN))
569 return 0;
570 if (!eflag)
571 printf(" RA:%s ",
572 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
573 break;
574 case CTRL_ACK:
575 printf("Acknowledgment");
576 if (!TTEST2(*p, CTRL_ACK_HDRLEN))
577 return 0;
578 if (!eflag)
579 printf(" RA:%s ",
580 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
581 break;
582 case CTRL_CF_END:
583 printf("CF-End");
584 if (!TTEST2(*p, CTRL_END_HDRLEN))
585 return 0;
586 if (!eflag)
587 printf(" RA:%s ",
588 etheraddr_string(((const struct ctrl_end_t *)p)->ra));
589 break;
590 case CTRL_END_ACK:
591 printf("CF-End+CF-Ack");
592 if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
593 return 0;
594 if (!eflag)
595 printf(" RA:%s ",
596 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
597 break;
598 default:
599 printf("Unknown Ctrl Subtype");
600 }
601 return 1;
602 }
603
604 /*
605 * Print Header funcs
606 */
607
608 /*
609 * Data Frame - Address field contents
610 *
611 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
612 * 0 | 0 | DA | SA | BSSID | n/a
613 * 0 | 1 | DA | BSSID | SA | n/a
614 * 1 | 0 | BSSID | SA | DA | n/a
615 * 1 | 1 | RA | TA | DA | SA
616 */
617
618 static void
619 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
620 const u_int8_t **dstp)
621 {
622 switch (FC_SUBTYPE(fc)) {
623 case DATA_DATA:
624 case DATA_NODATA:
625 break;
626 case DATA_DATA_CF_ACK:
627 case DATA_NODATA_CF_ACK:
628 printf("CF Ack ");
629 break;
630 case DATA_DATA_CF_POLL:
631 case DATA_NODATA_CF_POLL:
632 printf("CF Poll ");
633 break;
634 case DATA_DATA_CF_ACK_POLL:
635 case DATA_NODATA_CF_ACK_POLL:
636 printf("CF Ack/Poll ");
637 break;
638 }
639
640 #define ADDR1 (p + 4)
641 #define ADDR2 (p + 10)
642 #define ADDR3 (p + 16)
643 #define ADDR4 (p + 24)
644
645 if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
646 if (srcp != NULL)
647 *srcp = ADDR2;
648 if (dstp != NULL)
649 *dstp = ADDR1;
650 if (!eflag)
651 return;
652 printf("DA:%s SA:%s BSSID:%s ",
653 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
654 etheraddr_string(ADDR3));
655 } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
656 if (srcp != NULL)
657 *srcp = ADDR3;
658 if (dstp != NULL)
659 *dstp = ADDR1;
660 if (!eflag)
661 return;
662 printf("DA:%s BSSID:%s SA:%s ",
663 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
664 etheraddr_string(ADDR3));
665 } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
666 if (srcp != NULL)
667 *srcp = ADDR2;
668 if (dstp != NULL)
669 *dstp = ADDR3;
670 if (!eflag)
671 return;
672 printf("BSSID:%s SA:%s DA:%s ",
673 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
674 etheraddr_string(ADDR3));
675 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
676 if (srcp != NULL)
677 *srcp = ADDR4;
678 if (dstp != NULL)
679 *dstp = ADDR3;
680 if (!eflag)
681 return;
682 printf("RA:%s TA:%s DA:%s SA:%s ",
683 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
684 etheraddr_string(ADDR3), etheraddr_string(ADDR4));
685 }
686
687 #undef ADDR1
688 #undef ADDR2
689 #undef ADDR3
690 #undef ADDR4
691 }
692
693 static void
694 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
695 const u_int8_t **dstp)
696 {
697 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
698
699 if (srcp != NULL)
700 *srcp = hp->sa;
701 if (dstp != NULL)
702 *dstp = hp->da;
703 if (!eflag)
704 return;
705
706 printf("BSSID:%s DA:%s SA:%s ",
707 etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
708 etheraddr_string((hp)->sa));
709 }
710
711 static void
712 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
713 const u_int8_t **dstp)
714 {
715 if (srcp != NULL)
716 *srcp = NULL;
717 if (dstp != NULL)
718 *dstp = NULL;
719 if (!eflag)
720 return;
721
722 switch (FC_SUBTYPE(fc)) {
723 case CTRL_PS_POLL:
724 printf("BSSID:%s TA:%s ",
725 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
726 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
727 break;
728 case CTRL_RTS:
729 printf("RA:%s TA:%s ",
730 etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
731 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
732 break;
733 case CTRL_CTS:
734 printf("RA:%s ",
735 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
736 break;
737 case CTRL_ACK:
738 printf("RA:%s ",
739 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
740 break;
741 case CTRL_CF_END:
742 printf("RA:%s BSSID:%s ",
743 etheraddr_string(((const struct ctrl_end_t *)p)->ra),
744 etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
745 break;
746 case CTRL_END_ACK:
747 printf("RA:%s BSSID:%s ",
748 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
749 etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
750 break;
751 default:
752 printf("(H) Unknown Ctrl Subtype");
753 break;
754 }
755 }
756
757 static int
758 extract_header_length(u_int16_t fc)
759 {
760 switch (FC_TYPE(fc)) {
761 case T_MGMT:
762 return MGMT_HDRLEN;
763 case T_CTRL:
764 switch (FC_SUBTYPE(fc)) {
765 case CTRL_PS_POLL:
766 return CTRL_PS_POLL_HDRLEN;
767 case CTRL_RTS:
768 return CTRL_RTS_HDRLEN;
769 case CTRL_CTS:
770 return CTRL_CTS_HDRLEN;
771 case CTRL_ACK:
772 return CTRL_ACK_HDRLEN;
773 case CTRL_CF_END:
774 return CTRL_END_HDRLEN;
775 case CTRL_END_ACK:
776 return CTRL_END_ACK_HDRLEN;
777 default:
778 return 0;
779 }
780 case T_DATA:
781 return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
782 default:
783 printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
784 return 0;
785 }
786 }
787
788 /*
789 * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
790 * to point to the source and destination MAC addresses in any case if
791 * "srcp" and "dstp" aren't null.
792 */
793 static inline void
794 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
795 const u_int8_t **dstp)
796 {
797 if (vflag) {
798 if (FC_MORE_DATA(fc))
799 printf("More Data ");
800 if (FC_MORE_FLAG(fc))
801 printf("More Fragments ");
802 if (FC_POWER_MGMT(fc))
803 printf("Pwr Mgmt ");
804 if (FC_RETRY(fc))
805 printf("Retry ");
806 if (FC_ORDER(fc))
807 printf("Strictly Ordered ");
808 if (FC_WEP(fc))
809 printf("WEP Encrypted ");
810 if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
811 printf("%dus ",
812 EXTRACT_LE_16BITS(
813 &((const struct mgmt_header_t *)p)->duration));
814 }
815
816 switch (FC_TYPE(fc)) {
817 case T_MGMT:
818 mgmt_header_print(p, srcp, dstp);
819 break;
820 case T_CTRL:
821 ctrl_header_print(fc, p, srcp, dstp);
822 break;
823 case T_DATA:
824 data_header_print(fc, p, srcp, dstp);
825 break;
826 default:
827 printf("(header) unknown IEEE802.11 frame type (%d)",
828 FC_TYPE(fc));
829 *srcp = NULL;
830 *dstp = NULL;
831 break;
832 }
833 }
834
835 static u_int
836 ieee802_11_print(const u_char *p, u_int length, u_int caplen)
837 {
838 u_int16_t fc;
839 u_int hdrlen;
840 const u_int8_t *src, *dst;
841 u_short extracted_ethertype;
842
843 if (caplen < IEEE802_11_FC_LEN) {
844 printf("[|802.11]");
845 return caplen;
846 }
847
848 fc = EXTRACT_LE_16BITS(p);
849 hdrlen = extract_header_length(fc);
850
851 if (caplen < hdrlen) {
852 printf("[|802.11]");
853 return hdrlen;
854 }
855
856 ieee_802_11_hdr_print(fc, p, &src, &dst);
857
858 /*
859 * Go past the 802.11 header.
860 */
861 length -= hdrlen;
862 caplen -= hdrlen;
863 p += hdrlen;
864
865 switch (FC_TYPE(fc)) {
866 case T_MGMT:
867 if (!mgmt_body_print(fc,
868 (const struct mgmt_header_t *)(p - hdrlen), p)) {
869 printf("[|802.11]");
870 return hdrlen;
871 }
872 break;
873 case T_CTRL:
874 if (!ctrl_body_print(fc, p - hdrlen)) {
875 printf("[|802.11]");
876 return hdrlen;
877 }
878 break;
879 case T_DATA:
880 /* There may be a problem w/ AP not having this bit set */
881 if (FC_WEP(fc)) {
882 if (!wep_print(p)) {
883 printf("[|802.11]");
884 return hdrlen;
885 }
886 } else if (llc_print(p, length, caplen, dst, src,
887 &extracted_ethertype) == 0) {
888 /*
889 * Some kinds of LLC packet we cannot
890 * handle intelligently
891 */
892 if (!eflag)
893 ieee_802_11_hdr_print(fc, p - hdrlen, NULL,
894 NULL);
895 if (extracted_ethertype)
896 printf("(LLC %s) ",
897 etherproto_string(
898 htons(extracted_ethertype)));
899 if (!xflag && !qflag)
900 default_print(p, caplen);
901 }
902 break;
903 default:
904 printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
905 break;
906 }
907
908 return hdrlen;
909 }
910
911 /*
912 * This is the top level routine of the printer. 'p' points
913 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
914 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
915 * is the number of bytes actually captured.
916 */
917 u_int
918 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
919 {
920 return ieee802_11_print(p, h->len, h->caplen);
921 }
922
923 static u_int
924 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
925 {
926 u_int32_t caphdr_len;
927
928 caphdr_len = EXTRACT_32BITS(p + 4);
929 if (caphdr_len < 8) {
930 /*
931 * Yow! The capture header length is claimed not
932 * to be large enough to include even the version
933 * cookie or capture header length!
934 */
935 printf("[|802.11]");
936 return caplen;
937 }
938
939 if (caplen < caphdr_len) {
940 printf("[|802.11]");
941 return caplen;
942 }
943
944 return caphdr_len + ieee802_11_print(p + caphdr_len,
945 length - caphdr_len, caplen - caphdr_len);
946 }
947
948 #define PRISM_HDR_LEN 144
949
950 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
951
952 /*
953 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
954 * containing information such as radio information, which we
955 * currently ignore.
956 *
957 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
958 * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
959 * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
960 * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
961 * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
962 * the first 4 bytes of the header are used to indicate which it is).
963 */
964 u_int
965 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
966 {
967 u_int caplen = h->caplen;
968 u_int length = h->len;
969
970 if (caplen < 4) {
971 printf("[|802.11]");
972 return caplen;
973 }
974
975 if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
976 return ieee802_11_radio_print(p, length, caplen);
977
978 if (caplen < PRISM_HDR_LEN) {
979 printf("[|802.11]");
980 return caplen;
981 }
982
983 return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
984 length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN);
985 }
986
987 /*
988 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
989 * header, containing information such as radio information, which we
990 * currently ignore.
991 */
992 u_int
993 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
994 {
995 u_int caplen = h->caplen;
996 u_int length = h->len;
997
998 if (caplen < 8) {
999 printf("[|802.11]");
1000 return caplen;
1001 }
1002
1003 return ieee802_11_radio_print(p, length, caplen);
1004 }