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.6.4.1 2002/05/13 08:34:50 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 } 859