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