]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_11.c
Get rid of unneeded includes of <netinet/in_systm.h> and <netinet/ip.h>.
[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.7 2002-05-13 08:30:19 guy Exp $ (LBL)";
26 #endif
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/socket.h>
35
36 #include <netinet/in.h>
37
38 #include <stdio.h>
39 #include <pcap.h>
40 #include <string.h>
41
42 #include "interface.h"
43 #include "addrtoname.h"
44 #include "ethertype.h"
45
46 #include "extract.h"
47
48 #include "ieee802_11.h"
49
50 #define PRINT_RATES(p) \
51 do { \
52 int z; \
53 char *sep = " ["; \
54 for (z = 0; z < p.rates.length ; z++) { \
55 printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \
56 sep = " "; \
57 } \
58 if (p.rates.length != 0) \
59 printf(" Mbit]"); \
60 } while (0)
61
62 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
63 static const char *subtype_text[]={
64 "Assoc Request",
65 "Assoc Response",
66 "ReAssoc Request",
67 "ReAssoc Response",
68 "Probe Request",
69 "Probe Response",
70 "RESERVED",
71 "RESERVED",
72 "Beacon",
73 "ATIM",
74 "Disassociation",
75 "Authentication",
76 "DeAuthentication",
77 "RESERVED",
78 "RESERVED"
79 };
80
81 static const char *status_text[] = {
82 "Succesful", /* 0 */
83 "Unspecified failure", /* 1 */
84 "Reserved", /* 2 */
85 "Reserved", /* 3 */
86 "Reserved", /* 4 */
87 "Reserved", /* 5 */
88 "Reserved", /* 6 */
89 "Reserved", /* 7 */
90 "Reserved", /* 8 */
91 "Reserved", /* 9 */
92 "Cannot Support all requested capabilities in the Capability Information field", /* 10 */
93 "Reassociation denied due to inability to confirm that association exists", /* 11 */
94 "Association denied due to reason outside the scope of the standard", /* 12 */
95 "Responding station does not support the specified authentication algorithm ", /* 13 */
96 "Received an Authentication frame with authentication transaction " \
97 "sequence number out of expected sequence", /* 14 */
98 "Authentication rejected because of challenge failure", /* 15 */
99 "Authentication rejected due to timeout waiting for next frame in sequence", /* 16 */
100 "Association denied because AP is unable to handle additional associated stations", /* 17 */
101 "Association denied due to requesting station not supporting all of the " \
102 "data rates in BSSBasicRateSet parameter", /* 18 */
103 NULL
104 };
105
106 static const char *reason_text[] = {
107 "Reserved", /* 0 */
108 "Unspecified reason", /* 1 */
109 "Previous authentication no longer valid", /* 2 */
110 "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
111 "Disassociated due to inactivity", /* 4 */
112 "Disassociated because AP is unable to handle all currently associated stations", /* 5 */
113 "Class 2 frame receivedfrom nonauthenticated station", /* 6 */
114 "Class 3 frame received from nonassociated station", /* 7 */
115 "Disassociated because sending station is leaving (or has left) BSS", /* 8 */
116 "Station requesting (re)association is not authenticated with responding station", /* 9 */
117 NULL
118 };
119
120 static int wep_print(const u_char *p,u_int length)
121 {
122 u_int32_t iv;
123
124 if (!TTEST2(*p, 4))
125 return 0;
126 iv = EXTRACT_LE_32BITS(p);
127
128 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
129 IV_KEYID(iv));
130
131 return 1;
132 }
133
134
135 static int parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset)
136 {
137 for (;;) {
138 if (!TTEST2(*(p + offset), 1))
139 return 1;
140 switch (*(p + offset)) {
141 case E_SSID:
142 if (!TTEST2(*(p+offset), 2))
143 return 0;
144 memcpy(&(pbody->ssid),p+offset,2); offset += 2;
145 if (pbody->ssid.length > 0)
146 {
147 if (!TTEST2(*(p+offset), pbody->ssid.length))
148 return 0;
149 memcpy(&(pbody->ssid.ssid),p+offset,pbody->ssid.length); offset += pbody->ssid.length;
150 pbody->ssid.ssid[pbody->ssid.length]='\0';
151 }
152 break;
153 case E_CHALLENGE:
154 if (!TTEST2(*(p+offset), 2))
155 return 0;
156 memcpy(&(pbody->challenge),p+offset,2); offset += 2;
157 if (pbody->challenge.length > 0)
158 {
159 if (!TTEST2(*(p+offset), pbody->challenge.length))
160 return 0;
161 memcpy(&(pbody->challenge.text),p+offset,pbody->challenge.length); offset += pbody->challenge.length;
162 pbody->challenge.text[pbody->challenge.length]='\0';
163 }
164 break;
165 case E_RATES:
166 if (!TTEST2(*(p+offset), 2))
167 return 0;
168 memcpy(&(pbody->rates),p+offset,2); offset += 2;
169 if (pbody->rates.length > 0) {
170 if (!TTEST2(*(p+offset), pbody->rates.length))
171 return 0;
172 memcpy(&(pbody->rates.rate),p+offset,pbody->rates.length); offset += pbody->rates.length;
173 }
174 break;
175 case E_DS:
176 if (!TTEST2(*(p+offset), 3))
177 return 0;
178 memcpy(&(pbody->ds),p+offset,3); offset +=3;
179 break;
180 case E_CF:
181 if (!TTEST2(*(p+offset), 8))
182 return 0;
183 memcpy(&(pbody->cf),p+offset,8); offset +=8;
184 break;
185 case E_TIM:
186 if (!TTEST2(*(p+offset), 2))
187 return 0;
188 memcpy(&(pbody->tim),p+offset,2); offset +=2;
189 if (!TTEST2(*(p+offset), 3))
190 return 0;
191 memcpy(&(pbody->tim.count),p+offset,3); offset +=3;
192
193 if ((pbody->tim.length -3) > 0)
194 {
195 if (!TTEST2(*(p+offset), pbody->tim.length -3))
196 return 0;
197 memcpy((pbody->tim.bitmap),p+(pbody->tim.length -3),(pbody->tim.length -3));
198 offset += pbody->tim.length -3;
199 }
200
201 break;
202 default:
203 #if 0
204 printf("(1) unhandled element_id (%d) ", *(p+offset) );
205 #endif
206 offset+= *(p+offset+1) + 2;
207 break;
208 }
209 }
210 return 1;
211 }
212
213 /*********************************************************************************
214 * Print Handle functions for the management frame types
215 *********************************************************************************/
216
217 static int handle_beacon(u_int16_t fc, const struct mgmt_header_t *pmh,
218 const u_char *p)
219 {
220 struct mgmt_body_t pbody;
221 int offset = 0;
222
223 memset(&pbody, 0, sizeof(pbody));
224
225 if (!TTEST2(*p, 12))
226 return 0;
227 memcpy(&pbody.timestamp, p, 8);
228 offset += 8;
229 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
230 offset += 2;
231 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
232 offset += 2;
233
234 if (!parse_elements(&pbody,p,offset))
235 return 0;
236
237 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
238 fn_print(pbody.ssid.ssid, NULL);
239 printf(")");
240 PRINT_RATES(pbody);
241 printf(" %s CH: %u %s",
242 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS",
243 pbody.ds.channel,
244 CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
245
246 return 1;
247 }
248
249 static int handle_assoc_request(u_int16_t fc, const struct mgmt_header_t *pmh,
250 const u_char *p)
251 {
252 struct mgmt_body_t pbody;
253 int offset = 0;
254
255 memset(&pbody, 0, sizeof(pbody));
256
257 if (!TTEST2(*p, 4))
258 return 0;
259 pbody.capability_info = EXTRACT_LE_16BITS(p);
260 offset += 2;
261 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
262 offset += 2;
263
264 if (!parse_elements(&pbody,p,offset))
265 return 0;
266
267 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
268 fn_print(pbody.ssid.ssid, NULL);
269 printf(")");
270 PRINT_RATES(pbody);
271 return 1;
272 }
273
274 static int handle_assoc_response(u_int16_t fc, const struct mgmt_header_t *pmh,
275 const u_char *p)
276 {
277 struct mgmt_body_t pbody;
278 int offset = 0;
279
280 memset(&pbody, 0, sizeof(pbody));
281
282 if (!TTEST2(*p, 6))
283 return 0;
284 pbody.capability_info = EXTRACT_LE_16BITS(p);
285 offset += 2;
286 pbody.status_code = EXTRACT_LE_16BITS(p+offset);
287 offset += 2;
288 pbody.aid = EXTRACT_LE_16BITS(p+offset);
289 offset += 2;
290
291 if (!parse_elements(&pbody,p,offset))
292 return 0;
293
294 printf("%s AID(%x) :%s: %s", subtype_text[FC_SUBTYPE(fc)],
295 ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
296 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
297 (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a"));
298
299 return 1;
300 }
301
302
303 static int handle_reassoc_request(u_int16_t fc, const struct mgmt_header_t *pmh,
304 const u_char *p)
305 {
306 struct mgmt_body_t pbody;
307 int offset = 0;
308
309 memset(&pbody, 0, sizeof(pbody));
310
311 if (!TTEST2(*p, 10))
312 return 0;
313 pbody.capability_info = EXTRACT_LE_16BITS(p);
314 offset += 2;
315 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
316 offset += 2;
317 memcpy(&pbody.ap,p+offset,6);
318 offset += 6;
319
320 if (!parse_elements(&pbody,p,offset))
321 return 0;
322
323 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
324 fn_print(pbody.ssid.ssid, NULL);
325 printf(") AP : %s", etheraddr_string( pbody.ap ));
326
327 return 1;
328 }
329
330 static int handle_reassoc_response(u_int16_t fc, const struct mgmt_header_t *pmh,
331 const u_char *p)
332 {
333 /* Same as a Association Reponse */
334 return handle_assoc_response(fc,pmh,p);
335 }
336
337 static int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh,
338 const u_char *p)
339 {
340 struct mgmt_body_t pbody;
341 int offset = 0;
342
343 memset(&pbody, 0, sizeof(pbody));
344
345 if (!parse_elements(&pbody, p, offset))
346 return 0;
347
348 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
349 fn_print(pbody.ssid.ssid, NULL);
350 printf(")");
351 PRINT_RATES(pbody);
352
353 return 1;
354 }
355
356 static int handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh,
357 const u_char *p)
358 {
359 struct mgmt_body_t pbody;
360 int offset = 0;
361
362 memset(&pbody, 0, sizeof(pbody));
363
364 if (!TTEST2(*p, 12))
365 return 0;
366 memcpy(&pbody.timestamp,p,8);
367 offset += 8;
368 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
369 offset += 2;
370 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
371 offset += 2;
372
373 if (!parse_elements(&pbody, p, offset))
374 return 0;
375
376 printf("%s (", subtype_text[FC_SUBTYPE(fc)]);
377 fn_print(pbody.ssid.ssid, NULL);
378 printf(") ");
379 PRINT_RATES(pbody);
380 printf(" CH: %u%s", pbody.ds.channel,
381 CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
382
383 return 1;
384 }
385
386 static int handle_atim(u_int16_t fc, const struct mgmt_header_t *pmh,
387 const u_char *p)
388 {
389 /* the frame body for ATIM is null. */
390 printf("ATIM");
391 return 1;
392 }
393
394 static int handle_disassoc(u_int16_t fc, const struct mgmt_header_t *pmh,
395 const u_char *p)
396 {
397 struct mgmt_body_t pbody;
398 int offset = 0;
399
400 memset(&pbody, 0, sizeof(pbody));
401
402 if (!TTEST2(*p, 2))
403 return 0;
404 pbody.reason_code = EXTRACT_LE_16BITS(p);
405 offset += 2;
406
407 printf("%s: %s", subtype_text[FC_SUBTYPE(fc)],
408 pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
409
410 return 1;
411 }
412
413 static int handle_auth(u_int16_t fc, const struct mgmt_header_t *pmh,
414 const u_char *p)
415 {
416 struct mgmt_body_t pbody;
417 int offset = 0;
418
419 memset(&pbody, 0, sizeof(pbody));
420
421 if (!TTEST2(*p, 6))
422 return 0;
423 pbody.auth_alg = EXTRACT_LE_16BITS(p);
424 offset += 2;
425 pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
426 offset += 2;
427 pbody.status_code = EXTRACT_LE_16BITS(p + offset);
428 offset += 2;
429
430 if (!parse_elements(&pbody,p,offset))
431 return 0;
432
433 if ((pbody.auth_alg == 1) &&
434 ((pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3))) {
435 printf("%s (%s)-%x [Challenge Text] %s",
436 subtype_text[FC_SUBTYPE(fc)],
437 pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" ,
438 pbody.auth_trans_seq_num,
439 ((pbody.auth_trans_seq_num % 2) ?
440 (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : "" ));
441 } else {
442 printf("%s (%s)-%x: %s",
443 subtype_text[FC_SUBTYPE(fc)],
444 pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" ,
445 pbody.auth_trans_seq_num,
446 ((pbody.auth_trans_seq_num % 2) ? (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : ""));
447 }
448
449 return 1;
450 }
451
452 static int handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh,
453 const u_char *p)
454 {
455 struct mgmt_body_t pbody;
456 int offset = 0;
457
458 memset(&pbody, 0, sizeof(pbody));
459
460 if (!TTEST2(*p, 2))
461 return 0;
462 pbody.reason_code = EXTRACT_LE_16BITS(p);
463 offset += 2;
464
465 if (eflag) {
466 printf("%s: %s",
467 subtype_text[FC_SUBTYPE(fc)],
468 pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
469 } else {
470 printf("%s (%s): %s",
471 subtype_text[FC_SUBTYPE(fc)], etheraddr_string(pmh->sa),
472 pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
473 }
474
475 return 1;
476 }
477
478
479 /*********************************************************************************
480 * Print Body funcs
481 *********************************************************************************/
482
483
484 static int mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
485 const u_char *p, u_int length)
486 {
487 switch (FC_SUBTYPE(fc)) {
488 case ST_ASSOC_REQUEST:
489 return (handle_assoc_request(fc, pmh, p));
490 case ST_ASSOC_RESPONSE:
491 return (handle_assoc_response(fc, pmh, p));
492 case ST_REASSOC_REQUEST:
493 return (handle_reassoc_request(fc, pmh, p));
494 case ST_REASSOC_RESPONSE:
495 return (handle_reassoc_response(fc, pmh, p));
496 case ST_PROBE_REQUEST:
497 return (handle_probe_request(fc, pmh, p));
498 case ST_PROBE_RESPONSE:
499 return (handle_probe_response(fc, pmh, p));
500 case ST_BEACON:
501 return (handle_beacon(fc, pmh, p));
502 case ST_ATIM:
503 return (handle_atim(fc, pmh, p));
504 case ST_DISASSOC:
505 return (handle_disassoc(fc, pmh, p));
506 case ST_AUTH:
507 if (!TTEST2(*p, 3))
508 return 0;
509 if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
510 printf("Authentication (Shared-Key)-3 ");
511 return (wep_print(p, length));
512 }
513 else
514 return (handle_auth(fc, pmh, p));
515 case ST_DEAUTH:
516 return (handle_deauth(fc, pmh, p));
517 break;
518 default:
519 printf("Unhandled Managment subtype(%x)",
520 FC_SUBTYPE(fc));
521 return 1;
522 }
523 }
524
525
526 /*********************************************************************************
527 * Handles printing all the control frame types
528 *********************************************************************************/
529
530 static int ctrl_body_print(u_int16_t fc,const u_char *p, u_int length)
531 {
532 switch (FC_SUBTYPE(fc)) {
533 case CTRL_PS_POLL:
534 if (!TTEST2(*p, CTRL_PS_POLL_LEN))
535 return 0;
536 printf("Power Save-Poll AID(%x)",
537 EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
538 break;
539 case CTRL_RTS:
540 if (!TTEST2(*p, CTRL_RTS_LEN))
541 return 0;
542 if (eflag)
543 printf("Request-To-Send");
544 else
545 printf("Request-To-Send TA:%s ",
546 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
547 break;
548 case CTRL_CTS:
549 if (!TTEST2(*p, CTRL_CTS_LEN))
550 return 0;
551 if (eflag)
552 printf("Clear-To-Send");
553 else
554 printf("Clear-To-Send RA:%s ",
555 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
556 break;
557 case CTRL_ACK:
558 if (!TTEST2(*p, CTRL_ACK_LEN))
559 return 0;
560 if (eflag)
561 printf("Acknowledgment");
562 else
563 printf("Acknowledgment RA:%s ",
564 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
565 break;
566 case CTRL_CF_END:
567 if (!TTEST2(*p, CTRL_END_LEN))
568 return 0;
569 if (eflag)
570 printf("CF-End");
571 else
572 printf("CF-End RA:%s ",
573 etheraddr_string(((const struct ctrl_end_t *)p)->ra));
574 break;
575 case CTRL_END_ACK:
576 if (!TTEST2(*p, CTRL_END_ACK_LEN))
577 return 0;
578 if (eflag)
579 printf("CF-End+CF-Ack");
580 else
581 printf("CF-End+CF-Ack RA:%s ",
582 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
583 break;
584 default:
585 printf("(B) Unknown Ctrl Subtype");
586 }
587 return 1;
588 }
589
590
591
592 /*
593 * Print Header funcs
594 */
595
596 /*
597 * Data Frame - Address field contents
598 *
599 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
600 * 0 | 0 | DA | SA | BSSID | n/a
601 * 0 | 1 | DA | BSSID | SA | n/a
602 * 1 | 0 | BSSID | SA | DA | n/a
603 * 1 | 1 | RA | TA | DA | SA
604 */
605
606 static void data_header_print(u_int16_t fc,const u_char *p, u_int length)
607 {
608 #define ADDR1 (p + 4)
609 #define ADDR2 (p + 10)
610 #define ADDR3 (p + 16)
611 #define ADDR4 (p + 24)
612
613 if (!FC_TO_DS(fc)) {
614 if (!FC_FROM_DS(fc))
615 printf("DA:%s SA:%s BSSID:%s ",
616 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
617 etheraddr_string(ADDR3));
618 else
619 printf("DA:%s BSSID:%s SA:%s ",
620 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
621 etheraddr_string(ADDR3));
622 } else {
623 if (!FC_FROM_DS(fc))
624 printf("BSSID:%s SA:%s DA:%s ",
625 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
626 etheraddr_string(ADDR3));
627 else
628 printf("RA:%s TA:%s DA:%s SA:%s ",
629 etheraddr_string(ADDR1), etheraddr_string(ADDR2),
630 etheraddr_string(ADDR3), etheraddr_string(ADDR4));
631 }
632
633 #undef ADDR1
634 #undef ADDR2
635 #undef ADDR3
636 #undef ADDR4
637 }
638
639
640 static void mgmt_header_print(const u_char *p, u_int length)
641 {
642 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
643
644 printf("BSSID:%s DA:%s SA:%s ",
645 etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
646 etheraddr_string((hp)->sa));
647 }
648
649 static void ctrl_header_print(u_int16_t fc,const u_char *p, u_int length)
650 {
651 switch (FC_SUBTYPE(fc)) {
652 case CTRL_PS_POLL:
653 printf("BSSID:%s TA:%s ",
654 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
655 etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
656 break;
657 case CTRL_RTS:
658 printf("RA:%s TA:%s ",
659 etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
660 etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
661 break;
662 case CTRL_CTS:
663 printf("RA:%s ",
664 etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
665 break;
666 case CTRL_ACK:
667 printf("RA:%s ",
668 etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
669 break;
670 case CTRL_CF_END:
671 printf("RA:%s BSSID:%s ",
672 etheraddr_string(((const struct ctrl_end_t *)p)->ra),
673 etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
674 break;
675 case CTRL_END_ACK:
676 printf("RA:%s BSSID:%s ",
677 etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
678 etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
679 break;
680 default:
681 printf("(H) Unknown Ctrl Subtype");
682 }
683 }
684
685 static int GetHeaderLength(u_int16_t fc)
686 {
687 int iLength=0;
688
689 switch (FC_TYPE(fc)) {
690 case T_MGMT:
691 iLength = MGMT_HEADER_LEN;
692 break;
693 case T_CTRL:
694 switch (FC_SUBTYPE(fc)) {
695 case CTRL_PS_POLL:
696 iLength = CTRL_PS_POLL_LEN;
697 break;
698 case CTRL_RTS:
699 iLength = CTRL_RTS_LEN;
700 break;
701 case CTRL_CTS:
702 iLength = CTRL_CTS_LEN;
703 break;
704 case CTRL_ACK:
705 iLength = CTRL_ACK_LEN;
706 break;
707 case CTRL_CF_END:
708 iLength = CTRL_END_LEN;
709 break;
710 case CTRL_END_ACK:
711 iLength = CTRL_END_ACK_LEN;
712 break;
713 default:
714 iLength = 0;
715 break;
716 }
717 break;
718 case T_DATA:
719 if (FC_TO_DS(fc) && FC_FROM_DS(fc))
720 iLength = 30;
721 else
722 iLength = 24;
723 break;
724 default:
725 printf("unknown IEEE802.11 frame type (%d)",
726 FC_TYPE(fc));
727 break;
728 }
729
730 return iLength;
731 }
732
733 /*
734 * Print the 802.11 MAC header
735 */
736 static inline void
737 ieee_802_11_print(u_int16_t fc, const u_char *p, u_int length)
738 {
739 switch (FC_TYPE(fc)) {
740 case T_MGMT:
741 mgmt_header_print(p, length);
742 break;
743
744 case T_CTRL:
745 ctrl_header_print(fc, p, length);
746 break;
747
748 case T_DATA:
749 data_header_print(fc, p, length);
750 break;
751
752 default:
753 printf("(header) unknown IEEE802.11 frame type (%d)",
754 FC_TYPE(fc));
755 break;
756 }
757 }
758
759 /*
760 * This is the top level routine of the printer. 'p' is the points
761 * to the ether header of the packet, 'h->tv' is the timestamp,
762 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
763 * is the number of bytes actually captured.
764 */
765 void
766 ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
767 {
768 u_int caplen = h->caplen;
769 u_int length = h->len;
770 u_int16_t fc;
771 u_int HEADER_LENGTH;
772 u_short extracted_ethertype;
773
774 ++infodelay;
775 ts_print(&h->ts);
776
777 if (caplen < IEEE802_11_FC_LEN) {
778 printf("[|802.11]");
779 goto out;
780 }
781
782 fc=EXTRACT_LE_16BITS(p);
783
784 if (eflag)
785 ieee_802_11_print(fc, p, length);
786
787 /*
788 * Some printers want to get back at the ethernet addresses,
789 * and/or check that they're not walking off the end of the packet.
790 * Rather than pass them all the way down, we set these globals.
791 */
792 packetp = p;
793 snapend = p + caplen;
794
795 HEADER_LENGTH=GetHeaderLength(fc);
796
797 length -= HEADER_LENGTH;
798 caplen -= HEADER_LENGTH;
799 p += HEADER_LENGTH;
800
801 switch (FC_TYPE(fc)) {
802 case T_MGMT:
803 if (!mgmt_body_print(fc, (const struct mgmt_header_t *)packetp,
804 p, length)) {
805 printf("[|802.11]");
806 goto out;
807 }
808 break;
809
810 case T_CTRL:
811 if (!ctrl_body_print(fc, p - HEADER_LENGTH,
812 length + HEADER_LENGTH)) {
813 printf("[|802.11]");
814 goto out;
815 }
816 break;
817
818 case T_DATA:
819 /* There may be a problem w/ AP not having this bit set */
820 if (FC_WEP(fc)) {
821 if (!wep_print(p,length)) {
822 printf("[|802.11]");
823 goto out;
824 }
825 } else {
826 if (llc_print(p, length, caplen, packetp + 10,
827 packetp + 4, &extracted_ethertype) == 0) {
828 /*
829 * Some kinds of LLC packet we cannot
830 * handle intelligently
831 */
832 if (!eflag)
833 ieee_802_11_print(fc, p - HEADER_LENGTH,
834 length + HEADER_LENGTH);
835 if (extracted_ethertype) {
836 printf("(LLC %s) ",
837 etherproto_string(htons(extracted_ethertype)));
838 }
839 if (!xflag && !qflag)
840 default_print(p, caplen);
841 }
842 }
843 break;
844
845 default:
846 printf("(body) unhandled IEEE802.11 frame type (%d)",
847 FC_TYPE(fc));
848 break;
849 }
850
851 if (xflag)
852 default_print(p, caplen);
853 out:
854 putchar('\n');
855 --infodelay;
856 if (infoprint)
857 info(0);
858 }