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 2001/09/17 21:57:53 fenner 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 RATEStoBUF(p, buf) \ 51 do { \ 52 int z = 0; \ 53 for (z = 0 ; z < p.rates.length ; z++) \ 54 snprintf(buf, sizeof(buf), "%s %2.1f", buf, (.5 * (p.rates.rate[z] & 0x7f))); \ 55 } while (0) 56 57 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; 58 static const char *subtype_text[]={ 59 "Assoc Request", 60 "Assoc Response", 61 "ReAssoc Request", 62 "ReAssoc Response", 63 "Probe Request", 64 "Probe Response", 65 "RESERVED", 66 "RESERVED", 67 "Beacon", 68 "ATIM", 69 "Disassociation", 70 "Authentication", 71 "DeAuthentication", 72 "RESERVED", 73 "RESERVED" 74 }; 75 76 static const char *status_text[] = { 77 "Succesful", /* 0 */ 78 "Unspecified failure", /* 1 */ 79 "Reserved", /* 2 */ 80 "Reserved", /* 3 */ 81 "Reserved", /* 4 */ 82 "Reserved", /* 5 */ 83 "Reserved", /* 6 */ 84 "Reserved", /* 7 */ 85 "Reserved", /* 8 */ 86 "Reserved", /* 9 */ 87 "Cannot Support all requested capabilities in the Capability Information field", /* 10 */ 88 "Reassociation denied due to inability to confirm that association exists", /* 11 */ 89 "Association denied due to reason outside the scope of the standard", /* 12 */ 90 "Responding station does not support the specified authentication algorithm ", /* 13 */ 91 "Received an Authentication frame with authentication transaction " \ 92 "sequence number out of expected sequence", /* 14 */ 93 "Authentication rejected because of challenge failure", /* 15 */ 94 "Authentication rejected due to timeout waiting for next frame in sequence", /* 16 */ 95 "Association denied because AP is unable to handle additional associated stations", /* 17 */ 96 "Association denied due to requesting station not supporting all of the " \ 97 "data rates in BSSBasicRateSet parameter", /* 18 */ 98 NULL 99 }; 100 101 static const char *reason_text[] = { 102 "Reserved", /* 0 */ 103 "Unspecified reason", /* 1 */ 104 "Previous authentication no longer valid", /* 2 */ 105 "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */ 106 "Disassociated due to inactivity", /* 4 */ 107 "Disassociated because AP is unable to handle all currently associated stations", /* 5 */ 108 "Class 2 frame receivedfrom nonauthenticated station", /* 6 */ 109 "Class 3 frame received from nonassociated station", /* 7 */ 110 "Disassociated because sending station is leaving (or has left) BSS", /* 8 */ 111 "Station requesting (re)association is not authenticated with responding station", /* 9 */ 112 NULL 113 }; 114 115 static int wep_print(const u_char *p,u_int length) 116 { 117 u_int32_t iv; 118 119 if (!TTEST2(*p, 4)) 120 return 0; 121 iv = EXTRACT_LE_32BITS(p); 122 123 printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), 124 IV_KEYID(iv)); 125 126 return 1; 127 } 128 129 130 static int parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset) 131 { 132 for (;;) { 133 if (!TTEST2(*(p + offset), 1)) 134 return 0; 135 if (*(p + offset) == 0xff) 136 break; 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 struct mgmt_header_t *pmh, 215 const u_char *p) 216 { 217 struct mgmt_body_t pbody; 218 int offset = 0; 219 char buf[128]; 220 221 memset(buf, 0, sizeof(buf)); 222 memset(&pbody, 0, sizeof(pbody)); 223 224 if (!TTEST2(*p, 12)) 225 return 0; 226 memcpy(&pbody.timestamp, p, 8); 227 offset += 8; 228 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); 229 offset += 2; 230 pbody.capability_info = EXTRACT_LE_16BITS(p+offset); 231 offset += 2; 232 233 if (!parse_elements(&pbody,p,offset)) 234 return 0; 235 236 RATEStoBUF(pbody, buf); 237 238 printf("%s (%s) [%s Mbit] %s CH: %x %s", 239 subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid, buf, 240 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS", 241 pbody.ds.channel, 242 CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" ); 243 244 return 1; 245 } 246 247 static int handle_assoc_request(u_int16_t fc, const struct mgmt_header_t *pmh, 248 const u_char *p) 249 { 250 struct mgmt_body_t pbody; 251 int offset = 0; 252 char buf[128]; 253 254 memset(buf, 0, sizeof(buf)); 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 RATEStoBUF(pbody,buf); 268 269 printf("%s (%s) [%s Mbit] ", 270 subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid,buf); 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 (%s) AP : %s",subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid, etheraddr_string( pbody.ap )); 324 325 return 1; 326 } 327 328 static int handle_reassoc_response(u_int16_t fc, const struct mgmt_header_t *pmh, 329 const u_char *p) 330 { 331 /* Same as a Association Reponse */ 332 return handle_assoc_response(fc,pmh,p); 333 } 334 335 static int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh, 336 const u_char *p) 337 { 338 struct mgmt_body_t pbody; 339 int offset = 0; 340 char buf[128]; 341 342 memset(buf, 0, sizeof(buf)); 343 344 memset(&pbody, 0, sizeof(pbody)); 345 346 if (!parse_elements(&pbody, p, offset)) 347 return 0; 348 349 RATEStoBUF(pbody, buf); 350 351 printf("%s (%s) [%s Mbit] ", subtype_text[FC_SUBTYPE(fc)], 352 pbody.ssid.ssid,buf); 353 354 return 1; 355 } 356 357 static int handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh, 358 const u_char *p) 359 { 360 struct mgmt_body_t pbody; 361 int offset = 0; 362 char buf[128]; 363 364 memset(buf, 0, sizeof(buf)); 365 366 memset(&pbody, 0, sizeof(pbody)); 367 368 if (!TTEST2(*p, 12)) 369 return 0; 370 memcpy(&pbody.timestamp,p,8); 371 offset += 8; 372 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); 373 offset += 2; 374 pbody.capability_info = EXTRACT_LE_16BITS(p+offset); 375 offset += 2; 376 377 if (!parse_elements(&pbody, p, offset)) 378 return 0; 379 380 printf("%s (%s) CH: %x %s", subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid,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