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