]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_11.c
Handle DLT_PRISM_HEADER captures that are really DLT_IEEE802_11_RADIO
[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.16 2002-12-17 09:13:45 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 data_header_print(u_int16_t fc, const u_char *p)
594 {
595 #define ADDR1 (p + 4)
596 #define ADDR2 (p + 10)
597 #define ADDR3 (p + 16)
598 #define ADDR4 (p + 24)
599
600 if (!FC_TO_DS(fc)) {
601 if (!FC_FROM_DS(fc))
602 printf("DA:%s SA:%s BSSID:%s ",
603 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
604 etheraddr_string(ADDR3));
605 else
606 printf("DA:%s BSSID:%s SA:%s ",
607 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
608 etheraddr_string(ADDR3));
609 } else {
610 if (!FC_FROM_DS(fc))
611 printf("BSSID:%s SA:%s DA:%s ",
612 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
613 etheraddr_string(ADDR3));
614 else
615 printf("RA:%s TA:%s DA:%s SA:%s ",
616 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
617 etheraddr_string(ADDR3), etheraddr_string(ADDR4));
618 }
619
620 #undef ADDR1
621 #undef ADDR2
622 #undef ADDR3
623 #undef ADDR4
624 }
625
626
627 static void mgmt_header_print(const u_char *p)
628 {
629 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
630
631 printf("BSSID:%s DA:%s SA:%s ",
632 etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
633 etheraddr_string((hp)->sa));
634 }
635
636 static void ctrl_header_print(u_int16_t fc, const u_char *p)
637 {
638 switch (FC_SUBTYPE(fc)) {
639 case CTRL_PS_POLL:
640 printf("BSSID:%s TA:%s ",
641 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
642 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
643 break;
644 case CTRL_RTS:
645 printf("RA:%s TA:%s ",
646 etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
647 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
648 break;
649 case CTRL_CTS:
650 printf("RA:%s ",
651 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
652 break;
653 case CTRL_ACK:
654 printf("RA:%s ",
655 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
656 break;
657 case CTRL_CF_END:
658 printf("RA:%s BSSID:%s ",
659 etheraddr_string(((const struct ctrl_end_t *)p)->ra),
660 etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
661 break;
662 case CTRL_END_ACK:
663 printf("RA:%s BSSID:%s ",
664 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
665 etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
666 break;
667 default:
668 printf("(H) Unknown Ctrl Subtype");
669 }
670 }
671
672 static int GetHeaderLength(u_int16_t fc)
673 {
674 int iLength=0;
675
676 switch (FC_TYPE(fc)) {
677 case T_MGMT:
678 iLength = MGMT_HEADER_LEN;
679 break;
680 case T_CTRL:
681 switch (FC_SUBTYPE(fc)) {
682 case CTRL_PS_POLL:
683 iLength = CTRL_PS_POLL_LEN;
684 break;
685 case CTRL_RTS:
686 iLength = CTRL_RTS_LEN;
687 break;
688 case CTRL_CTS:
689 iLength = CTRL_CTS_LEN;
690 break;
691 case CTRL_ACK:
692 iLength = CTRL_ACK_LEN;
693 break;
694 case CTRL_CF_END:
695 iLength = CTRL_END_LEN;
696 break;
697 case CTRL_END_ACK:
698 iLength = CTRL_END_ACK_LEN;
699 break;
700 default:
701 iLength = 0;
702 break;
703 }
704 break;
705 case T_DATA:
706 if (FC_TO_DS(fc) && FC_FROM_DS(fc))
707 iLength = 30;
708 else
709 iLength = 24;
710 break;
711 default:
712 printf("unknown IEEE802.11 frame type (%d)",
713 FC_TYPE(fc));
714 break;
715 }
716
717 return iLength;
718 }
719
720 /*
721 * Print the 802.11 MAC header
722 */
723 static inline void
724 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p)
725 {
726 switch (FC_TYPE(fc)) {
727 case T_MGMT:
728 mgmt_header_print(p);
729 break;
730
731 case T_CTRL:
732 ctrl_header_print(fc, p);
733 break;
734
735 case T_DATA:
736 data_header_print(fc, p);
737 break;
738
739 default:
740 printf("(header) unknown IEEE802.11 frame type (%d)",
741 FC_TYPE(fc));
742 break;
743 }
744 }
745
746 static void
747 ieee802_11_print(const u_char *p, u_int length, u_int caplen)
748 {
749 u_int16_t fc;
750 u_int HEADER_LENGTH;
751 u_short extracted_ethertype;
752
753 if (caplen < IEEE802_11_FC_LEN) {
754 printf("[|802.11]");
755 return;
756 }
757
758 fc = EXTRACT_LE_16BITS(p);
759 HEADER_LENGTH = GetHeaderLength(fc);
760
761 if (caplen < HEADER_LENGTH) {
762 printf("[|802.11]");
763 return;
764 }
765
766 if (eflag)
767 ieee_802_11_hdr_print(fc, p);
768
769 /*
770 * Some printers want to get back at the ethernet addresses,
771 * and/or check that they're not walking off the end of the packet.
772 * Rather than pass them all the way down, we set these globals.
773 */
774 packetp = p;
775 snapend = p + caplen;
776
777 length -= HEADER_LENGTH;
778 caplen -= HEADER_LENGTH;
779 p += HEADER_LENGTH;
780
781 switch (FC_TYPE(fc)) {
782 case T_MGMT:
783 if (!mgmt_body_print(fc, (const struct mgmt_header_t *)packetp,
784 p)) {
785 printf("[|802.11]");
786 return;
787 }
788 break;
789
790 case T_CTRL:
791 if (!ctrl_body_print(fc, p - HEADER_LENGTH)) {
792 printf("[|802.11]");
793 return;
794 }
795 break;
796
797 case T_DATA:
798 /* There may be a problem w/ AP not having this bit set */
799 if (FC_WEP(fc)) {
800 if (!wep_print(p)) {
801 printf("[|802.11]");
802 return;
803 }
804 } else {
805 if (llc_print(p, length, caplen, packetp + 10,
806 packetp + 4, &extracted_ethertype) == 0) {
807 /*
808 * Some kinds of LLC packet we cannot
809 * handle intelligently
810 */
811 if (!eflag)
812 ieee_802_11_hdr_print(fc, p - HEADER_LENGTH);
813 if (extracted_ethertype) {
814 printf("(LLC %s) ",
815 etherproto_string(htons(extracted_ethertype)));
816 }
817 if (!xflag && !qflag)
818 default_print(p, caplen);
819 }
820 }
821 break;
822
823 default:
824 printf("(body) unhandled IEEE802.11 frame type (%d)",
825 FC_TYPE(fc));
826 break;
827 }
828
829 if (xflag)
830 default_print(p, caplen);
831 }
832
833 /*
834 * This is the top level routine of the printer. 'p' points
835 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
836 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
837 * is the number of bytes actually captured.
838 */
839 void
840 ieee802_11_if_print(u_char *user _U_, const struct pcap_pkthdr *h, const u_char *p)
841 {
842 u_int caplen = h->caplen;
843 u_int length = h->len;
844
845 ++infodelay;
846 ts_print(&h->ts);
847
848 ieee802_11_print(p, length, caplen);
849
850 putchar('\n');
851 --infodelay;
852 if (infoprint)
853 info(0);
854 }
855
856 static void
857 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
858 {
859 u_int32_t caphdr_len;
860
861 caphdr_len = EXTRACT_32BITS(p + 4);
862 if (caphdr_len < 8) {
863 /*
864 * Yow! The capture header length is claimed not
865 * to be large enough to include even the version
866 * cookie or capture header length!
867 */
868 printf("[|802.11]");
869 return;
870 }
871
872 if (caplen < caphdr_len) {
873 printf("[|802.11]");
874 return;
875 }
876
877 ieee802_11_print(p + caphdr_len, length - caphdr_len,
878 caplen - caphdr_len);
879 }
880
881 #define PRISM_HDR_LEN 144
882
883 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
884
885 /*
886 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
887 * containing information such as radio information, which we
888 * currently ignore.
889 *
890 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
891 * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
892 * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
893 * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
894 * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
895 * the first 4 bytes of the header are used to indicate which it is).
896 */
897 void
898 prism_if_print(u_char *user _U_, const struct pcap_pkthdr *h, const u_char *p)
899 {
900 u_int caplen = h->caplen;
901 u_int length = h->len;
902 u_int32_t msgcode;
903
904 ++infodelay;
905 ts_print(&h->ts);
906
907 if (caplen < 4) {
908 printf("[|802.11]");
909 goto out;
910 }
911
912 msgcode = EXTRACT_32BITS(p);
913 if (msgcode == WLANCAP_MAGIC_COOKIE_V1)
914 ieee802_11_radio_print(p, length, caplen);
915 else {
916 if (caplen < PRISM_HDR_LEN) {
917 printf("[|802.11]");
918 goto out;
919 }
920
921 ieee802_11_print(p + PRISM_HDR_LEN, length - PRISM_HDR_LEN,
922 caplen - PRISM_HDR_LEN);
923 }
924
925 out:
926 putchar('\n');
927 --infodelay;
928 if (infoprint)
929 info(0);
930 }
931
932 /*
933 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
934 * header, containing information such as radio information, which we
935 * currently ignore.
936 */
937 void
938 ieee802_11_radio_if_print(u_char *user _U_, const struct pcap_pkthdr *h,
939 const u_char *p)
940 {
941 u_int caplen = h->caplen;
942 u_int length = h->len;
943
944 ++infodelay;
945 ts_print(&h->ts);
946
947 if (caplen < 8) {
948 printf("[|802.11]");
949 goto out;
950 }
951
952 ieee802_11_radio_print(p, length, caplen);
953
954 out:
955 putchar('\n');
956 --infodelay;
957 if (infoprint)
958 info(0);
959 }