]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_11.c
Stylistic cleanups, from David Young.
[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[] =
25 "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.21 2003-07-22 17:35:04 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("%s (", subtype_text[FC_SUBTYPE(fc)]);
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("%s (", subtype_text[FC_SUBTYPE(fc)]);
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("%s AID(%x) :%s: %s", subtype_text[FC_SUBTYPE(fc)],
306 ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
307 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
308 (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a"));
309
310 return 1;
311 }
312
313 static int
314 handle_reassoc_request(u_int16_t fc, const u_char *p)
315 {
316 struct mgmt_body_t pbody;
317 int offset = 0;
318
319 memset(&pbody, 0, sizeof(pbody));
320
321 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
322 IEEE802_11_AP_LEN))
323 return 0;
324 pbody.capability_info = EXTRACT_LE_16BITS(p);
325 offset += IEEE802_11_CAPINFO_LEN;
326 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
327 offset += IEEE802_11_LISTENINT_LEN;
328 memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
329 offset += IEEE802_11_AP_LEN;
330
331 if (!parse_elements(&pbody, p, offset))
332 return 0;
333
334 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
335 fn_print(pbody.ssid.ssid, NULL);
336 printf(") AP : %s", etheraddr_string( pbody.ap ));
337
338 return 1;
339 }
340
341 static int
342 handle_reassoc_response(u_int16_t fc, const u_char *p)
343 {
344 /* Same as a Association Reponse */
345 return handle_assoc_response(fc, p);
346 }
347
348 static int
349 handle_probe_request(u_int16_t fc, const u_char *p)
350 {
351 struct mgmt_body_t pbody;
352 int offset = 0;
353
354 memset(&pbody, 0, sizeof(pbody));
355
356 if (!parse_elements(&pbody, p, offset))
357 return 0;
358
359 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
360 fn_print(pbody.ssid.ssid, NULL);
361 printf(")");
362 PRINT_RATES(pbody);
363
364 return 1;
365 }
366
367 static int
368 handle_probe_response(u_int16_t fc, const u_char *p)
369 {
370 struct mgmt_body_t pbody;
371 int offset = 0;
372
373 memset(&pbody, 0, sizeof(pbody));
374
375 if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
376 IEEE802_11_CAPINFO_LEN))
377 return 0;
378
379 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
380 offset += IEEE802_11_TSTAMP_LEN;
381 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
382 offset += IEEE802_11_BCNINT_LEN;
383 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
384 offset += IEEE802_11_CAPINFO_LEN;
385
386 if (!parse_elements(&pbody, p, offset))
387 return 0;
388
389 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
390 fn_print(pbody.ssid.ssid, NULL);
391 printf(") ");
392 PRINT_RATES(pbody);
393 printf(" CH: %u%s", pbody.ds.channel,
394 CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
395
396 return 1;
397 }
398
399 static int
400 handle_atim(void)
401 {
402 /* the frame body for ATIM is null. */
403 printf("ATIM");
404 return 1;
405 }
406
407 static int
408 handle_disassoc(u_int16_t fc, const u_char *p)
409 {
410 struct mgmt_body_t pbody;
411
412 memset(&pbody, 0, sizeof(pbody));
413
414 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
415 return 0;
416 pbody.reason_code = EXTRACT_LE_16BITS(p);
417
418 printf("%s: %s", subtype_text[FC_SUBTYPE(fc)],
419 (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
420 : "Reserved" );
421
422 return 1;
423 }
424
425 static int
426 handle_auth(u_int16_t fc, const u_char *p)
427 {
428 struct mgmt_body_t pbody;
429 int offset = 0;
430
431 memset(&pbody, 0, sizeof(pbody));
432
433 if (!TTEST2(*p, 6))
434 return 0;
435 pbody.auth_alg = EXTRACT_LE_16BITS(p);
436 offset += 2;
437 pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
438 offset += 2;
439 pbody.status_code = EXTRACT_LE_16BITS(p + offset);
440 offset += 2;
441
442 if (!parse_elements(&pbody, p, offset))
443 return 0;
444
445 if ((pbody.auth_alg == 1) &&
446 ((pbody.auth_trans_seq_num == 2) ||
447 (pbody.auth_trans_seq_num == 3))) {
448 printf("%s (%s)-%x [Challenge Text] %s",
449 subtype_text[FC_SUBTYPE(fc)],
450 (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg]
451 : "Reserved",
452 pbody.auth_trans_seq_num,
453 ((pbody.auth_trans_seq_num % 2)
454 ? ((pbody.status_code < 19)
455 ? status_text[pbody.status_code]
456 : "n/a") : ""));
457 return 1;
458 }
459 printf("%s (%s)-%x: %s",
460 subtype_text[FC_SUBTYPE(fc)],
461 (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg] : "Reserved",
462 pbody.auth_trans_seq_num,
463 (pbody.auth_trans_seq_num % 2)
464 ? ((pbody.status_code < 19) ? status_text[pbody.status_code]
465 : "n/a")
466 : "");
467
468 return 1;
469 }
470
471 static int
472 handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh,
473 const u_char *p)
474 {
475 struct mgmt_body_t pbody;
476 int offset = 0;
477 const char *reason = NULL;
478
479 memset(&pbody, 0, sizeof(pbody));
480
481 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
482 return 0;
483 pbody.reason_code = EXTRACT_LE_16BITS(p);
484 offset += IEEE802_11_REASON_LEN;
485
486 reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
487 : "Reserved";
488
489 if (eflag) {
490 printf("%s: %s", subtype_text[FC_SUBTYPE(fc)], reason);
491 } else {
492 printf("%s (%s): %s",
493 subtype_text[FC_SUBTYPE(fc)], etheraddr_string(pmh->sa),
494 reason);
495 }
496 return 1;
497 }
498
499
500 /*********************************************************************************
501 * Print Body funcs
502 *********************************************************************************/
503
504
505 static int
506 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
507 const u_char *p)
508 {
509 switch (FC_SUBTYPE(fc)) {
510 case ST_ASSOC_REQUEST:
511 return handle_assoc_request(fc, p);
512 case ST_ASSOC_RESPONSE:
513 return handle_assoc_response(fc, p);
514 case ST_REASSOC_REQUEST:
515 return handle_reassoc_request(fc, p);
516 case ST_REASSOC_RESPONSE:
517 return handle_reassoc_response(fc, p);
518 case ST_PROBE_REQUEST:
519 return handle_probe_request(fc, p);
520 case ST_PROBE_RESPONSE:
521 return handle_probe_response(fc, p);
522 case ST_BEACON:
523 return handle_beacon(fc, p);
524 case ST_ATIM:
525 return handle_atim();
526 case ST_DISASSOC:
527 return handle_disassoc(fc, p);
528 case ST_AUTH:
529 if (!TTEST2(*p, 3))
530 return 0;
531 if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
532 printf("Authentication (Shared-Key)-3 ");
533 return wep_print(p);
534 }
535 return handle_auth(fc, p);
536 case ST_DEAUTH:
537 return handle_deauth(fc, pmh, p);
538 break;
539 default:
540 printf("Unhandled Managment subtype(%x)",
541 FC_SUBTYPE(fc));
542 return 1;
543 }
544 }
545
546
547 /*********************************************************************************
548 * Handles printing all the control frame types
549 *********************************************************************************/
550
551 static int
552 ctrl_body_print(u_int16_t fc, const u_char *p)
553 {
554 switch (FC_SUBTYPE(fc)) {
555 case CTRL_PS_POLL:
556 if (!TTEST2(*p, CTRL_PS_POLL_LEN))
557 return 0;
558 printf("Power Save-Poll AID(%x)",
559 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
560 break;
561 case CTRL_RTS:
562 if (!TTEST2(*p, CTRL_RTS_LEN))
563 return 0;
564 printf("Request-To-Send");
565 if (!eflag)
566 printf(" TA:%s ",
567 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
568 break;
569 case CTRL_CTS:
570 if (!TTEST2(*p, CTRL_CTS_LEN))
571 return 0;
572 printf("Clear-To-Send");
573 if (!eflag)
574 printf(" RA:%s ",
575 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
576 break;
577 case CTRL_ACK:
578 if (!TTEST2(*p, CTRL_ACK_LEN))
579 return 0;
580 printf("Acknowledgment");
581 if (!eflag)
582 printf(" RA:%s ",
583 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
584 break;
585 case CTRL_CF_END:
586 if (!TTEST2(*p, CTRL_END_LEN))
587 return 0;
588 printf("CF-End");
589 if (!eflag)
590 printf(" RA:%s ",
591 etheraddr_string(((const struct ctrl_end_t *)p)->ra));
592 break;
593 case CTRL_END_ACK:
594 if (!TTEST2(*p, CTRL_END_ACK_LEN))
595 return 0;
596 printf("CF-End+CF-Ack");
597 if (!eflag)
598 printf(" RA:%s ",
599 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
600 break;
601 default:
602 printf("Unknown Ctrl Subtype");
603 }
604 return 1;
605 }
606
607 /*
608 * Print Header funcs
609 */
610
611 /*
612 * Data Frame - Address field contents
613 *
614 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
615 * 0 | 0 | DA | SA | BSSID | n/a
616 * 0 | 1 | DA | BSSID | SA | n/a
617 * 1 | 0 | BSSID | SA | DA | n/a
618 * 1 | 1 | RA | TA | DA | SA
619 */
620
621 static void
622 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
623 const u_int8_t **dstp)
624 {
625 switch (FC_SUBTYPE(fc)) {
626 case DATA_DATA:
627 case DATA_NODATA:
628 break;
629 case DATA_DATA_CF_ACK:
630 case DATA_NODATA_CF_ACK:
631 printf("CF Ack ");
632 break;
633 case DATA_DATA_CF_POLL:
634 case DATA_NODATA_CF_POLL:
635 printf("CF Poll ");
636 break;
637 case DATA_DATA_CF_ACK_POLL:
638 case DATA_NODATA_CF_ACK_POLL:
639 printf("CF Ack/Poll ");
640 break;
641 }
642
643 #define ADDR1 (p + 4)
644 #define ADDR2 (p + 10)
645 #define ADDR3 (p + 16)
646 #define ADDR4 (p + 24)
647
648 if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
649 if (srcp != NULL)
650 *srcp = ADDR2;
651 if (dstp != NULL)
652 *dstp = ADDR1;
653 if (!eflag)
654 return;
655 printf("DA:%s SA:%s BSSID:%s ",
656 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
657 etheraddr_string(ADDR3));
658 } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
659 if (srcp != NULL)
660 *srcp = ADDR3;
661 if (dstp != NULL)
662 *dstp = ADDR1;
663 if (!eflag)
664 return;
665 printf("DA:%s BSSID:%s SA:%s ",
666 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
667 etheraddr_string(ADDR3));
668 } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
669 if (srcp != NULL)
670 *srcp = ADDR2;
671 if (dstp != NULL)
672 *dstp = ADDR3;
673 if (!eflag)
674 return;
675 printf("BSSID:%s SA:%s DA:%s ",
676 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
677 etheraddr_string(ADDR3));
678 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
679 if (srcp != NULL)
680 *srcp = ADDR4;
681 if (dstp != NULL)
682 *dstp = ADDR3;
683 if (!eflag)
684 return;
685 printf("RA:%s TA:%s DA:%s SA:%s ",
686 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
687 etheraddr_string(ADDR3), etheraddr_string(ADDR4));
688 }
689
690 #undef ADDR1
691 #undef ADDR2
692 #undef ADDR3
693 #undef ADDR4
694 }
695
696 static void
697 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
698 const u_int8_t **dstp)
699 {
700 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
701
702 if (srcp != NULL)
703 *srcp = hp->sa;
704 if (dstp != NULL)
705 *dstp = hp->da;
706 if (!eflag)
707 return;
708
709 printf("BSSID:%s DA:%s SA:%s ",
710 etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
711 etheraddr_string((hp)->sa));
712 }
713
714 static void
715 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
716 const u_int8_t **dstp)
717 {
718 if (srcp != NULL)
719 *srcp = NULL;
720 if (dstp != NULL)
721 *dstp = NULL;
722 if (!eflag)
723 return;
724
725 switch (FC_SUBTYPE(fc)) {
726 case CTRL_PS_POLL:
727 printf("BSSID:%s TA:%s ",
728 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
729 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
730 break;
731 case CTRL_RTS:
732 printf("RA:%s TA:%s ",
733 etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
734 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
735 break;
736 case CTRL_CTS:
737 printf("RA:%s ",
738 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
739 break;
740 case CTRL_ACK:
741 printf("RA:%s ",
742 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
743 break;
744 case CTRL_CF_END:
745 printf("RA:%s BSSID:%s ",
746 etheraddr_string(((const struct ctrl_end_t *)p)->ra),
747 etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
748 break;
749 case CTRL_END_ACK:
750 printf("RA:%s BSSID:%s ",
751 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
752 etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
753 break;
754 default:
755 printf("(H) Unknown Ctrl Subtype");
756 break;
757 }
758 }
759
760 static int
761 extract_header_length(u_int16_t fc)
762 {
763 switch (FC_TYPE(fc)) {
764 case T_MGMT:
765 return MGMT_HEADER_LEN;
766 case T_CTRL:
767 switch (FC_SUBTYPE(fc)) {
768 case CTRL_PS_POLL:
769 return CTRL_PS_POLL_LEN;
770 case CTRL_RTS:
771 return CTRL_RTS_LEN;
772 case CTRL_CTS:
773 return CTRL_CTS_LEN;
774 case CTRL_ACK:
775 return CTRL_ACK_LEN;
776 case CTRL_CF_END:
777 return CTRL_END_LEN;
778 case CTRL_END_ACK:
779 return CTRL_END_ACK_LEN;
780 default:
781 return 0;
782 }
783 case T_DATA:
784 return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
785 default:
786 printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
787 return 0;
788 }
789 }
790
791 /*
792 * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
793 * to point to the source and destination MAC addresses in any case if
794 * "srcp" and "dstp" aren't null.
795 */
796 static inline void
797 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
798 const u_int8_t **dstp)
799 {
800 if (vflag) {
801 if (FC_MORE_DATA(fc))
802 printf("More Data ");
803 if (FC_MORE_FLAG(fc))
804 printf("More Fragments ");
805 if (FC_POWER_MGMT(fc))
806 printf("Pwr Mgmt ");
807 if (FC_RETRY(fc))
808 printf("Retry ");
809 if (FC_ORDER(fc))
810 printf("Strictly Ordered ");
811 if (FC_WEP(fc))
812 printf("WEP Encrypted ");
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 }