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