1 /* $OpenBSD: print-802_11.c,v 1.6 2006/06/26 23:06:07 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* usr.sbin/tcpdump/print-802_11.c,v 1.3 2005/03/09 11:43:17 deraadt Exp */ 20 21 #include <sys/param.h> 22 #include <sys/time.h> 23 #include <sys/socket.h> 24 #include <sys/file.h> 25 #include <sys/ioctl.h> 26 27 #include <net/if.h> 28 #include <net/if_dl.h> 29 #include <net/if_media.h> 30 #include <net/if_arp.h> 31 #include <net/if_llc.h> 32 #include <net/bpf.h> 33 34 #include <netinet/in.h> 35 #include <netinet/if_ether.h> 36 #include <arpa/inet.h> 37 38 #include <net80211/ieee80211.h> 39 #include <net80211/ieee80211_radiotap.h> 40 41 #include <pcap.h> 42 #include <stdio.h> 43 #include <string.h> 44 45 #include "hostapd.h" 46 47 const char *ieee80211_mgt_subtype_name[] = { 48 "association request", 49 "association response", 50 "reassociation request", 51 "reassociation response", 52 "probe request", 53 "probe response", 54 "reserved#6", 55 "reserved#7", 56 "beacon", 57 "atim", 58 "disassociation", 59 "authentication", 60 "deauthentication", 61 "reserved#13", 62 "reserved#14", 63 "reserved#15" 64 }; 65 66 const u_int8_t *snapend; 67 int vflag = 1, eflag = 1; 68 69 int ieee80211_hdr(struct ieee80211_frame *); 70 void ieee80211_print_element(u_int8_t *, u_int); 71 void ieee80211_print_essid(u_int8_t *, u_int); 72 int ieee80211_elements(struct ieee80211_frame *); 73 int ieee80211_frame(struct ieee80211_frame *); 74 int ieee80211_print(struct ieee80211_frame *); 75 u_int ieee80211_any2ieee(u_int, u_int); 76 void ieee802_11_if_print(u_int8_t *, u_int); 77 void ieee802_11_radio_if_print(u_int8_t *, u_int); 78 79 #define TCARR(a) TCHECK2(*a, sizeof(a)) 80 81 int 82 ieee80211_hdr(struct ieee80211_frame *wh) 83 { 84 struct ieee80211_frame_addr4 *w4; 85 86 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 87 case IEEE80211_FC1_DIR_NODS: 88 TCARR(wh->i_addr2); 89 PRINTF("%s", etheraddr_string(wh->i_addr2)); 90 TCARR(wh->i_addr1); 91 PRINTF(" > %s", etheraddr_string(wh->i_addr1)); 92 TCARR(wh->i_addr3); 93 PRINTF(", bssid %s", etheraddr_string(wh->i_addr3)); 94 break; 95 case IEEE80211_FC1_DIR_TODS: 96 TCARR(wh->i_addr2); 97 PRINTF("%s", etheraddr_string(wh->i_addr2)); 98 TCARR(wh->i_addr3); 99 PRINTF(" > %s", etheraddr_string(wh->i_addr3)); 100 TCARR(wh->i_addr1); 101 PRINTF(", bssid %s, > DS", etheraddr_string(wh->i_addr1)); 102 break; 103 case IEEE80211_FC1_DIR_FROMDS: 104 TCARR(wh->i_addr3); 105 PRINTF("%s", etheraddr_string(wh->i_addr3)); 106 TCARR(wh->i_addr1); 107 PRINTF(" > %s", etheraddr_string(wh->i_addr1)); 108 TCARR(wh->i_addr2); 109 PRINTF(", bssid %s, DS >", etheraddr_string(wh->i_addr2)); 110 break; 111 case IEEE80211_FC1_DIR_DSTODS: 112 w4 = (struct ieee80211_frame_addr4 *) wh; 113 TCARR(w4->i_addr4); 114 PRINTF("%s", etheraddr_string(w4->i_addr4)); 115 TCARR(w4->i_addr3); 116 PRINTF(" > %s", etheraddr_string(w4->i_addr3)); 117 TCARR(w4->i_addr2); 118 PRINTF(", bssid %s", etheraddr_string(w4->i_addr2)); 119 TCARR(w4->i_addr1); 120 PRINTF(" > %s, DS > DS", etheraddr_string(w4->i_addr1)); 121 break; 122 } 123 if (vflag) { 124 TCARR(wh->i_seq); 125 PRINTF(" (seq %u)", letoh16(*(u_int16_t *)&wh->i_seq[0])); 126 } 127 128 return (0); 129 130 trunc: 131 /* Truncated elements in frame */ 132 return (1); 133 } 134 135 /* Caller checks len */ 136 void 137 ieee80211_print_element(u_int8_t *data, u_int len) 138 { 139 u_int8_t *p; 140 u_int i; 141 142 PRINTF(" 0x"); 143 for (i = 0, p = data; i < len; i++, p++) 144 PRINTF("%02x", *p); 145 } 146 147 /* Caller checks len */ 148 void 149 ieee80211_print_essid(u_int8_t *essid, u_int len) 150 { 151 u_int8_t *p; 152 u_int i; 153 154 if (len > IEEE80211_NWID_LEN) 155 len = IEEE80211_NWID_LEN; 156 157 /* determine printable or not */ 158 for (i = 0, p = essid; i < len; i++, p++) { 159 if (*p < ' ' || *p > 0x7e) 160 break; 161 } 162 if (i == len) { 163 PRINTF(" ("); 164 for (i = 0, p = essid; i < len; i++, p++) 165 PRINTF("%c", *p); 166 PRINTF(")"); 167 } else 168 ieee80211_print_element(essid, len); 169 } 170 171 int 172 ieee80211_elements(struct ieee80211_frame *wh) 173 { 174 u_int8_t *frm; 175 u_int8_t *tstamp, *bintval, *capinfo; 176 int i; 177 178 frm = (u_int8_t *)&wh[1]; 179 180 tstamp = frm; 181 TCHECK2(*tstamp, 8); 182 frm += 8; 183 184 bintval = frm; 185 TCHECK2(*bintval, 2); 186 frm += 2; 187 188 if (vflag) 189 PRINTF(", interval %u", letoh16(*(u_int16_t *)bintval)); 190 191 capinfo = frm; 192 TCHECK2(*capinfo, 2); 193 frm += 2; 194 195 #if 0 196 if (vflag) 197 printb(", caps", letoh16(*(u_int16_t *)capinfo), 198 IEEE80211_CAPINFO_BITS); 199 #endif 200 201 while (TTEST2(*frm, 2)) { 202 u_int len = frm[1]; 203 u_int8_t *data = frm + 2; 204 205 if (!TTEST2(*data, len)) 206 break; 207 208 #define ELEM_CHECK(l) if (len != l) break 209 210 switch (*frm) { 211 case IEEE80211_ELEMID_SSID: 212 PRINTF(", ssid"); 213 ieee80211_print_essid(data, len); 214 break; 215 case IEEE80211_ELEMID_RATES: 216 if (!vflag) 217 break; 218 PRINTF(", rates"); 219 for (i = len; i > 0; i--, data++) 220 PRINTF(" %uM", 221 (data[0] & IEEE80211_RATE_VAL) / 2); 222 break; 223 case IEEE80211_ELEMID_FHPARMS: 224 ELEM_CHECK(5); 225 PRINTF(", fh (dwell %u, chan %u, index %u)", 226 (data[1] << 8) | data[0], 227 (data[2] - 1) * 80 + data[3], /* FH_CHAN */ 228 data[4]); 229 break; 230 case IEEE80211_ELEMID_DSPARMS: 231 ELEM_CHECK(1); 232 if (!vflag) 233 break; 234 PRINTF(", ds"); 235 PRINTF(" (chan %u)", data[0]); 236 break; 237 case IEEE80211_ELEMID_CFPARMS: 238 if (!vflag) 239 break; 240 PRINTF(", cf"); 241 ieee80211_print_element(data, len); 242 break; 243 case IEEE80211_ELEMID_TIM: 244 if (!vflag) 245 break; 246 PRINTF(", tim"); 247 ieee80211_print_element(data, len); 248 break; 249 case IEEE80211_ELEMID_IBSSPARMS: 250 if (!vflag) 251 break; 252 PRINTF(", ibss"); 253 ieee80211_print_element(data, len); 254 break; 255 case IEEE80211_ELEMID_COUNTRY: 256 if (!vflag) 257 break; 258 PRINTF(", country"); 259 for (i = len; i > 0; i--, data++) 260 PRINTF(" %u", data[0]); 261 break; 262 case IEEE80211_ELEMID_CHALLENGE: 263 if (!vflag) 264 break; 265 PRINTF(", challenge"); 266 ieee80211_print_element(data, len); 267 break; 268 case IEEE80211_ELEMID_ERP: 269 if (!vflag) 270 break; 271 PRINTF(", erp"); 272 ieee80211_print_element(data, len); 273 break; 274 case IEEE80211_ELEMID_RSN: 275 if (!vflag) 276 break; 277 PRINTF(", rsn"); 278 ieee80211_print_element(data, len); 279 break; 280 case IEEE80211_ELEMID_XRATES: 281 if (!vflag) 282 break; 283 PRINTF(", xrates"); 284 for (i = len; i > 0; i--, data++) 285 PRINTF(" %uM", 286 (data[0] & IEEE80211_RATE_VAL) / 2); 287 break; 288 case IEEE80211_ELEMID_TPC: 289 if (!vflag) 290 break; 291 PRINTF(", tpc"); 292 ieee80211_print_element(data, len); 293 break; 294 case IEEE80211_ELEMID_CCKM: 295 if (!vflag) 296 break; 297 PRINTF(", cckm"); 298 ieee80211_print_element(data, len); 299 break; 300 case IEEE80211_ELEMID_VENDOR: 301 if (!vflag) 302 break; 303 PRINTF(", vendor"); 304 ieee80211_print_element(data, len); 305 break; 306 default: 307 if (!vflag) 308 break; 309 PRINTF(", %u:%u", (u_int) *frm, len); 310 ieee80211_print_element(data, len); 311 break; 312 } 313 frm += len + 2; 314 315 if (frm >= snapend) 316 break; 317 } 318 319 #undef ELEM_CHECK 320 321 return (0); 322 323 trunc: 324 /* Truncated elements in frame */ 325 return (1); 326 } 327 328 int 329 ieee80211_frame(struct ieee80211_frame *wh) 330 { 331 u_int8_t subtype, type, *frm; 332 333 TCARR(wh->i_fc); 334 335 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 336 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 337 338 frm = (u_int8_t *)&wh[1]; 339 340 switch (type) { 341 case IEEE80211_FC0_TYPE_DATA: 342 PRINTF(": data"); 343 break; 344 case IEEE80211_FC0_TYPE_MGT: 345 PRINTF(": %s", ieee80211_mgt_subtype_name[ 346 subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]); 347 switch (subtype) { 348 case IEEE80211_FC0_SUBTYPE_BEACON: 349 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 350 if (ieee80211_elements(wh) != 0) 351 goto trunc; 352 break; 353 case IEEE80211_FC0_SUBTYPE_AUTH: 354 TCHECK2(*frm, 2); /* Auth Algorithm */ 355 switch (IEEE80211_AUTH_ALGORITHM(frm)) { 356 case IEEE80211_AUTH_ALG_OPEN: 357 TCHECK2(*frm, 4); /* Auth Transaction */ 358 switch (IEEE80211_AUTH_TRANSACTION(frm)) { 359 case IEEE80211_AUTH_OPEN_REQUEST: 360 PRINTF(" request"); 361 break; 362 case IEEE80211_AUTH_OPEN_RESPONSE: 363 PRINTF(" response"); 364 break; 365 } 366 break; 367 case IEEE80211_AUTH_ALG_SHARED: 368 TCHECK2(*frm, 4); /* Auth Transaction */ 369 switch (IEEE80211_AUTH_TRANSACTION(frm)) { 370 case IEEE80211_AUTH_SHARED_REQUEST: 371 PRINTF(" request"); 372 break; 373 case IEEE80211_AUTH_SHARED_CHALLENGE: 374 PRINTF(" challenge"); 375 break; 376 case IEEE80211_AUTH_SHARED_RESPONSE: 377 PRINTF(" response"); 378 break; 379 case IEEE80211_AUTH_SHARED_PASS: 380 PRINTF(" pass"); 381 break; 382 } 383 break; 384 case IEEE80211_AUTH_ALG_LEAP: 385 PRINTF(" (leap)"); 386 break; 387 } 388 break; 389 } 390 break; 391 default: 392 PRINTF(": type#%d", type); 393 break; 394 } 395 396 if (wh->i_fc[1] & IEEE80211_FC1_WEP) 397 PRINTF(", WEP"); 398 399 return (0); 400 401 trunc: 402 /* Truncated 802.11 frame */ 403 return (1); 404 } 405 406 u_int 407 ieee80211_any2ieee(u_int freq, u_int flags) 408 { 409 if (flags & IEEE80211_CHAN_2GHZ) { 410 if (freq == 2484) 411 return 14; 412 if (freq < 2484) 413 return (freq - 2407) / 5; 414 else 415 return 15 + ((freq - 2512) / 20); 416 } else if (flags & IEEE80211_CHAN_5GHZ) { 417 return (freq - 5000) / 5; 418 } else { 419 /* Assume channel is already an IEEE number */ 420 return (freq); 421 } 422 } 423 424 int 425 ieee80211_print(struct ieee80211_frame *wh) 426 { 427 if (eflag) 428 if (ieee80211_hdr(wh)) 429 return (1); 430 431 return (ieee80211_frame(wh)); 432 } 433 434 void 435 ieee802_11_if_print(u_int8_t *buf, u_int len) 436 { 437 struct ieee80211_frame *wh = (struct ieee80211_frame*)buf; 438 439 snapend = buf + len; 440 441 if (ieee80211_print(wh) != 0) 442 PRINTF("[|802.11]"); 443 444 PRINTF(NULL); 445 } 446 447 void 448 ieee802_11_radio_if_print(u_int8_t *buf, u_int len) 449 { 450 struct ieee80211_radiotap_header *rh = 451 (struct ieee80211_radiotap_header*)buf; 452 struct ieee80211_frame *wh; 453 u_int8_t *t; 454 u_int32_t present; 455 u_int rh_len; 456 457 snapend = buf + len; 458 459 TCHECK(*rh); 460 461 rh_len = letoh16(rh->it_len); 462 if (rh->it_version != 0) { 463 PRINTF("[?radiotap + 802.11 v:%u]", rh->it_version); 464 goto out; 465 } 466 467 wh = (struct ieee80211_frame *)(buf + rh_len); 468 if (len <= rh_len || ieee80211_print(wh)) 469 PRINTF("[|802.11]"); 470 471 t = (u_int8_t*)buf + sizeof(struct ieee80211_radiotap_header); 472 473 if ((present = letoh32(rh->it_present)) == 0) 474 goto out; 475 476 PRINTF(", <radiotap v%u", rh->it_version); 477 478 #define RADIOTAP(_x) \ 479 (present & (1 << IEEE80211_RADIOTAP_##_x)) 480 481 if (RADIOTAP(TSFT)) { 482 u_int64_t tsf; 483 u_int32_t tsf_v[2]; 484 485 TCHECK2(*t, 8); 486 487 tsf = letoh64(*(u_int64_t *)t); 488 tsf_v[0] = (u_int32_t)(tsf >> 32); 489 tsf_v[1] = (u_int32_t)(tsf & 0x00000000ffffffff); 490 if (vflag > 1) 491 PRINTF(", tsf 0x%08x%08x", tsf_v[0], tsf_v[1]); 492 t += 8; 493 } 494 495 if (RADIOTAP(FLAGS)) { 496 u_int8_t flags = *(u_int8_t*)t; 497 TCHECK2(*t, 1); 498 499 if (flags & IEEE80211_RADIOTAP_F_CFP) 500 PRINTF(", CFP"); 501 if (flags & IEEE80211_RADIOTAP_F_SHORTPRE) 502 PRINTF(", SHORTPRE"); 503 if (flags & IEEE80211_RADIOTAP_F_WEP) 504 PRINTF(", WEP"); 505 if (flags & IEEE80211_RADIOTAP_F_FRAG) 506 PRINTF(", FRAG"); 507 t += 1; 508 } 509 510 if (RADIOTAP(RATE)) { 511 TCHECK2(*t, 1); 512 if (vflag) 513 PRINTF(", %uMbit/s", (*(u_int8_t*)t) / 2); 514 t += 1; 515 } 516 517 if (RADIOTAP(CHANNEL)) { 518 u_int16_t freq, flags; 519 TCHECK2(*t, 2); 520 521 freq = letoh16(*(u_int16_t*)t); 522 t += 2; 523 TCHECK2(*t, 2); 524 flags = letoh16(*(u_int16_t*)t); 525 t += 2; 526 527 PRINTF(", chan %u", ieee80211_any2ieee(freq, flags)); 528 529 if (flags & IEEE80211_CHAN_DYN && 530 flags & IEEE80211_CHAN_2GHZ) 531 PRINTF(", 11g"); 532 else if (flags & IEEE80211_CHAN_CCK && 533 flags & IEEE80211_CHAN_2GHZ) 534 PRINTF(", 11b"); 535 else if (flags & IEEE80211_CHAN_OFDM && 536 flags & IEEE80211_CHAN_2GHZ) 537 PRINTF(", 11G"); 538 else if (flags & IEEE80211_CHAN_OFDM && 539 flags & IEEE80211_CHAN_5GHZ) 540 PRINTF(", 11a"); 541 542 if (flags & IEEE80211_CHAN_TURBO) 543 PRINTF(", TURBO"); 544 if (flags & IEEE80211_CHAN_XR) 545 PRINTF(", XR"); 546 } 547 548 if (RADIOTAP(FHSS)) { 549 TCHECK2(*t, 2); 550 PRINTF(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1); 551 t += 2; 552 } 553 554 if (RADIOTAP(DBM_ANTSIGNAL)) { 555 TCHECK(*t); 556 PRINTF(", sig %ddBm", *(int8_t*)t); 557 t += 1; 558 } 559 560 if (RADIOTAP(DBM_ANTNOISE)) { 561 TCHECK(*t); 562 PRINTF(", noise %ddBm", *(int8_t*)t); 563 t += 1; 564 } 565 566 if (RADIOTAP(LOCK_QUALITY)) { 567 TCHECK2(*t, 2); 568 if (vflag) 569 PRINTF(", quality %u", letoh16(*(u_int16_t*)t)); 570 t += 2; 571 } 572 573 if (RADIOTAP(TX_ATTENUATION)) { 574 TCHECK2(*t, 2); 575 if (vflag) 576 PRINTF(", txatt %u", 577 letoh16(*(u_int16_t*)t)); 578 t += 2; 579 } 580 581 if (RADIOTAP(DB_TX_ATTENUATION)) { 582 TCHECK2(*t, 2); 583 if (vflag) 584 PRINTF(", txatt %udB", 585 letoh16(*(u_int16_t*)t)); 586 t += 2; 587 } 588 589 if (RADIOTAP(DBM_TX_POWER)) { 590 TCHECK(*t); 591 PRINTF(", txpower %ddBm", *(int8_t*)t); 592 t += 1; 593 } 594 595 if (RADIOTAP(ANTENNA)) { 596 TCHECK(*t); 597 if (vflag) 598 PRINTF(", antenna %u", *(u_int8_t*)t); 599 t += 1; 600 } 601 602 if (RADIOTAP(DB_ANTSIGNAL)) { 603 TCHECK(*t); 604 PRINTF(", signal %udB", *(u_int8_t*)t); 605 t += 1; 606 } 607 608 if (RADIOTAP(DB_ANTNOISE)) { 609 TCHECK(*t); 610 PRINTF(", noise %udB", *(u_int8_t*)t); 611 t += 1; 612 } 613 614 if (RADIOTAP(FCS)) { 615 TCHECK2(*t, 4); 616 if (vflag) 617 PRINTF(", fcs %08x", letoh32(*(u_int32_t*)t)); 618 t += 4; 619 } 620 621 if (RADIOTAP(RSSI)) { 622 u_int8_t rssi, max_rssi; 623 TCHECK(*t); 624 rssi = *(u_int8_t*)t; 625 t += 1; 626 TCHECK(*t); 627 max_rssi = *(u_int8_t*)t; 628 t += 1; 629 630 PRINTF(", rssi %u/%u", rssi, max_rssi); 631 } 632 633 #undef RADIOTAP 634 635 PRINTF(">"); 636 goto out; 637 638 trunc: 639 /* Truncated frame */ 640 PRINTF("[|radiotap + 802.11]"); 641 642 out: 643 PRINTF(NULL); 644 } 645 646 void 647 hostapd_print_ieee80211(u_int dlt, u_int verbose, u_int8_t *buf, u_int len) 648 { 649 if (verbose) 650 vflag = 1; 651 else 652 vflag = 0; 653 654 if (dlt == DLT_IEEE802_11) 655 ieee802_11_if_print(buf, len); 656 else 657 ieee802_11_radio_if_print(buf, len); 658 } 659