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 #include <sys/cdefs.h> 24 #ifndef lint 25 __RCSID("$NetBSD: print-802_11.c,v 1.10 2023/08/17 20:19:40 christos Exp $"); 26 #endif 27 28 /* \summary: IEEE 802.11 printer */ 29 30 #ifdef HAVE_CONFIG_H 31 #include <config.h> 32 #endif 33 34 #include "netdissect-stdinc.h" 35 36 #include <string.h> 37 38 #include "netdissect.h" 39 #include "addrtoname.h" 40 41 #include "extract.h" 42 43 #include "cpack.h" 44 45 46 /* Lengths of 802.11 header components. */ 47 #define IEEE802_11_FC_LEN 2 48 #define IEEE802_11_DUR_LEN 2 49 #define IEEE802_11_DA_LEN 6 50 #define IEEE802_11_SA_LEN 6 51 #define IEEE802_11_BSSID_LEN 6 52 #define IEEE802_11_RA_LEN 6 53 #define IEEE802_11_TA_LEN 6 54 #define IEEE802_11_ADDR1_LEN 6 55 #define IEEE802_11_SEQ_LEN 2 56 #define IEEE802_11_CTL_LEN 2 57 #define IEEE802_11_CARRIED_FC_LEN 2 58 #define IEEE802_11_HT_CONTROL_LEN 4 59 #define IEEE802_11_IV_LEN 3 60 #define IEEE802_11_KID_LEN 1 61 62 /* Frame check sequence length. */ 63 #define IEEE802_11_FCS_LEN 4 64 65 /* Lengths of beacon components. */ 66 #define IEEE802_11_TSTAMP_LEN 8 67 #define IEEE802_11_BCNINT_LEN 2 68 #define IEEE802_11_CAPINFO_LEN 2 69 #define IEEE802_11_LISTENINT_LEN 2 70 71 #define IEEE802_11_AID_LEN 2 72 #define IEEE802_11_STATUS_LEN 2 73 #define IEEE802_11_REASON_LEN 2 74 75 /* Length of previous AP in reassocation frame */ 76 #define IEEE802_11_AP_LEN 6 77 78 #define T_MGMT 0x0 /* management */ 79 #define T_CTRL 0x1 /* control */ 80 #define T_DATA 0x2 /* data */ 81 #define T_RESV 0x3 /* reserved */ 82 83 #define ST_ASSOC_REQUEST 0x0 84 #define ST_ASSOC_RESPONSE 0x1 85 #define ST_REASSOC_REQUEST 0x2 86 #define ST_REASSOC_RESPONSE 0x3 87 #define ST_PROBE_REQUEST 0x4 88 #define ST_PROBE_RESPONSE 0x5 89 /* RESERVED 0x6 */ 90 /* RESERVED 0x7 */ 91 #define ST_BEACON 0x8 92 #define ST_ATIM 0x9 93 #define ST_DISASSOC 0xA 94 #define ST_AUTH 0xB 95 #define ST_DEAUTH 0xC 96 #define ST_ACTION 0xD 97 /* RESERVED 0xE */ 98 /* RESERVED 0xF */ 99 100 static const struct tok st_str[] = { 101 { ST_ASSOC_REQUEST, "Assoc Request" }, 102 { ST_ASSOC_RESPONSE, "Assoc Response" }, 103 { ST_REASSOC_REQUEST, "ReAssoc Request" }, 104 { ST_REASSOC_RESPONSE, "ReAssoc Response" }, 105 { ST_PROBE_REQUEST, "Probe Request" }, 106 { ST_PROBE_RESPONSE, "Probe Response" }, 107 { ST_BEACON, "Beacon" }, 108 { ST_ATIM, "ATIM" }, 109 { ST_DISASSOC, "Disassociation" }, 110 { ST_AUTH, "Authentication" }, 111 { ST_DEAUTH, "DeAuthentication" }, 112 { ST_ACTION, "Action" }, 113 { 0, NULL } 114 }; 115 116 #define CTRL_CONTROL_WRAPPER 0x7 117 #define CTRL_BAR 0x8 118 #define CTRL_BA 0x9 119 #define CTRL_PS_POLL 0xA 120 #define CTRL_RTS 0xB 121 #define CTRL_CTS 0xC 122 #define CTRL_ACK 0xD 123 #define CTRL_CF_END 0xE 124 #define CTRL_END_ACK 0xF 125 126 static const struct tok ctrl_str[] = { 127 { CTRL_CONTROL_WRAPPER, "Control Wrapper" }, 128 { CTRL_BAR, "BAR" }, 129 { CTRL_BA, "BA" }, 130 { CTRL_PS_POLL, "Power Save-Poll" }, 131 { CTRL_RTS, "Request-To-Send" }, 132 { CTRL_CTS, "Clear-To-Send" }, 133 { CTRL_ACK, "Acknowledgment" }, 134 { CTRL_CF_END, "CF-End" }, 135 { CTRL_END_ACK, "CF-End+CF-Ack" }, 136 { 0, NULL } 137 }; 138 139 #define DATA_DATA 0x0 140 #define DATA_DATA_CF_ACK 0x1 141 #define DATA_DATA_CF_POLL 0x2 142 #define DATA_DATA_CF_ACK_POLL 0x3 143 #define DATA_NODATA 0x4 144 #define DATA_NODATA_CF_ACK 0x5 145 #define DATA_NODATA_CF_POLL 0x6 146 #define DATA_NODATA_CF_ACK_POLL 0x7 147 148 #define DATA_QOS_DATA 0x8 149 #define DATA_QOS_DATA_CF_ACK 0x9 150 #define DATA_QOS_DATA_CF_POLL 0xA 151 #define DATA_QOS_DATA_CF_ACK_POLL 0xB 152 #define DATA_QOS_NODATA 0xC 153 #define DATA_QOS_CF_POLL_NODATA 0xE 154 #define DATA_QOS_CF_ACK_POLL_NODATA 0xF 155 156 /* 157 * The subtype field of a data frame is, in effect, composed of 4 flag 158 * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have 159 * any data), and QoS. 160 */ 161 #define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01) 162 #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02) 163 #define DATA_FRAME_IS_NULL(x) ((x) & 0x04) 164 #define DATA_FRAME_IS_QOS(x) ((x) & 0x08) 165 166 /* 167 * Bits in the frame control field. 168 */ 169 #define FC_VERSION(fc) ((fc) & 0x3) 170 #define FC_TYPE(fc) (((fc) >> 2) & 0x3) 171 #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF) 172 #define FC_TO_DS(fc) ((fc) & 0x0100) 173 #define FC_FROM_DS(fc) ((fc) & 0x0200) 174 #define FC_MORE_FLAG(fc) ((fc) & 0x0400) 175 #define FC_RETRY(fc) ((fc) & 0x0800) 176 #define FC_POWER_MGMT(fc) ((fc) & 0x1000) 177 #define FC_MORE_DATA(fc) ((fc) & 0x2000) 178 #define FC_PROTECTED(fc) ((fc) & 0x4000) 179 #define FC_ORDER(fc) ((fc) & 0x8000) 180 181 struct mgmt_header_t { 182 nd_uint16_t fc; 183 nd_uint16_t duration; 184 nd_mac_addr da; 185 nd_mac_addr sa; 186 nd_mac_addr bssid; 187 nd_uint16_t seq_ctrl; 188 }; 189 190 #define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 191 IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\ 192 IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN) 193 194 #define CAPABILITY_ESS(cap) ((cap) & 0x0001) 195 #define CAPABILITY_IBSS(cap) ((cap) & 0x0002) 196 #define CAPABILITY_CFP(cap) ((cap) & 0x0004) 197 #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008) 198 #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010) 199 200 struct ssid_t { 201 uint8_t element_id; 202 uint8_t length; 203 u_char ssid[33]; /* 32 + 1 for null */ 204 }; 205 206 struct rates_t { 207 uint8_t element_id; 208 uint8_t length; 209 uint8_t rate[16]; 210 }; 211 212 struct challenge_t { 213 uint8_t element_id; 214 uint8_t length; 215 uint8_t text[254]; /* 1-253 + 1 for null */ 216 }; 217 218 struct fh_t { 219 uint8_t element_id; 220 uint8_t length; 221 uint16_t dwell_time; 222 uint8_t hop_set; 223 uint8_t hop_pattern; 224 uint8_t hop_index; 225 }; 226 227 struct ds_t { 228 uint8_t element_id; 229 uint8_t length; 230 uint8_t channel; 231 }; 232 233 struct cf_t { 234 uint8_t element_id; 235 uint8_t length; 236 uint8_t count; 237 uint8_t period; 238 uint16_t max_duration; 239 uint16_t dur_remaining; 240 }; 241 242 struct tim_t { 243 uint8_t element_id; 244 uint8_t length; 245 uint8_t count; 246 uint8_t period; 247 uint8_t bitmap_control; 248 uint8_t bitmap[251]; 249 }; 250 251 #define E_SSID 0 252 #define E_RATES 1 253 #define E_FH 2 254 #define E_DS 3 255 #define E_CF 4 256 #define E_TIM 5 257 #define E_IBSS 6 258 /* reserved 7 */ 259 /* reserved 8 */ 260 /* reserved 9 */ 261 /* reserved 10 */ 262 /* reserved 11 */ 263 /* reserved 12 */ 264 /* reserved 13 */ 265 /* reserved 14 */ 266 /* reserved 15 */ 267 /* reserved 16 */ 268 269 #define E_CHALLENGE 16 270 /* reserved 17 */ 271 /* reserved 18 */ 272 /* reserved 19 */ 273 /* reserved 16 */ 274 /* reserved 16 */ 275 276 277 struct mgmt_body_t { 278 uint8_t timestamp[IEEE802_11_TSTAMP_LEN]; 279 uint16_t beacon_interval; 280 uint16_t listen_interval; 281 uint16_t status_code; 282 uint16_t aid; 283 u_char ap[IEEE802_11_AP_LEN]; 284 uint16_t reason_code; 285 uint16_t auth_alg; 286 uint16_t auth_trans_seq_num; 287 int challenge_present; 288 struct challenge_t challenge; 289 uint16_t capability_info; 290 int ssid_present; 291 struct ssid_t ssid; 292 int rates_present; 293 struct rates_t rates; 294 int ds_present; 295 struct ds_t ds; 296 int cf_present; 297 struct cf_t cf; 298 int fh_present; 299 struct fh_t fh; 300 int tim_present; 301 struct tim_t tim; 302 }; 303 304 struct ctrl_control_wrapper_hdr_t { 305 nd_uint16_t fc; 306 nd_uint16_t duration; 307 nd_mac_addr addr1; 308 nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN]; 309 nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN]; 310 }; 311 312 #define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 313 IEEE802_11_ADDR1_LEN+\ 314 IEEE802_11_CARRIED_FC_LEN+\ 315 IEEE802_11_HT_CONTROL_LEN) 316 317 struct ctrl_rts_hdr_t { 318 nd_uint16_t fc; 319 nd_uint16_t duration; 320 nd_mac_addr ra; 321 nd_mac_addr ta; 322 }; 323 324 #define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 325 IEEE802_11_RA_LEN+IEEE802_11_TA_LEN) 326 327 struct ctrl_cts_hdr_t { 328 nd_uint16_t fc; 329 nd_uint16_t duration; 330 nd_mac_addr ra; 331 }; 332 333 #define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 334 335 struct ctrl_ack_hdr_t { 336 nd_uint16_t fc; 337 nd_uint16_t duration; 338 nd_mac_addr ra; 339 }; 340 341 #define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 342 343 struct ctrl_ps_poll_hdr_t { 344 nd_uint16_t fc; 345 nd_uint16_t aid; 346 nd_mac_addr bssid; 347 nd_mac_addr ta; 348 }; 349 350 #define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\ 351 IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN) 352 353 struct ctrl_end_hdr_t { 354 nd_uint16_t fc; 355 nd_uint16_t duration; 356 nd_mac_addr ra; 357 nd_mac_addr bssid; 358 }; 359 360 #define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 361 IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) 362 363 struct ctrl_end_ack_hdr_t { 364 nd_uint16_t fc; 365 nd_uint16_t duration; 366 nd_mac_addr ra; 367 nd_mac_addr bssid; 368 }; 369 370 #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 371 IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) 372 373 struct ctrl_ba_hdr_t { 374 nd_uint16_t fc; 375 nd_uint16_t duration; 376 nd_mac_addr ra; 377 }; 378 379 #define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 380 381 struct ctrl_bar_hdr_t { 382 nd_uint16_t fc; 383 nd_uint16_t dur; 384 nd_mac_addr ra; 385 nd_mac_addr ta; 386 nd_uint16_t ctl; 387 nd_uint16_t seq; 388 }; 389 390 #define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 391 IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\ 392 IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN) 393 394 struct meshcntl_t { 395 nd_uint8_t flags; 396 nd_uint8_t ttl; 397 nd_uint32_t seq; 398 nd_mac_addr addr4; 399 nd_mac_addr addr5; 400 nd_mac_addr addr6; 401 }; 402 403 #define IV_IV(iv) ((iv) & 0xFFFFFF) 404 #define IV_PAD(iv) (((iv) >> 24) & 0x3F) 405 #define IV_KEYID(iv) (((iv) >> 30) & 0x03) 406 407 #define PRINT_SSID(p) \ 408 if (p.ssid_present) { \ 409 ND_PRINT(" ("); \ 410 fn_print_str(ndo, p.ssid.ssid); \ 411 ND_PRINT(")"); \ 412 } 413 414 #define PRINT_RATE(_sep, _r, _suf) \ 415 ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf) 416 #define PRINT_RATES(p) \ 417 if (p.rates_present) { \ 418 int z; \ 419 const char *sep = " ["; \ 420 for (z = 0; z < p.rates.length ; z++) { \ 421 PRINT_RATE(sep, p.rates.rate[z], \ 422 (p.rates.rate[z] & 0x80 ? "*" : "")); \ 423 sep = " "; \ 424 } \ 425 if (p.rates.length != 0) \ 426 ND_PRINT(" Mbit]"); \ 427 } 428 429 #define PRINT_DS_CHANNEL(p) \ 430 if (p.ds_present) \ 431 ND_PRINT(" CH: %u", p.ds.channel); \ 432 ND_PRINT("%s", \ 433 CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : ""); 434 435 #define MAX_MCS_INDEX 76 436 437 /* 438 * Indices are: 439 * 440 * the MCS index (0-76); 441 * 442 * 0 for 20 MHz, 1 for 40 MHz; 443 * 444 * 0 for a long guard interval, 1 for a short guard interval. 445 */ 446 static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = { 447 /* MCS 0 */ 448 { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, }, 449 /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, }, 450 }, 451 452 /* MCS 1 */ 453 { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, 454 /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, 455 }, 456 457 /* MCS 2 */ 458 { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, 459 /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, 460 }, 461 462 /* MCS 3 */ 463 { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, 464 /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, 465 }, 466 467 /* MCS 4 */ 468 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 469 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 470 }, 471 472 /* MCS 5 */ 473 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 474 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 475 }, 476 477 /* MCS 6 */ 478 { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, 479 /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, 480 }, 481 482 /* MCS 7 */ 483 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 484 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 485 }, 486 487 /* MCS 8 */ 488 { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, 489 /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, 490 }, 491 492 /* MCS 9 */ 493 { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, 494 /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, 495 }, 496 497 /* MCS 10 */ 498 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 499 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 500 }, 501 502 /* MCS 11 */ 503 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 504 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 505 }, 506 507 /* MCS 12 */ 508 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 509 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 510 }, 511 512 /* MCS 13 */ 513 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 514 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 515 }, 516 517 /* MCS 14 */ 518 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 519 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 520 }, 521 522 /* MCS 15 */ 523 { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, 524 /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, 525 }, 526 527 /* MCS 16 */ 528 { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, 529 /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, 530 }, 531 532 /* MCS 17 */ 533 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 534 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 535 }, 536 537 /* MCS 18 */ 538 { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, 539 /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, 540 }, 541 542 /* MCS 19 */ 543 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 544 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 545 }, 546 547 /* MCS 20 */ 548 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 549 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 550 }, 551 552 /* MCS 21 */ 553 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 554 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 555 }, 556 557 /* MCS 22 */ 558 { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, 559 /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, 560 }, 561 562 /* MCS 23 */ 563 { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, 564 /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, 565 }, 566 567 /* MCS 24 */ 568 { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, 569 /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, 570 }, 571 572 /* MCS 25 */ 573 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 574 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 575 }, 576 577 /* MCS 26 */ 578 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 579 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 580 }, 581 582 /* MCS 27 */ 583 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 584 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 585 }, 586 587 /* MCS 28 */ 588 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 589 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 590 }, 591 592 /* MCS 29 */ 593 { /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, }, 594 /* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, }, 595 }, 596 597 /* MCS 30 */ 598 { /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, }, 599 /* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, }, 600 }, 601 602 /* MCS 31 */ 603 { /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, }, 604 /* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, }, 605 }, 606 607 /* MCS 32 */ 608 { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */ 609 /* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, }, 610 }, 611 612 /* MCS 33 */ 613 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 614 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 615 }, 616 617 /* MCS 34 */ 618 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 619 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 620 }, 621 622 /* MCS 35 */ 623 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 624 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 625 }, 626 627 /* MCS 36 */ 628 { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, 629 /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, 630 }, 631 632 /* MCS 37 */ 633 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 634 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 635 }, 636 637 /* MCS 38 */ 638 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 639 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 640 }, 641 642 /* MCS 39 */ 643 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 644 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 645 }, 646 647 /* MCS 40 */ 648 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 649 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 650 }, 651 652 /* MCS 41 */ 653 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 654 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 655 }, 656 657 /* MCS 42 */ 658 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 659 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 660 }, 661 662 /* MCS 43 */ 663 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 664 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 665 }, 666 667 /* MCS 44 */ 668 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 669 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 670 }, 671 672 /* MCS 45 */ 673 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 674 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 675 }, 676 677 /* MCS 46 */ 678 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 679 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 680 }, 681 682 /* MCS 47 */ 683 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 684 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 685 }, 686 687 /* MCS 48 */ 688 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 689 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 690 }, 691 692 /* MCS 49 */ 693 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 694 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 695 }, 696 697 /* MCS 50 */ 698 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 699 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 700 }, 701 702 /* MCS 51 */ 703 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 704 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 705 }, 706 707 /* MCS 52 */ 708 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 709 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 710 }, 711 712 /* MCS 53 */ 713 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 714 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 715 }, 716 717 /* MCS 54 */ 718 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 719 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 720 }, 721 722 /* MCS 55 */ 723 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 724 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 725 }, 726 727 /* MCS 56 */ 728 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 729 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 730 }, 731 732 /* MCS 57 */ 733 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 734 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 735 }, 736 737 /* MCS 58 */ 738 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 739 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 740 }, 741 742 /* MCS 59 */ 743 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 744 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 745 }, 746 747 /* MCS 60 */ 748 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 749 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 750 }, 751 752 /* MCS 61 */ 753 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 754 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 755 }, 756 757 /* MCS 62 */ 758 { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, 759 /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, 760 }, 761 762 /* MCS 63 */ 763 { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, 764 /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, 765 }, 766 767 /* MCS 64 */ 768 { /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, }, 769 /* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, }, 770 }, 771 772 /* MCS 65 */ 773 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 774 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 775 }, 776 777 /* MCS 66 */ 778 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 779 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 780 }, 781 782 /* MCS 67 */ 783 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 784 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 785 }, 786 787 /* MCS 68 */ 788 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 789 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 790 }, 791 792 /* MCS 69 */ 793 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 794 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 795 }, 796 797 /* MCS 70 */ 798 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 799 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 800 }, 801 802 /* MCS 71 */ 803 { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, 804 /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, 805 }, 806 807 /* MCS 72 */ 808 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 809 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 810 }, 811 812 /* MCS 73 */ 813 { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, 814 /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, 815 }, 816 817 /* MCS 74 */ 818 { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, 819 /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, 820 }, 821 822 /* MCS 75 */ 823 { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, 824 /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, 825 }, 826 827 /* MCS 76 */ 828 { /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, }, 829 /* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, }, 830 }, 831 }; 832 833 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; 834 #define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0])) 835 836 static const char *status_text[] = { 837 "Successful", /* 0 */ 838 "Unspecified failure", /* 1 */ 839 "TDLS wakeup schedule rejected but alternative schedule " 840 "provided", /* 2 */ 841 "TDLS wakeup schedule rejected",/* 3 */ 842 "Reserved", /* 4 */ 843 "Security disabled", /* 5 */ 844 "Unacceptable lifetime", /* 6 */ 845 "Not in same BSS", /* 7 */ 846 "Reserved", /* 8 */ 847 "Reserved", /* 9 */ 848 "Cannot Support all requested capabilities in the Capability " 849 "Information field", /* 10 */ 850 "Reassociation denied due to inability to confirm that association " 851 "exists", /* 11 */ 852 "Association denied due to reason outside the scope of this " 853 "standard", /* 12 */ 854 "Responding STA does not support the specified authentication " 855 "algorithm", /* 13 */ 856 "Received an Authentication frame with authentication transaction " 857 "sequence number out of expected sequence", /* 14 */ 858 "Authentication rejected because of challenge failure", /* 15 */ 859 "Authentication rejected due to timeout waiting for next frame in " 860 "sequence", /* 16 */ 861 "Association denied because AP is unable to handle " 862 "additional associated STAs", /* 17 */ 863 "Association denied due to requesting STA not supporting " 864 "all of the data rates in the BSSBasicRateSet parameter, " 865 "the Basic HT-MCS Set field of the HT Operation " 866 "parameter, or the Basic VHT-MCS and NSS Set field in " 867 "the VHT Operation parameter", /* 18 */ 868 "Association denied due to requesting STA not supporting " 869 "the short preamble option", /* 19 */ 870 "Reserved", /* 20 */ 871 "Reserved", /* 21 */ 872 "Association request rejected because Spectrum Management " 873 "capability is required", /* 22 */ 874 "Association request rejected because the information in the " 875 "Power Capability element is unacceptable", /* 23 */ 876 "Association request rejected because the information in the " 877 "Supported Channels element is unacceptable", /* 24 */ 878 "Association denied due to requesting STA not supporting " 879 "the Short Slot Time option", /* 25 */ 880 "Reserved", /* 26 */ 881 "Association denied because the requested STA does not support HT " 882 "features", /* 27 */ 883 "R0KH unreachable", /* 28 */ 884 "Association denied because the requesting STA does not " 885 "support the phased coexistence operation (PCO) " 886 "transition time required by the AP", /* 29 */ 887 "Association request rejected temporarily; try again " 888 "later", /* 30 */ 889 "Robust management frame policy violation", /* 31 */ 890 "Unspecified, QoS-related failure", /* 32 */ 891 "Association denied because QoS AP or PCP has " 892 "insufficient bandwidth to handle another QoS " 893 "STA", /* 33 */ 894 "Association denied due to excessive frame loss rates and/or " 895 "poor conditions on current operating channel", /* 34 */ 896 "Association (with QoS BSS) denied because the requesting STA " 897 "does not support the QoS facility", /* 35 */ 898 "Reserved", /* 36 */ 899 "The request has been declined", /* 37 */ 900 "The request has not been successful as one or more parameters " 901 "have invalid values", /* 38 */ 902 "The allocation or TS has not been created because the request " 903 "cannot be honored; however, a suggested TSPEC/DMG TSPEC is " 904 "provided so that the initiating STA can attempt to set " 905 "another allocation or TS with the suggested changes to the " 906 "TSPEC/DMG TSPEC", /* 39 */ 907 "Invalid element, i.e., an element defined in this standard " 908 "for which the content does not meet the specifications in " 909 "Clause 9", /* 40 */ 910 "Invalid group cipher", /* 41 */ 911 "Invalid pairwise cipher", /* 42 */ 912 "Invalid AKMP", /* 43 */ 913 "Unsupported RSNE version", /* 44 */ 914 "Invalid RSNE capabilities", /* 45 */ 915 "Cipher suite rejected because of security policy", /* 46 */ 916 "The TS or allocation has not been created; however, the " 917 "HC or PCP might be capable of creating a TS or " 918 "allocation, in response to a request, after the time " 919 "indicated in the TS Delay element", /* 47 */ 920 "Direct Link is not allowed in the BSS by policy", /* 48 */ 921 "The Destination STA is not present within this BSS", /* 49 */ 922 "The Destination STA is not a QoS STA", /* 50 */ 923 924 "Association denied because the listen interval is " 925 "too large", /* 51 */ 926 "Invalid FT Action frame count", /* 52 */ 927 "Invalid pairwise master key identifier (PMKID)", /* 53 */ 928 "Invalid MDE", /* 54 */ 929 "Invalid FTE", /* 55 */ 930 "Requested TCLAS processing is not supported by the AP " 931 "or PCP", /* 56 */ 932 "The AP or PCP has insufficient TCLAS processing " 933 "resources to satisfy the request", /* 57 */ 934 "The TS has not been created because the request " 935 "cannot be honored; however, the HC or PCP suggests " 936 "that the STA transition to a different BSS to set up " 937 "the TS", /* 58 */ 938 "GAS Advertisement Protocol not supported", /* 59 */ 939 "No outstanding GAS request", /* 60 */ 940 "GAS Response not received from the Advertisement " 941 "Server", /* 61 */ 942 "STA timed out waiting for GAS Query Response", /* 62 */ 943 "LARGE GAS Response is larger than query response " 944 "length limit", /* 63 */ 945 "Request refused because home network does not support " 946 "request", /* 64 */ 947 "Advertisement Server in the network is not currently " 948 "reachable", /* 65 */ 949 "Reserved", /* 66 */ 950 "Request refused due to permissions received via SSPN " 951 "interface", /* 67 */ 952 "Request refused because the AP or PCP does not " 953 "support unauthenticated access", /* 68 */ 954 "Reserved", /* 69 */ 955 "Reserved", /* 70 */ 956 "Reserved", /* 71 */ 957 "Invalid contents of RSNE", /* 72 */ 958 "U-APSD coexistence is not supported", /* 73 */ 959 "Requested U-APSD coexistence mode is not supported", /* 74 */ 960 "Requested Interval/Duration value cannot be " 961 "supported with U-APSD coexistence", /* 75 */ 962 "Authentication is rejected because an Anti-Clogging " 963 "Token is required", /* 76 */ 964 "Authentication is rejected because the offered " 965 "finite cyclic group is not supported", /* 77 */ 966 "The TBTT adjustment request has not been successful " 967 "because the STA could not find an alternative TBTT", /* 78 */ 968 "Transmission failure", /* 79 */ 969 "Requested TCLAS Not Supported", /* 80 */ 970 "TCLAS Resources Exhausted", /* 81 */ 971 "Rejected with Suggested BSS transition", /* 82 */ 972 "Reject with recommended schedule", /* 83 */ 973 "Reject because no wakeup schedule specified", /* 84 */ 974 "Success, the destination STA is in power save mode", /* 85 */ 975 "FST pending, in process of admitting FST session", /* 86 */ 976 "Performing FST now", /* 87 */ 977 "FST pending, gap(s) in block ack window", /* 88 */ 978 "Reject because of U-PID setting", /* 89 */ 979 "Reserved", /* 90 */ 980 "Reserved", /* 91 */ 981 "(Re)Association refused for some external reason", /* 92 */ 982 "(Re)Association refused because of memory limits " 983 "at the AP", /* 93 */ 984 "(Re)Association refused because emergency services " 985 "are not supported at the AP", /* 94 */ 986 "GAS query response not yet received", /* 95 */ 987 "Reject since the request is for transition to a " 988 "frequency band subject to DSE procedures and " 989 "FST Initiator is a dependent STA", /* 96 */ 990 "Requested TCLAS processing has been terminated by " 991 "the AP", /* 97 */ 992 "The TS schedule conflicts with an existing " 993 "schedule; an alternative schedule is provided", /* 98 */ 994 "The association has been denied; however, one or " 995 "more Multi-band elements are included that can " 996 "be used by the receiving STA to join the BSS", /* 99 */ 997 "The request failed due to a reservation conflict", /* 100 */ 998 "The request failed due to exceeded MAF limit", /* 101 */ 999 "The request failed due to exceeded MCCA track " 1000 "limit", /* 102 */ 1001 "Association denied because the information in the" 1002 "Spectrum Management field is unacceptable", /* 103 */ 1003 "Association denied because the requesting STA " 1004 "does not support VHT features", /* 104 */ 1005 "Enablement denied", /* 105 */ 1006 "Enablement denied due to restriction from an " 1007 "authorized GDB", /* 106 */ 1008 "Authorization deenabled", /* 107 */ 1009 }; 1010 #define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0])) 1011 1012 static const char *reason_text[] = { 1013 "Reserved", /* 0 */ 1014 "Unspecified reason", /* 1 */ 1015 "Previous authentication no longer valid", /* 2 */ 1016 "Deauthenticated because sending STA is leaving (or has left) " 1017 "IBSS or ESS", /* 3 */ 1018 "Disassociated due to inactivity", /* 4 */ 1019 "Disassociated because AP is unable to handle all currently " 1020 " associated STAs", /* 5 */ 1021 "Class 2 frame received from nonauthenticated STA", /* 6 */ 1022 "Class 3 frame received from nonassociated STA", /* 7 */ 1023 "Disassociated because sending STA is leaving " 1024 "(or has left) BSS", /* 8 */ 1025 "STA requesting (re)association is not authenticated with " 1026 "responding STA", /* 9 */ 1027 "Disassociated because the information in the Power Capability " 1028 "element is unacceptable", /* 10 */ 1029 "Disassociated because the information in the Supported Channels " 1030 "element is unacceptable", /* 11 */ 1031 "Disassociated due to BSS transition management", /* 12 */ 1032 "Invalid element, i.e., an element defined in this standard for " 1033 "which the content does not meet the specifications " 1034 "in Clause 9", /* 13 */ 1035 "Message integrity code (MIC) failure", /* 14 */ 1036 "4-Way Handshake timeout", /* 15 */ 1037 "Group key handshake timeout", /* 16 */ 1038 "Information element in 4-Way Handshake different from (Re)Association" 1039 "Request/Probe Response/Beacon frame", /* 17 */ 1040 "Invalid group cipher", /* 18 */ 1041 "Invalid pairwise cipher", /* 19 */ 1042 "Invalid AKMP", /* 20 */ 1043 "Unsupported RSNE version", /* 21 */ 1044 "Invalid RSNE capabilities", /* 22 */ 1045 "IEEE 802.1X authentication failed", /* 23 */ 1046 "Cipher suite rejected because of the security policy", /* 24 */ 1047 "TDLS direct-link teardown due to TDLS peer STA " 1048 "unreachable via the TDLS direct link", /* 25 */ 1049 "TDLS direct-link teardown for unspecified reason", /* 26 */ 1050 "Disassociated because session terminated by SSP request",/* 27 */ 1051 "Disassociated because of lack of SSP roaming agreement",/* 28 */ 1052 "Requested service rejected because of SSP cipher suite or " 1053 "AKM requirement", /* 29 */ 1054 "Requested service not authorized in this location", /* 30 */ 1055 "TS deleted because QoS AP lacks sufficient bandwidth for this " 1056 "QoS STA due to a change in BSS service characteristics or " 1057 "operational mode (e.g. an HT BSS change from 40 MHz channel " 1058 "to 20 MHz channel)", /* 31 */ 1059 "Disassociated for unspecified, QoS-related reason", /* 32 */ 1060 "Disassociated because QoS AP lacks sufficient bandwidth for this " 1061 "QoS STA", /* 33 */ 1062 "Disassociated because of excessive number of frames that need to be " 1063 "acknowledged, but are not acknowledged due to AP transmissions " 1064 "and/or poor channel conditions", /* 34 */ 1065 "Disassociated because STA is transmitting outside the limits " 1066 "of its TXOPs", /* 35 */ 1067 "Requested from peer STA as the STA is leaving the BSS " 1068 "(or resetting)", /* 36 */ 1069 "Requested from peer STA as it does not want to use the " 1070 "mechanism", /* 37 */ 1071 "Requested from peer STA as the STA received frames using the " 1072 "mechanism for which a set up is required", /* 38 */ 1073 "Requested from peer STA due to time out", /* 39 */ 1074 "Reserved", /* 40 */ 1075 "Reserved", /* 41 */ 1076 "Reserved", /* 42 */ 1077 "Reserved", /* 43 */ 1078 "Reserved", /* 44 */ 1079 "Peer STA does not support the requested cipher suite", /* 45 */ 1080 "In a DLS Teardown frame: The teardown was initiated by the " 1081 "DLS peer. In a Disassociation frame: Disassociated because " 1082 "authorized access limit reached", /* 46 */ 1083 "In a DLS Teardown frame: The teardown was initiated by the " 1084 "AP. In a Disassociation frame: Disassociated due to external " 1085 "service requirements", /* 47 */ 1086 "Invalid FT Action frame count", /* 48 */ 1087 "Invalid pairwise master key identifier (PMKID)", /* 49 */ 1088 "Invalid MDE", /* 50 */ 1089 "Invalid FTE", /* 51 */ 1090 "Mesh peering canceled for unknown reasons", /* 52 */ 1091 "The mesh STA has reached the supported maximum number of " 1092 "peer mesh STAs", /* 53 */ 1093 "The received information violates the Mesh Configuration " 1094 "policy configured in the mesh STA profile", /* 54 */ 1095 "The mesh STA has received a Mesh Peering Close frame " 1096 "requesting to close the mesh peering", /* 55 */ 1097 "The mesh STA has resent dot11MeshMaxRetries Mesh " 1098 "Peering Open frames, without receiving a Mesh Peering " 1099 "Confirm frame", /* 56 */ 1100 "The confirmTimer for the mesh peering instance times out", /* 57 */ 1101 "The mesh STA fails to unwrap the GTK or the values in the " 1102 "wrapped contents do not match", /* 58 */ 1103 "The mesh STA receives inconsistent information about the " 1104 "mesh parameters between mesh peering Management frames", /* 59 */ 1105 "The mesh STA fails the authenticated mesh peering exchange " 1106 "because due to failure in selecting either the pairwise " 1107 "ciphersuite or group ciphersuite", /* 60 */ 1108 "The mesh STA does not have proxy information for this " 1109 "external destination", /* 61 */ 1110 "The mesh STA does not have forwarding information for this " 1111 "destination", /* 62 */ 1112 "The mesh STA determines that the link to the next hop of an " 1113 "active path in its forwarding information is no longer " 1114 "usable", /* 63 */ 1115 "The Deauthentication frame was sent because the MAC " 1116 "address of the STA already exists in the mesh BSS", /* 64 */ 1117 "The mesh STA performs channel switch to meet regulatory " 1118 "requirements", /* 65 */ 1119 "The mesh STA performs channel switching with unspecified " 1120 "reason", /* 66 */ 1121 }; 1122 #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0])) 1123 1124 static int 1125 wep_print(netdissect_options *ndo, 1126 const u_char *p) 1127 { 1128 uint32_t iv; 1129 1130 ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN); 1131 iv = GET_LE_U_4(p); 1132 1133 ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), 1134 IV_KEYID(iv)); 1135 1136 return 1; 1137 trunc: 1138 return 0; 1139 } 1140 1141 static int 1142 parse_elements(netdissect_options *ndo, 1143 struct mgmt_body_t *pbody, const u_char *p, int offset, 1144 u_int length) 1145 { 1146 u_int elementlen; 1147 struct ssid_t ssid; 1148 struct challenge_t challenge; 1149 struct rates_t rates; 1150 struct ds_t ds; 1151 struct cf_t cf; 1152 struct tim_t tim; 1153 1154 /* 1155 * We haven't seen any elements yet. 1156 */ 1157 pbody->challenge_present = 0; 1158 pbody->ssid_present = 0; 1159 pbody->rates_present = 0; 1160 pbody->ds_present = 0; 1161 pbody->cf_present = 0; 1162 pbody->tim_present = 0; 1163 1164 while (length != 0) { 1165 /* Make sure we at least have the element ID and length. */ 1166 ND_TCHECK_2(p + offset); 1167 if (length < 2) 1168 goto trunc; 1169 elementlen = GET_U_1(p + offset + 1); 1170 1171 /* Make sure we have the entire element. */ 1172 ND_TCHECK_LEN(p + offset + 2, elementlen); 1173 if (length < elementlen + 2) 1174 goto trunc; 1175 1176 switch (GET_U_1(p + offset)) { 1177 case E_SSID: 1178 memcpy(&ssid, p + offset, 2); 1179 offset += 2; 1180 length -= 2; 1181 if (ssid.length != 0) { 1182 if (ssid.length > sizeof(ssid.ssid) - 1) 1183 return 0; 1184 memcpy(&ssid.ssid, p + offset, ssid.length); 1185 offset += ssid.length; 1186 length -= ssid.length; 1187 } 1188 ssid.ssid[ssid.length] = '\0'; 1189 /* 1190 * Present and not truncated. 1191 * 1192 * If we haven't already seen an SSID IE, 1193 * copy this one, otherwise ignore this one, 1194 * so we later report the first one we saw. 1195 */ 1196 if (!pbody->ssid_present) { 1197 pbody->ssid = ssid; 1198 pbody->ssid_present = 1; 1199 } 1200 break; 1201 case E_CHALLENGE: 1202 memcpy(&challenge, p + offset, 2); 1203 offset += 2; 1204 length -= 2; 1205 if (challenge.length != 0) { 1206 if (challenge.length > 1207 sizeof(challenge.text) - 1) 1208 return 0; 1209 memcpy(&challenge.text, p + offset, 1210 challenge.length); 1211 offset += challenge.length; 1212 length -= challenge.length; 1213 } 1214 challenge.text[challenge.length] = '\0'; 1215 /* 1216 * Present and not truncated. 1217 * 1218 * If we haven't already seen a challenge IE, 1219 * copy this one, otherwise ignore this one, 1220 * so we later report the first one we saw. 1221 */ 1222 if (!pbody->challenge_present) { 1223 pbody->challenge = challenge; 1224 pbody->challenge_present = 1; 1225 } 1226 break; 1227 case E_RATES: 1228 memcpy(&rates, p + offset, 2); 1229 offset += 2; 1230 length -= 2; 1231 if (rates.length != 0) { 1232 if (rates.length > sizeof(rates.rate)) 1233 return 0; 1234 memcpy(&rates.rate, p + offset, rates.length); 1235 offset += rates.length; 1236 length -= rates.length; 1237 } 1238 /* 1239 * Present and not truncated. 1240 * 1241 * If we haven't already seen a rates IE, 1242 * copy this one if it's not zero-length, 1243 * otherwise ignore this one, so we later 1244 * report the first one we saw. 1245 * 1246 * We ignore zero-length rates IEs as some 1247 * devices seem to put a zero-length rates 1248 * IE, followed by an SSID IE, followed by 1249 * a non-zero-length rates IE into frames, 1250 * even though IEEE Std 802.11-2007 doesn't 1251 * seem to indicate that a zero-length rates 1252 * IE is valid. 1253 */ 1254 if (!pbody->rates_present && rates.length != 0) { 1255 pbody->rates = rates; 1256 pbody->rates_present = 1; 1257 } 1258 break; 1259 case E_DS: 1260 memcpy(&ds, p + offset, 2); 1261 offset += 2; 1262 length -= 2; 1263 if (ds.length != 1) { 1264 offset += ds.length; 1265 length -= ds.length; 1266 break; 1267 } 1268 ds.channel = GET_U_1(p + offset); 1269 offset += 1; 1270 length -= 1; 1271 /* 1272 * Present and not truncated. 1273 * 1274 * If we haven't already seen a DS IE, 1275 * copy this one, otherwise ignore this one, 1276 * so we later report the first one we saw. 1277 */ 1278 if (!pbody->ds_present) { 1279 pbody->ds = ds; 1280 pbody->ds_present = 1; 1281 } 1282 break; 1283 case E_CF: 1284 memcpy(&cf, p + offset, 2); 1285 offset += 2; 1286 length -= 2; 1287 if (cf.length != 6) { 1288 offset += cf.length; 1289 length -= cf.length; 1290 break; 1291 } 1292 cf.count = GET_U_1(p + offset); 1293 offset += 1; 1294 length -= 1; 1295 cf.period = GET_U_1(p + offset); 1296 offset += 1; 1297 length -= 1; 1298 cf.max_duration = GET_LE_U_2(p + offset); 1299 offset += 2; 1300 length -= 2; 1301 cf.dur_remaining = GET_LE_U_2(p + offset); 1302 offset += 2; 1303 length -= 2; 1304 /* 1305 * Present and not truncated. 1306 * 1307 * If we haven't already seen a CF IE, 1308 * copy this one, otherwise ignore this one, 1309 * so we later report the first one we saw. 1310 */ 1311 if (!pbody->cf_present) { 1312 pbody->cf = cf; 1313 pbody->cf_present = 1; 1314 } 1315 break; 1316 case E_TIM: 1317 memcpy(&tim, p + offset, 2); 1318 offset += 2; 1319 length -= 2; 1320 if (tim.length <= 3U) { 1321 offset += tim.length; 1322 length -= tim.length; 1323 break; 1324 } 1325 if (tim.length - 3U > sizeof(tim.bitmap)) 1326 return 0; 1327 tim.count = GET_U_1(p + offset); 1328 offset += 1; 1329 length -= 1; 1330 tim.period = GET_U_1(p + offset); 1331 offset += 1; 1332 length -= 1; 1333 tim.bitmap_control = GET_U_1(p + offset); 1334 offset += 1; 1335 length -= 1; 1336 memcpy(tim.bitmap, p + offset, tim.length - 3); 1337 offset += tim.length - 3; 1338 length -= tim.length - 3; 1339 /* 1340 * Present and not truncated. 1341 * 1342 * If we haven't already seen a TIM IE, 1343 * copy this one, otherwise ignore this one, 1344 * so we later report the first one we saw. 1345 */ 1346 if (!pbody->tim_present) { 1347 pbody->tim = tim; 1348 pbody->tim_present = 1; 1349 } 1350 break; 1351 default: 1352 #if 0 1353 ND_PRINT("(1) unhandled element_id (%u) ", 1354 GET_U_1(p + offset)); 1355 #endif 1356 offset += 2 + elementlen; 1357 length -= 2 + elementlen; 1358 break; 1359 } 1360 } 1361 1362 /* No problems found. */ 1363 return 1; 1364 trunc: 1365 return 0; 1366 } 1367 1368 /********************************************************************************* 1369 * Print Handle functions for the management frame types 1370 *********************************************************************************/ 1371 1372 static int 1373 handle_beacon(netdissect_options *ndo, 1374 const u_char *p, u_int length) 1375 { 1376 struct mgmt_body_t pbody; 1377 int offset = 0; 1378 int ret; 1379 1380 memset(&pbody, 0, sizeof(pbody)); 1381 1382 ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1383 IEEE802_11_CAPINFO_LEN); 1384 if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1385 IEEE802_11_CAPINFO_LEN) 1386 goto trunc; 1387 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); 1388 offset += IEEE802_11_TSTAMP_LEN; 1389 length -= IEEE802_11_TSTAMP_LEN; 1390 pbody.beacon_interval = GET_LE_U_2(p + offset); 1391 offset += IEEE802_11_BCNINT_LEN; 1392 length -= IEEE802_11_BCNINT_LEN; 1393 pbody.capability_info = GET_LE_U_2(p + offset); 1394 offset += IEEE802_11_CAPINFO_LEN; 1395 length -= IEEE802_11_CAPINFO_LEN; 1396 1397 ret = parse_elements(ndo, &pbody, p, offset, length); 1398 1399 PRINT_SSID(pbody); 1400 PRINT_RATES(pbody); 1401 ND_PRINT(" %s", 1402 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS"); 1403 PRINT_DS_CHANNEL(pbody); 1404 1405 return ret; 1406 trunc: 1407 return 0; 1408 } 1409 1410 static int 1411 handle_assoc_request(netdissect_options *ndo, 1412 const u_char *p, u_int length) 1413 { 1414 struct mgmt_body_t pbody; 1415 int offset = 0; 1416 int ret; 1417 1418 memset(&pbody, 0, sizeof(pbody)); 1419 1420 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN); 1421 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN) 1422 goto trunc; 1423 pbody.capability_info = GET_LE_U_2(p); 1424 offset += IEEE802_11_CAPINFO_LEN; 1425 length -= IEEE802_11_CAPINFO_LEN; 1426 pbody.listen_interval = GET_LE_U_2(p + offset); 1427 offset += IEEE802_11_LISTENINT_LEN; 1428 length -= IEEE802_11_LISTENINT_LEN; 1429 1430 ret = parse_elements(ndo, &pbody, p, offset, length); 1431 1432 PRINT_SSID(pbody); 1433 PRINT_RATES(pbody); 1434 return ret; 1435 trunc: 1436 return 0; 1437 } 1438 1439 static int 1440 handle_assoc_response(netdissect_options *ndo, 1441 const u_char *p, u_int length) 1442 { 1443 struct mgmt_body_t pbody; 1444 int offset = 0; 1445 int ret; 1446 1447 memset(&pbody, 0, sizeof(pbody)); 1448 1449 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + 1450 IEEE802_11_AID_LEN); 1451 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + 1452 IEEE802_11_AID_LEN) 1453 goto trunc; 1454 pbody.capability_info = GET_LE_U_2(p); 1455 offset += IEEE802_11_CAPINFO_LEN; 1456 length -= IEEE802_11_CAPINFO_LEN; 1457 pbody.status_code = GET_LE_U_2(p + offset); 1458 offset += IEEE802_11_STATUS_LEN; 1459 length -= IEEE802_11_STATUS_LEN; 1460 pbody.aid = GET_LE_U_2(p + offset); 1461 offset += IEEE802_11_AID_LEN; 1462 length -= IEEE802_11_AID_LEN; 1463 1464 ret = parse_elements(ndo, &pbody, p, offset, length); 1465 1466 ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 , 1467 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "", 1468 (pbody.status_code < NUM_STATUSES 1469 ? status_text[pbody.status_code] 1470 : "n/a")); 1471 1472 return ret; 1473 trunc: 1474 return 0; 1475 } 1476 1477 static int 1478 handle_reassoc_request(netdissect_options *ndo, 1479 const u_char *p, u_int length) 1480 { 1481 struct mgmt_body_t pbody; 1482 int offset = 0; 1483 int ret; 1484 1485 memset(&pbody, 0, sizeof(pbody)); 1486 1487 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + 1488 IEEE802_11_AP_LEN); 1489 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + 1490 IEEE802_11_AP_LEN) 1491 goto trunc; 1492 pbody.capability_info = GET_LE_U_2(p); 1493 offset += IEEE802_11_CAPINFO_LEN; 1494 length -= IEEE802_11_CAPINFO_LEN; 1495 pbody.listen_interval = GET_LE_U_2(p + offset); 1496 offset += IEEE802_11_LISTENINT_LEN; 1497 length -= IEEE802_11_LISTENINT_LEN; 1498 memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN); 1499 offset += IEEE802_11_AP_LEN; 1500 length -= IEEE802_11_AP_LEN; 1501 1502 ret = parse_elements(ndo, &pbody, p, offset, length); 1503 1504 PRINT_SSID(pbody); 1505 ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap )); 1506 1507 return ret; 1508 trunc: 1509 return 0; 1510 } 1511 1512 static int 1513 handle_reassoc_response(netdissect_options *ndo, 1514 const u_char *p, u_int length) 1515 { 1516 /* Same as a Association Response */ 1517 return handle_assoc_response(ndo, p, length); 1518 } 1519 1520 static int 1521 handle_probe_request(netdissect_options *ndo, 1522 const u_char *p, u_int length) 1523 { 1524 struct mgmt_body_t pbody; 1525 int offset = 0; 1526 int ret; 1527 1528 memset(&pbody, 0, sizeof(pbody)); 1529 1530 ret = parse_elements(ndo, &pbody, p, offset, length); 1531 1532 PRINT_SSID(pbody); 1533 PRINT_RATES(pbody); 1534 1535 return ret; 1536 } 1537 1538 static int 1539 handle_probe_response(netdissect_options *ndo, 1540 const u_char *p, u_int length) 1541 { 1542 struct mgmt_body_t pbody; 1543 int offset = 0; 1544 int ret; 1545 1546 memset(&pbody, 0, sizeof(pbody)); 1547 1548 ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1549 IEEE802_11_CAPINFO_LEN); 1550 if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1551 IEEE802_11_CAPINFO_LEN) 1552 goto trunc; 1553 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); 1554 offset += IEEE802_11_TSTAMP_LEN; 1555 length -= IEEE802_11_TSTAMP_LEN; 1556 pbody.beacon_interval = GET_LE_U_2(p + offset); 1557 offset += IEEE802_11_BCNINT_LEN; 1558 length -= IEEE802_11_BCNINT_LEN; 1559 pbody.capability_info = GET_LE_U_2(p + offset); 1560 offset += IEEE802_11_CAPINFO_LEN; 1561 length -= IEEE802_11_CAPINFO_LEN; 1562 1563 ret = parse_elements(ndo, &pbody, p, offset, length); 1564 1565 PRINT_SSID(pbody); 1566 PRINT_RATES(pbody); 1567 PRINT_DS_CHANNEL(pbody); 1568 1569 return ret; 1570 trunc: 1571 return 0; 1572 } 1573 1574 static int 1575 handle_atim(void) 1576 { 1577 /* the frame body for ATIM is null. */ 1578 return 1; 1579 } 1580 1581 static int 1582 handle_disassoc(netdissect_options *ndo, 1583 const u_char *p, u_int length) 1584 { 1585 struct mgmt_body_t pbody; 1586 1587 memset(&pbody, 0, sizeof(pbody)); 1588 1589 ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN); 1590 if (length < IEEE802_11_REASON_LEN) 1591 goto trunc; 1592 pbody.reason_code = GET_LE_U_2(p); 1593 1594 ND_PRINT(": %s", 1595 (pbody.reason_code < NUM_REASONS) 1596 ? reason_text[pbody.reason_code] 1597 : "Reserved"); 1598 1599 return 1; 1600 trunc: 1601 return 0; 1602 } 1603 1604 static int 1605 handle_auth(netdissect_options *ndo, 1606 const u_char *p, u_int length) 1607 { 1608 struct mgmt_body_t pbody; 1609 int offset = 0; 1610 int ret; 1611 1612 memset(&pbody, 0, sizeof(pbody)); 1613 1614 ND_TCHECK_6(p); 1615 if (length < 6) 1616 goto trunc; 1617 pbody.auth_alg = GET_LE_U_2(p); 1618 offset += 2; 1619 length -= 2; 1620 pbody.auth_trans_seq_num = GET_LE_U_2(p + offset); 1621 offset += 2; 1622 length -= 2; 1623 pbody.status_code = GET_LE_U_2(p + offset); 1624 offset += 2; 1625 length -= 2; 1626 1627 ret = parse_elements(ndo, &pbody, p, offset, length); 1628 1629 if ((pbody.auth_alg == 1) && 1630 ((pbody.auth_trans_seq_num == 2) || 1631 (pbody.auth_trans_seq_num == 3))) { 1632 ND_PRINT(" (%s)-%x [Challenge Text] %s", 1633 (pbody.auth_alg < NUM_AUTH_ALGS) 1634 ? auth_alg_text[pbody.auth_alg] 1635 : "Reserved", 1636 pbody.auth_trans_seq_num, 1637 ((pbody.auth_trans_seq_num % 2) 1638 ? ((pbody.status_code < NUM_STATUSES) 1639 ? status_text[pbody.status_code] 1640 : "n/a") : "")); 1641 return ret; 1642 } 1643 ND_PRINT(" (%s)-%x: %s", 1644 (pbody.auth_alg < NUM_AUTH_ALGS) 1645 ? auth_alg_text[pbody.auth_alg] 1646 : "Reserved", 1647 pbody.auth_trans_seq_num, 1648 (pbody.auth_trans_seq_num % 2) 1649 ? ((pbody.status_code < NUM_STATUSES) 1650 ? status_text[pbody.status_code] 1651 : "n/a") 1652 : ""); 1653 1654 return ret; 1655 trunc: 1656 return 0; 1657 } 1658 1659 static int 1660 handle_deauth(netdissect_options *ndo, 1661 const uint8_t *src, const u_char *p, u_int length) 1662 { 1663 struct mgmt_body_t pbody; 1664 const char *reason = NULL; 1665 1666 memset(&pbody, 0, sizeof(pbody)); 1667 1668 ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN); 1669 if (length < IEEE802_11_REASON_LEN) 1670 goto trunc; 1671 pbody.reason_code = GET_LE_U_2(p); 1672 1673 reason = (pbody.reason_code < NUM_REASONS) 1674 ? reason_text[pbody.reason_code] 1675 : "Reserved"; 1676 1677 if (ndo->ndo_eflag) { 1678 ND_PRINT(": %s", reason); 1679 } else { 1680 ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason); 1681 } 1682 return 1; 1683 trunc: 1684 return 0; 1685 } 1686 1687 #define PRINT_HT_ACTION(v) (\ 1688 (v) == 0 ? ND_PRINT("TxChWidth"): \ 1689 (v) == 1 ? ND_PRINT("MIMOPwrSave"): \ 1690 ND_PRINT("Act#%u", (v))) 1691 #define PRINT_BA_ACTION(v) (\ 1692 (v) == 0 ? ND_PRINT("ADDBA Request"): \ 1693 (v) == 1 ? ND_PRINT("ADDBA Response"): \ 1694 (v) == 2 ? ND_PRINT("DELBA"): \ 1695 ND_PRINT("Act#%u", (v))) 1696 #define PRINT_MESHLINK_ACTION(v) (\ 1697 (v) == 0 ? ND_PRINT("Request"): \ 1698 (v) == 1 ? ND_PRINT("Report"): \ 1699 ND_PRINT("Act#%u", (v))) 1700 #define PRINT_MESHPEERING_ACTION(v) (\ 1701 (v) == 0 ? ND_PRINT("Open"): \ 1702 (v) == 1 ? ND_PRINT("Confirm"): \ 1703 (v) == 2 ? ND_PRINT("Close"): \ 1704 ND_PRINT("Act#%u", (v))) 1705 #define PRINT_MESHPATH_ACTION(v) (\ 1706 (v) == 0 ? ND_PRINT("Request"): \ 1707 (v) == 1 ? ND_PRINT("Report"): \ 1708 (v) == 2 ? ND_PRINT("Error"): \ 1709 (v) == 3 ? ND_PRINT("RootAnnouncement"): \ 1710 ND_PRINT("Act#%u", (v))) 1711 1712 #define PRINT_MESH_ACTION(v) (\ 1713 (v) == 0 ? ND_PRINT("MeshLink"): \ 1714 (v) == 1 ? ND_PRINT("HWMP"): \ 1715 (v) == 2 ? ND_PRINT("Gate Announcement"): \ 1716 (v) == 3 ? ND_PRINT("Congestion Control"): \ 1717 (v) == 4 ? ND_PRINT("MCCA Setup Request"): \ 1718 (v) == 5 ? ND_PRINT("MCCA Setup Reply"): \ 1719 (v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \ 1720 (v) == 7 ? ND_PRINT("MCCA Advertisement"): \ 1721 (v) == 8 ? ND_PRINT("MCCA Teardown"): \ 1722 (v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \ 1723 (v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \ 1724 ND_PRINT("Act#%u", (v))) 1725 #define PRINT_MULTIHOP_ACTION(v) (\ 1726 (v) == 0 ? ND_PRINT("Proxy Update"): \ 1727 (v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \ 1728 ND_PRINT("Act#%u", (v))) 1729 #define PRINT_SELFPROT_ACTION(v) (\ 1730 (v) == 1 ? ND_PRINT("Peering Open"): \ 1731 (v) == 2 ? ND_PRINT("Peering Confirm"): \ 1732 (v) == 3 ? ND_PRINT("Peering Close"): \ 1733 (v) == 4 ? ND_PRINT("Group Key Inform"): \ 1734 (v) == 5 ? ND_PRINT("Group Key Acknowledge"): \ 1735 ND_PRINT("Act#%u", (v))) 1736 1737 static int 1738 handle_action(netdissect_options *ndo, 1739 const uint8_t *src, const u_char *p, u_int length) 1740 { 1741 ND_TCHECK_2(p); 1742 if (length < 2) 1743 goto trunc; 1744 if (ndo->ndo_eflag) { 1745 ND_PRINT(": "); 1746 } else { 1747 ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src)); 1748 } 1749 switch (GET_U_1(p)) { 1750 case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break; 1751 case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break; 1752 case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break; 1753 case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break; 1754 case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break; 1755 case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break; 1756 case 14: 1757 ND_PRINT("MultiohopAction "); 1758 PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break; 1759 case 15: 1760 ND_PRINT("SelfprotectAction "); 1761 PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break; 1762 case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break; 1763 default: 1764 ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1)); 1765 break; 1766 } 1767 return 1; 1768 trunc: 1769 return 0; 1770 } 1771 1772 1773 /********************************************************************************* 1774 * Print Body funcs 1775 *********************************************************************************/ 1776 1777 1778 static int 1779 mgmt_body_print(netdissect_options *ndo, 1780 uint16_t fc, const uint8_t *src, const u_char *p, u_int length) 1781 { 1782 ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc))); 1783 1784 /* There may be a problem w/ AP not having this bit set */ 1785 if (FC_PROTECTED(fc)) 1786 return wep_print(ndo, p); 1787 switch (FC_SUBTYPE(fc)) { 1788 case ST_ASSOC_REQUEST: 1789 return handle_assoc_request(ndo, p, length); 1790 case ST_ASSOC_RESPONSE: 1791 return handle_assoc_response(ndo, p, length); 1792 case ST_REASSOC_REQUEST: 1793 return handle_reassoc_request(ndo, p, length); 1794 case ST_REASSOC_RESPONSE: 1795 return handle_reassoc_response(ndo, p, length); 1796 case ST_PROBE_REQUEST: 1797 return handle_probe_request(ndo, p, length); 1798 case ST_PROBE_RESPONSE: 1799 return handle_probe_response(ndo, p, length); 1800 case ST_BEACON: 1801 return handle_beacon(ndo, p, length); 1802 case ST_ATIM: 1803 return handle_atim(); 1804 case ST_DISASSOC: 1805 return handle_disassoc(ndo, p, length); 1806 case ST_AUTH: 1807 return handle_auth(ndo, p, length); 1808 case ST_DEAUTH: 1809 return handle_deauth(ndo, src, p, length); 1810 case ST_ACTION: 1811 return handle_action(ndo, src, p, length); 1812 default: 1813 return 1; 1814 } 1815 } 1816 1817 1818 /********************************************************************************* 1819 * Handles printing all the control frame types 1820 *********************************************************************************/ 1821 1822 static int 1823 ctrl_body_print(netdissect_options *ndo, 1824 uint16_t fc, const u_char *p) 1825 { 1826 ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc))); 1827 switch (FC_SUBTYPE(fc)) { 1828 case CTRL_CONTROL_WRAPPER: 1829 /* XXX - requires special handling */ 1830 break; 1831 case CTRL_BAR: 1832 ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN); 1833 if (!ndo->ndo_eflag) 1834 ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ", 1835 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra), 1836 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta), 1837 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl), 1838 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq)); 1839 break; 1840 case CTRL_BA: 1841 ND_TCHECK_LEN(p, CTRL_BA_HDRLEN); 1842 if (!ndo->ndo_eflag) 1843 ND_PRINT(" RA:%s ", 1844 GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra)); 1845 break; 1846 case CTRL_PS_POLL: 1847 ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN); 1848 ND_PRINT(" AID(%x)", 1849 GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid)); 1850 break; 1851 case CTRL_RTS: 1852 ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN); 1853 if (!ndo->ndo_eflag) 1854 ND_PRINT(" TA:%s ", 1855 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta)); 1856 break; 1857 case CTRL_CTS: 1858 ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN); 1859 if (!ndo->ndo_eflag) 1860 ND_PRINT(" RA:%s ", 1861 GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra)); 1862 break; 1863 case CTRL_ACK: 1864 ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN); 1865 if (!ndo->ndo_eflag) 1866 ND_PRINT(" RA:%s ", 1867 GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra)); 1868 break; 1869 case CTRL_CF_END: 1870 ND_TCHECK_LEN(p, CTRL_END_HDRLEN); 1871 if (!ndo->ndo_eflag) 1872 ND_PRINT(" RA:%s ", 1873 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra)); 1874 break; 1875 case CTRL_END_ACK: 1876 ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN); 1877 if (!ndo->ndo_eflag) 1878 ND_PRINT(" RA:%s ", 1879 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra)); 1880 break; 1881 } 1882 return 1; 1883 trunc: 1884 return 0; 1885 } 1886 1887 /* 1888 * Data Frame - Address field contents 1889 * 1890 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4 1891 * 0 | 0 | DA | SA | BSSID | n/a 1892 * 0 | 1 | DA | BSSID | SA | n/a 1893 * 1 | 0 | BSSID | SA | DA | n/a 1894 * 1 | 1 | RA | TA | DA | SA 1895 */ 1896 1897 /* 1898 * Function to get source and destination MAC addresses for a data frame. 1899 */ 1900 static void 1901 get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp, 1902 const uint8_t **dstp) 1903 { 1904 #define ADDR1 (p + 4) 1905 #define ADDR2 (p + 10) 1906 #define ADDR3 (p + 16) 1907 #define ADDR4 (p + 24) 1908 1909 if (!FC_TO_DS(fc)) { 1910 if (!FC_FROM_DS(fc)) { 1911 /* not To DS and not From DS */ 1912 *srcp = ADDR2; 1913 *dstp = ADDR1; 1914 } else { 1915 /* not To DS and From DS */ 1916 *srcp = ADDR3; 1917 *dstp = ADDR1; 1918 } 1919 } else { 1920 if (!FC_FROM_DS(fc)) { 1921 /* To DS and not From DS */ 1922 *srcp = ADDR2; 1923 *dstp = ADDR3; 1924 } else { 1925 /* To DS and From DS */ 1926 *srcp = ADDR4; 1927 *dstp = ADDR3; 1928 } 1929 } 1930 1931 #undef ADDR1 1932 #undef ADDR2 1933 #undef ADDR3 1934 #undef ADDR4 1935 } 1936 1937 static void 1938 get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp) 1939 { 1940 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 1941 1942 if (srcp != NULL) 1943 *srcp = hp->sa; 1944 if (dstp != NULL) 1945 *dstp = hp->da; 1946 } 1947 1948 /* 1949 * Print Header funcs 1950 */ 1951 1952 static void 1953 data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) 1954 { 1955 u_int subtype = FC_SUBTYPE(fc); 1956 1957 if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) || 1958 DATA_FRAME_IS_QOS(subtype)) { 1959 ND_PRINT("CF "); 1960 if (DATA_FRAME_IS_CF_ACK(subtype)) { 1961 if (DATA_FRAME_IS_CF_POLL(subtype)) 1962 ND_PRINT("Ack/Poll"); 1963 else 1964 ND_PRINT("Ack"); 1965 } else { 1966 if (DATA_FRAME_IS_CF_POLL(subtype)) 1967 ND_PRINT("Poll"); 1968 } 1969 if (DATA_FRAME_IS_QOS(subtype)) 1970 ND_PRINT("+QoS"); 1971 ND_PRINT(" "); 1972 } 1973 1974 #define ADDR1 (p + 4) 1975 #define ADDR2 (p + 10) 1976 #define ADDR3 (p + 16) 1977 #define ADDR4 (p + 24) 1978 1979 if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) { 1980 ND_PRINT("DA:%s SA:%s BSSID:%s ", 1981 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1982 GET_ETHERADDR_STRING(ADDR3)); 1983 } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) { 1984 ND_PRINT("DA:%s BSSID:%s SA:%s ", 1985 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1986 GET_ETHERADDR_STRING(ADDR3)); 1987 } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) { 1988 ND_PRINT("BSSID:%s SA:%s DA:%s ", 1989 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1990 GET_ETHERADDR_STRING(ADDR3)); 1991 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { 1992 ND_PRINT("RA:%s TA:%s DA:%s SA:%s ", 1993 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1994 GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4)); 1995 } 1996 1997 #undef ADDR1 1998 #undef ADDR2 1999 #undef ADDR3 2000 #undef ADDR4 2001 } 2002 2003 static void 2004 mgmt_header_print(netdissect_options *ndo, const u_char *p) 2005 { 2006 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 2007 2008 ND_PRINT("BSSID:%s DA:%s SA:%s ", 2009 GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da), 2010 GET_ETHERADDR_STRING((hp)->sa)); 2011 } 2012 2013 static void 2014 ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) 2015 { 2016 switch (FC_SUBTYPE(fc)) { 2017 case CTRL_BAR: 2018 ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ", 2019 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra), 2020 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta), 2021 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl), 2022 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq)); 2023 break; 2024 case CTRL_BA: 2025 ND_PRINT("RA:%s ", 2026 GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra)); 2027 break; 2028 case CTRL_PS_POLL: 2029 ND_PRINT("BSSID:%s TA:%s ", 2030 GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid), 2031 GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta)); 2032 break; 2033 case CTRL_RTS: 2034 ND_PRINT("RA:%s TA:%s ", 2035 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra), 2036 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta)); 2037 break; 2038 case CTRL_CTS: 2039 ND_PRINT("RA:%s ", 2040 GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra)); 2041 break; 2042 case CTRL_ACK: 2043 ND_PRINT("RA:%s ", 2044 GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra)); 2045 break; 2046 case CTRL_CF_END: 2047 ND_PRINT("RA:%s BSSID:%s ", 2048 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra), 2049 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid)); 2050 break; 2051 case CTRL_END_ACK: 2052 ND_PRINT("RA:%s BSSID:%s ", 2053 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra), 2054 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid)); 2055 break; 2056 default: 2057 /* We shouldn't get here - we should already have quit */ 2058 break; 2059 } 2060 } 2061 2062 static int 2063 extract_header_length(netdissect_options *ndo, 2064 uint16_t fc) 2065 { 2066 int len; 2067 2068 switch (FC_TYPE(fc)) { 2069 case T_MGMT: 2070 return MGMT_HDRLEN; 2071 case T_CTRL: 2072 switch (FC_SUBTYPE(fc)) { 2073 case CTRL_CONTROL_WRAPPER: 2074 return CTRL_CONTROL_WRAPPER_HDRLEN; 2075 case CTRL_BAR: 2076 return CTRL_BAR_HDRLEN; 2077 case CTRL_BA: 2078 return CTRL_BA_HDRLEN; 2079 case CTRL_PS_POLL: 2080 return CTRL_PS_POLL_HDRLEN; 2081 case CTRL_RTS: 2082 return CTRL_RTS_HDRLEN; 2083 case CTRL_CTS: 2084 return CTRL_CTS_HDRLEN; 2085 case CTRL_ACK: 2086 return CTRL_ACK_HDRLEN; 2087 case CTRL_CF_END: 2088 return CTRL_END_HDRLEN; 2089 case CTRL_END_ACK: 2090 return CTRL_END_ACK_HDRLEN; 2091 default: 2092 ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc)); 2093 return 0; 2094 } 2095 case T_DATA: 2096 len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24; 2097 if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) 2098 len += 2; 2099 return len; 2100 default: 2101 ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc)); 2102 return 0; 2103 } 2104 } 2105 2106 static int 2107 extract_mesh_header_length(netdissect_options *ndo, const u_char *p) 2108 { 2109 return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3)); 2110 } 2111 2112 /* 2113 * Print the 802.11 MAC header. 2114 */ 2115 static void 2116 ieee_802_11_hdr_print(netdissect_options *ndo, 2117 uint16_t fc, const u_char *p, u_int hdrlen, 2118 u_int meshdrlen) 2119 { 2120 if (ndo->ndo_vflag) { 2121 if (FC_MORE_DATA(fc)) 2122 ND_PRINT("More Data "); 2123 if (FC_MORE_FLAG(fc)) 2124 ND_PRINT("More Fragments "); 2125 if (FC_POWER_MGMT(fc)) 2126 ND_PRINT("Pwr Mgmt "); 2127 if (FC_RETRY(fc)) 2128 ND_PRINT("Retry "); 2129 if (FC_ORDER(fc)) 2130 ND_PRINT("Strictly Ordered "); 2131 if (FC_PROTECTED(fc)) 2132 ND_PRINT("Protected "); 2133 if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL) 2134 ND_PRINT("%uus ", 2135 GET_LE_U_2(((const struct mgmt_header_t *)p)->duration)); 2136 } 2137 if (meshdrlen != 0) { 2138 const struct meshcntl_t *mc = 2139 (const struct meshcntl_t *)(p + hdrlen - meshdrlen); 2140 u_int ae = GET_U_1(mc->flags) & 3; 2141 2142 ND_PRINT("MeshData (AE %u TTL %u seq %u", ae, 2143 GET_U_1(mc->ttl), GET_LE_U_4(mc->seq)); 2144 if (ae > 0) 2145 ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4)); 2146 if (ae > 1) 2147 ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5)); 2148 if (ae > 2) 2149 ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6)); 2150 ND_PRINT(") "); 2151 } 2152 2153 switch (FC_TYPE(fc)) { 2154 case T_MGMT: 2155 mgmt_header_print(ndo, p); 2156 break; 2157 case T_CTRL: 2158 ctrl_header_print(ndo, fc, p); 2159 break; 2160 case T_DATA: 2161 data_header_print(ndo, fc, p); 2162 break; 2163 default: 2164 break; 2165 } 2166 } 2167 2168 static u_int 2169 ieee802_11_print(netdissect_options *ndo, 2170 const u_char *p, u_int length, u_int orig_caplen, int pad, 2171 u_int fcslen) 2172 { 2173 uint16_t fc; 2174 u_int caplen, hdrlen, meshdrlen; 2175 struct lladdr_info src, dst; 2176 int llc_hdrlen; 2177 2178 ndo->ndo_protocol = "802.11"; 2179 caplen = orig_caplen; 2180 /* Remove FCS, if present */ 2181 if (length < fcslen) { 2182 nd_print_trunc(ndo); 2183 return caplen; 2184 } 2185 length -= fcslen; 2186 if (caplen > length) { 2187 /* Amount of FCS in actual packet data, if any */ 2188 fcslen = caplen - length; 2189 caplen -= fcslen; 2190 ndo->ndo_snapend -= fcslen; 2191 } 2192 2193 if (caplen < IEEE802_11_FC_LEN) { 2194 nd_print_trunc(ndo); 2195 return orig_caplen; 2196 } 2197 2198 fc = GET_LE_U_2(p); 2199 hdrlen = extract_header_length(ndo, fc); 2200 if (hdrlen == 0) { 2201 /* Unknown frame type or control frame subtype; quit. */ 2202 return (0); 2203 } 2204 if (pad) 2205 hdrlen = roundup2(hdrlen, 4); 2206 if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA && 2207 DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) { 2208 if(!ND_TTEST_1(p + hdrlen)) { 2209 nd_print_trunc(ndo); 2210 return hdrlen; 2211 } 2212 meshdrlen = extract_mesh_header_length(ndo, p + hdrlen); 2213 hdrlen += meshdrlen; 2214 } else 2215 meshdrlen = 0; 2216 2217 if (caplen < hdrlen) { 2218 nd_print_trunc(ndo); 2219 return hdrlen; 2220 } 2221 2222 if (ndo->ndo_eflag) 2223 ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen); 2224 2225 /* 2226 * Go past the 802.11 header. 2227 */ 2228 length -= hdrlen; 2229 caplen -= hdrlen; 2230 p += hdrlen; 2231 2232 src.addr_string = etheraddr_string; 2233 dst.addr_string = etheraddr_string; 2234 switch (FC_TYPE(fc)) { 2235 case T_MGMT: 2236 get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr); 2237 if (!mgmt_body_print(ndo, fc, src.addr, p, length)) { 2238 nd_print_trunc(ndo); 2239 return hdrlen; 2240 } 2241 break; 2242 case T_CTRL: 2243 if (!ctrl_body_print(ndo, fc, p - hdrlen)) { 2244 nd_print_trunc(ndo); 2245 return hdrlen; 2246 } 2247 break; 2248 case T_DATA: 2249 if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc))) 2250 return hdrlen; /* no-data frame */ 2251 /* There may be a problem w/ AP not having this bit set */ 2252 if (FC_PROTECTED(fc)) { 2253 ND_PRINT("Data"); 2254 if (!wep_print(ndo, p)) { 2255 nd_print_trunc(ndo); 2256 return hdrlen; 2257 } 2258 } else { 2259 get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr); 2260 llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); 2261 if (llc_hdrlen < 0) { 2262 /* 2263 * Some kinds of LLC packet we cannot 2264 * handle intelligently 2265 */ 2266 if (!ndo->ndo_suppress_default_print) 2267 ND_DEFAULTPRINT(p, caplen); 2268 llc_hdrlen = -llc_hdrlen; 2269 } 2270 hdrlen += llc_hdrlen; 2271 } 2272 break; 2273 default: 2274 /* We shouldn't get here - we should already have quit */ 2275 break; 2276 } 2277 2278 return hdrlen; 2279 } 2280 2281 /* 2282 * This is the top level routine of the printer. 'p' points 2283 * to the 802.11 header of the packet, 'h->ts' is the timestamp, 2284 * 'h->len' is the length of the packet off the wire, and 'h->caplen' 2285 * is the number of bytes actually captured. 2286 */ 2287 void 2288 ieee802_11_if_print(netdissect_options *ndo, 2289 const struct pcap_pkthdr *h, const u_char *p) 2290 { 2291 ndo->ndo_protocol = "802.11"; 2292 ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0); 2293 } 2294 2295 2296 /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ 2297 /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */ 2298 2299 /*- 2300 * Copyright (c) 2003, 2004 David Young. All rights reserved. 2301 * 2302 * Redistribution and use in source and binary forms, with or without 2303 * modification, are permitted provided that the following conditions 2304 * are met: 2305 * 1. Redistributions of source code must retain the above copyright 2306 * notice, this list of conditions and the following disclaimer. 2307 * 2. Redistributions in binary form must reproduce the above copyright 2308 * notice, this list of conditions and the following disclaimer in the 2309 * documentation and/or other materials provided with the distribution. 2310 * 3. The name of David Young may not be used to endorse or promote 2311 * products derived from this software without specific prior 2312 * written permission. 2313 * 2314 * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY 2315 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2316 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 2317 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID 2318 * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2319 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2320 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2321 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2322 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2323 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2324 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 2325 * OF SUCH DAMAGE. 2326 */ 2327 2328 /* A generic radio capture format is desirable. It must be 2329 * rigidly defined (e.g., units for fields should be given), 2330 * and easily extensible. 2331 * 2332 * The following is an extensible radio capture format. It is 2333 * based on a bitmap indicating which fields are present. 2334 * 2335 * I am trying to describe precisely what the application programmer 2336 * should expect in the following, and for that reason I tell the 2337 * units and origin of each measurement (where it applies), or else I 2338 * use sufficiently weaselly language ("is a monotonically nondecreasing 2339 * function of...") that I cannot set false expectations for lawyerly 2340 * readers. 2341 */ 2342 2343 /* 2344 * The radio capture header precedes the 802.11 header. 2345 * 2346 * Note well: all radiotap fields are little-endian. 2347 */ 2348 struct ieee80211_radiotap_header { 2349 nd_uint8_t it_version; /* Version 0. Only increases 2350 * for drastic changes, 2351 * introduction of compatible 2352 * new fields does not count. 2353 */ 2354 nd_uint8_t it_pad; 2355 nd_uint16_t it_len; /* length of the whole 2356 * header in bytes, including 2357 * it_version, it_pad, 2358 * it_len, and data fields. 2359 */ 2360 nd_uint32_t it_present; /* A bitmap telling which 2361 * fields are present. Set bit 31 2362 * (0x80000000) to extend the 2363 * bitmap by another 32 bits. 2364 * Additional extensions are made 2365 * by setting bit 31. 2366 */ 2367 }; 2368 2369 /* Name Data type Units 2370 * ---- --------- ----- 2371 * 2372 * IEEE80211_RADIOTAP_TSFT uint64_t microseconds 2373 * 2374 * Value in microseconds of the MAC's 64-bit 802.11 Time 2375 * Synchronization Function timer when the first bit of the 2376 * MPDU arrived at the MAC. For received frames, only. 2377 * 2378 * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap 2379 * 2380 * Tx/Rx frequency in MHz, followed by flags (see below). 2381 * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to 2382 * represent an HT channel as there is not enough room in 2383 * the flags word. 2384 * 2385 * IEEE80211_RADIOTAP_FHSS uint16_t see below 2386 * 2387 * For frequency-hopping radios, the hop set (first byte) 2388 * and pattern (second byte). 2389 * 2390 * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index 2391 * 2392 * Tx/Rx data rate. If bit 0x80 is set then it represents an 2393 * an MCS index and not an IEEE rate. 2394 * 2395 * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from 2396 * one milliwatt (dBm) 2397 * 2398 * RF signal power at the antenna, decibel difference from 2399 * one milliwatt. 2400 * 2401 * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from 2402 * one milliwatt (dBm) 2403 * 2404 * RF noise power at the antenna, decibel difference from one 2405 * milliwatt. 2406 * 2407 * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) 2408 * 2409 * RF signal power at the antenna, decibel difference from an 2410 * arbitrary, fixed reference. 2411 * 2412 * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) 2413 * 2414 * RF noise power at the antenna, decibel difference from an 2415 * arbitrary, fixed reference point. 2416 * 2417 * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless 2418 * 2419 * Quality of Barker code lock. Unitless. Monotonically 2420 * nondecreasing with "better" lock strength. Called "Signal 2421 * Quality" in datasheets. (Is there a standard way to measure 2422 * this?) 2423 * 2424 * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless 2425 * 2426 * Transmit power expressed as unitless distance from max 2427 * power set at factory calibration. 0 is max power. 2428 * Monotonically nondecreasing with lower power levels. 2429 * 2430 * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) 2431 * 2432 * Transmit power expressed as decibel distance from max power 2433 * set at factory calibration. 0 is max power. Monotonically 2434 * nondecreasing with lower power levels. 2435 * 2436 * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from 2437 * one milliwatt (dBm) 2438 * 2439 * Transmit power expressed as dBm (decibels from a 1 milliwatt 2440 * reference). This is the absolute power level measured at 2441 * the antenna port. 2442 * 2443 * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap 2444 * 2445 * Properties of transmitted and received frames. See flags 2446 * defined below. 2447 * 2448 * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index 2449 * 2450 * Unitless indication of the Rx/Tx antenna for this packet. 2451 * The first antenna is antenna 0. 2452 * 2453 * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap 2454 * 2455 * Properties of received frames. See flags defined below. 2456 * 2457 * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap 2458 * uint16_t MHz 2459 * uint8_t channel number 2460 * uint8_t .5 dBm 2461 * 2462 * Extended channel specification: flags (see below) followed by 2463 * frequency in MHz, the corresponding IEEE channel number, and 2464 * finally the maximum regulatory transmit power cap in .5 dBm 2465 * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL 2466 * and only one of the two should be present. 2467 * 2468 * IEEE80211_RADIOTAP_MCS uint8_t known 2469 * uint8_t flags 2470 * uint8_t mcs 2471 * 2472 * Bitset indicating which fields have known values, followed 2473 * by bitset of flag values, followed by the MCS rate index as 2474 * in IEEE 802.11n. 2475 * 2476 * 2477 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless 2478 * 2479 * Contains the AMPDU information for the subframe. 2480 * 2481 * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 2482 * 2483 * Contains VHT information about this frame. 2484 * 2485 * IEEE80211_RADIOTAP_VENDOR_NAMESPACE 2486 * uint8_t OUI[3] 2487 * uint8_t subspace 2488 * uint16_t length 2489 * 2490 * The Vendor Namespace Field contains three sub-fields. The first 2491 * sub-field is 3 bytes long. It contains the vendor's IEEE 802 2492 * Organizationally Unique Identifier (OUI). The fourth byte is a 2493 * vendor-specific "namespace selector." 2494 * 2495 */ 2496 enum ieee80211_radiotap_type { 2497 IEEE80211_RADIOTAP_TSFT = 0, 2498 IEEE80211_RADIOTAP_FLAGS = 1, 2499 IEEE80211_RADIOTAP_RATE = 2, 2500 IEEE80211_RADIOTAP_CHANNEL = 3, 2501 IEEE80211_RADIOTAP_FHSS = 4, 2502 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, 2503 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, 2504 IEEE80211_RADIOTAP_LOCK_QUALITY = 7, 2505 IEEE80211_RADIOTAP_TX_ATTENUATION = 8, 2506 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, 2507 IEEE80211_RADIOTAP_DBM_TX_POWER = 10, 2508 IEEE80211_RADIOTAP_ANTENNA = 11, 2509 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, 2510 IEEE80211_RADIOTAP_DB_ANTNOISE = 13, 2511 IEEE80211_RADIOTAP_RX_FLAGS = 14, 2512 /* NB: gap for netbsd definitions */ 2513 IEEE80211_RADIOTAP_XCHANNEL = 18, 2514 IEEE80211_RADIOTAP_MCS = 19, 2515 IEEE80211_RADIOTAP_AMPDU_STATUS = 20, 2516 IEEE80211_RADIOTAP_VHT = 21, 2517 IEEE80211_RADIOTAP_NAMESPACE = 29, 2518 IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, 2519 IEEE80211_RADIOTAP_EXT = 31 2520 }; 2521 2522 /* channel attributes */ 2523 #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */ 2524 #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */ 2525 #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */ 2526 #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */ 2527 #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */ 2528 #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */ 2529 #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */ 2530 #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */ 2531 #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */ 2532 #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */ 2533 #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */ 2534 #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */ 2535 #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */ 2536 #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */ 2537 #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */ 2538 2539 /* Useful combinations of channel characteristics, borrowed from Ethereal */ 2540 #define IEEE80211_CHAN_A \ 2541 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 2542 #define IEEE80211_CHAN_B \ 2543 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 2544 #define IEEE80211_CHAN_G \ 2545 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 2546 #define IEEE80211_CHAN_TA \ 2547 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) 2548 #define IEEE80211_CHAN_TG \ 2549 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO) 2550 2551 2552 /* For IEEE80211_RADIOTAP_FLAGS */ 2553 #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received 2554 * during CFP 2555 */ 2556 #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received 2557 * with short 2558 * preamble 2559 */ 2560 #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received 2561 * with WEP encryption 2562 */ 2563 #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received 2564 * with fragmentation 2565 */ 2566 #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ 2567 #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between 2568 * 802.11 header and payload 2569 * (to 32-bit boundary) 2570 */ 2571 #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */ 2572 2573 /* For IEEE80211_RADIOTAP_RX_FLAGS */ 2574 #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ 2575 #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */ 2576 2577 /* For IEEE80211_RADIOTAP_MCS known */ 2578 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01 2579 #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */ 2580 #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04 2581 #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08 2582 #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10 2583 #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20 2584 #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40 2585 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80 2586 2587 /* For IEEE80211_RADIOTAP_MCS flags */ 2588 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03 2589 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0 2590 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1 2591 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2 2592 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3 2593 #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */ 2594 #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08 2595 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 2596 #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 2597 #define IEEE80211_RADIOTAP_MCS_STBC_1 1 2598 #define IEEE80211_RADIOTAP_MCS_STBC_2 2 2599 #define IEEE80211_RADIOTAP_MCS_STBC_3 3 2600 #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 2601 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80 2602 2603 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */ 2604 #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 2605 #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 2606 #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 2607 #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 2608 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 2609 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 2610 2611 /* For IEEE80211_RADIOTAP_VHT known */ 2612 #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001 2613 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002 2614 #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004 2615 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008 2616 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010 2617 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020 2618 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040 2619 #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080 2620 #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100 2621 2622 /* For IEEE80211_RADIOTAP_VHT flags */ 2623 #define IEEE80211_RADIOTAP_VHT_STBC 0x01 2624 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02 2625 #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04 2626 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08 2627 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10 2628 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20 2629 2630 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f 2631 2632 #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f 2633 #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0 2634 #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4 2635 2636 #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01 2637 2638 #define IEEE80211_CHAN_FHSS \ 2639 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) 2640 #define IEEE80211_CHAN_A \ 2641 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 2642 #define IEEE80211_CHAN_B \ 2643 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 2644 #define IEEE80211_CHAN_PUREG \ 2645 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) 2646 #define IEEE80211_CHAN_G \ 2647 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 2648 2649 #define IS_CHAN_FHSS(flags) \ 2650 ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) 2651 #define IS_CHAN_A(flags) \ 2652 ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) 2653 #define IS_CHAN_B(flags) \ 2654 ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) 2655 #define IS_CHAN_PUREG(flags) \ 2656 ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) 2657 #define IS_CHAN_G(flags) \ 2658 ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) 2659 #define IS_CHAN_ANYG(flags) \ 2660 (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags)) 2661 2662 static void 2663 print_chaninfo(netdissect_options *ndo, 2664 uint16_t freq, uint32_t flags, uint32_t presentflags) 2665 { 2666 ND_PRINT("%u MHz", freq); 2667 if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) { 2668 /* 2669 * We have the MCS field, so this is 11n, regardless 2670 * of what the channel flags say. 2671 */ 2672 ND_PRINT(" 11n"); 2673 } else { 2674 if (IS_CHAN_FHSS(flags)) 2675 ND_PRINT(" FHSS"); 2676 if (IS_CHAN_A(flags)) { 2677 if (flags & IEEE80211_CHAN_HALF) 2678 ND_PRINT(" 11a/10Mhz"); 2679 else if (flags & IEEE80211_CHAN_QUARTER) 2680 ND_PRINT(" 11a/5Mhz"); 2681 else 2682 ND_PRINT(" 11a"); 2683 } 2684 if (IS_CHAN_ANYG(flags)) { 2685 if (flags & IEEE80211_CHAN_HALF) 2686 ND_PRINT(" 11g/10Mhz"); 2687 else if (flags & IEEE80211_CHAN_QUARTER) 2688 ND_PRINT(" 11g/5Mhz"); 2689 else 2690 ND_PRINT(" 11g"); 2691 } else if (IS_CHAN_B(flags)) 2692 ND_PRINT(" 11b"); 2693 if (flags & IEEE80211_CHAN_TURBO) 2694 ND_PRINT(" Turbo"); 2695 } 2696 /* 2697 * These apply to 11n. 2698 */ 2699 if (flags & IEEE80211_CHAN_HT20) 2700 ND_PRINT(" ht/20"); 2701 else if (flags & IEEE80211_CHAN_HT40D) 2702 ND_PRINT(" ht/40-"); 2703 else if (flags & IEEE80211_CHAN_HT40U) 2704 ND_PRINT(" ht/40+"); 2705 ND_PRINT(" "); 2706 } 2707 2708 static int 2709 print_radiotap_field(netdissect_options *ndo, 2710 struct cpack_state *s, uint32_t bit, uint8_t *flagsp, 2711 uint32_t presentflags) 2712 { 2713 u_int i; 2714 int rc; 2715 2716 switch (bit) { 2717 2718 case IEEE80211_RADIOTAP_TSFT: { 2719 uint64_t tsft; 2720 2721 rc = nd_cpack_uint64(ndo, s, &tsft); 2722 if (rc != 0) 2723 goto trunc; 2724 ND_PRINT("%" PRIu64 "us tsft ", tsft); 2725 break; 2726 } 2727 2728 case IEEE80211_RADIOTAP_FLAGS: { 2729 uint8_t flagsval; 2730 2731 rc = nd_cpack_uint8(ndo, s, &flagsval); 2732 if (rc != 0) 2733 goto trunc; 2734 *flagsp = flagsval; 2735 if (flagsval & IEEE80211_RADIOTAP_F_CFP) 2736 ND_PRINT("cfp "); 2737 if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE) 2738 ND_PRINT("short preamble "); 2739 if (flagsval & IEEE80211_RADIOTAP_F_WEP) 2740 ND_PRINT("wep "); 2741 if (flagsval & IEEE80211_RADIOTAP_F_FRAG) 2742 ND_PRINT("fragmented "); 2743 if (flagsval & IEEE80211_RADIOTAP_F_BADFCS) 2744 ND_PRINT("bad-fcs "); 2745 break; 2746 } 2747 2748 case IEEE80211_RADIOTAP_RATE: { 2749 uint8_t rate; 2750 2751 rc = nd_cpack_uint8(ndo, s, &rate); 2752 if (rc != 0) 2753 goto trunc; 2754 /* 2755 * XXX On FreeBSD rate & 0x80 means we have an MCS. On 2756 * Linux and AirPcap it does not. (What about 2757 * macOS, NetBSD, OpenBSD, and DragonFly BSD?) 2758 * 2759 * This is an issue either for proprietary extensions 2760 * to 11a or 11g, which do exist, or for 11n 2761 * implementations that stuff a rate value into 2762 * this field, which also appear to exist. 2763 * 2764 * We currently handle that by assuming that 2765 * if the 0x80 bit is set *and* the remaining 2766 * bits have a value between 0 and 15 it's 2767 * an MCS value, otherwise it's a rate. If 2768 * there are cases where systems that use 2769 * "0x80 + MCS index" for MCS indices > 15, 2770 * or stuff a rate value here between 64 and 2771 * 71.5 Mb/s in here, we'll need a preference 2772 * setting. Such rates do exist, e.g. 11n 2773 * MCS 7 at 20 MHz with a long guard interval. 2774 */ 2775 if (rate >= 0x80 && rate <= 0x8f) { 2776 /* 2777 * XXX - we don't know the channel width 2778 * or guard interval length, so we can't 2779 * convert this to a data rate. 2780 * 2781 * If you want us to show a data rate, 2782 * use the MCS field, not the Rate field; 2783 * the MCS field includes not only the 2784 * MCS index, it also includes bandwidth 2785 * and guard interval information. 2786 * 2787 * XXX - can we get the channel width 2788 * from XChannel and the guard interval 2789 * information from Flags, at least on 2790 * FreeBSD? 2791 */ 2792 ND_PRINT("MCS %u ", rate & 0x7f); 2793 } else 2794 ND_PRINT("%2.1f Mb/s ", .5 * rate); 2795 break; 2796 } 2797 2798 case IEEE80211_RADIOTAP_CHANNEL: { 2799 uint16_t frequency; 2800 uint16_t flags; 2801 2802 rc = nd_cpack_uint16(ndo, s, &frequency); 2803 if (rc != 0) 2804 goto trunc; 2805 rc = nd_cpack_uint16(ndo, s, &flags); 2806 if (rc != 0) 2807 goto trunc; 2808 /* 2809 * If CHANNEL and XCHANNEL are both present, skip 2810 * CHANNEL. 2811 */ 2812 if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL)) 2813 break; 2814 print_chaninfo(ndo, frequency, flags, presentflags); 2815 break; 2816 } 2817 2818 case IEEE80211_RADIOTAP_FHSS: { 2819 uint8_t hopset; 2820 uint8_t hoppat; 2821 2822 rc = nd_cpack_uint8(ndo, s, &hopset); 2823 if (rc != 0) 2824 goto trunc; 2825 rc = nd_cpack_uint8(ndo, s, &hoppat); 2826 if (rc != 0) 2827 goto trunc; 2828 ND_PRINT("fhset %u fhpat %u ", hopset, hoppat); 2829 break; 2830 } 2831 2832 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: { 2833 int8_t dbm_antsignal; 2834 2835 rc = nd_cpack_int8(ndo, s, &dbm_antsignal); 2836 if (rc != 0) 2837 goto trunc; 2838 ND_PRINT("%ddBm signal ", dbm_antsignal); 2839 break; 2840 } 2841 2842 case IEEE80211_RADIOTAP_DBM_ANTNOISE: { 2843 int8_t dbm_antnoise; 2844 2845 rc = nd_cpack_int8(ndo, s, &dbm_antnoise); 2846 if (rc != 0) 2847 goto trunc; 2848 ND_PRINT("%ddBm noise ", dbm_antnoise); 2849 break; 2850 } 2851 2852 case IEEE80211_RADIOTAP_LOCK_QUALITY: { 2853 uint16_t lock_quality; 2854 2855 rc = nd_cpack_uint16(ndo, s, &lock_quality); 2856 if (rc != 0) 2857 goto trunc; 2858 ND_PRINT("%u sq ", lock_quality); 2859 break; 2860 } 2861 2862 case IEEE80211_RADIOTAP_TX_ATTENUATION: { 2863 int16_t tx_attenuation; 2864 2865 rc = nd_cpack_int16(ndo, s, &tx_attenuation); 2866 if (rc != 0) 2867 goto trunc; 2868 ND_PRINT("%d tx power ", -tx_attenuation); 2869 break; 2870 } 2871 2872 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: { 2873 int8_t db_tx_attenuation; 2874 2875 rc = nd_cpack_int8(ndo, s, &db_tx_attenuation); 2876 if (rc != 0) 2877 goto trunc; 2878 ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation); 2879 break; 2880 } 2881 2882 case IEEE80211_RADIOTAP_DBM_TX_POWER: { 2883 int8_t dbm_tx_power; 2884 2885 rc = nd_cpack_int8(ndo, s, &dbm_tx_power); 2886 if (rc != 0) 2887 goto trunc; 2888 ND_PRINT("%ddBm tx power ", dbm_tx_power); 2889 break; 2890 } 2891 2892 case IEEE80211_RADIOTAP_ANTENNA: { 2893 uint8_t antenna; 2894 2895 rc = nd_cpack_uint8(ndo, s, &antenna); 2896 if (rc != 0) 2897 goto trunc; 2898 ND_PRINT("antenna %u ", antenna); 2899 break; 2900 } 2901 2902 case IEEE80211_RADIOTAP_DB_ANTSIGNAL: { 2903 uint8_t db_antsignal; 2904 2905 rc = nd_cpack_uint8(ndo, s, &db_antsignal); 2906 if (rc != 0) 2907 goto trunc; 2908 ND_PRINT("%udB signal ", db_antsignal); 2909 break; 2910 } 2911 2912 case IEEE80211_RADIOTAP_DB_ANTNOISE: { 2913 uint8_t db_antnoise; 2914 2915 rc = nd_cpack_uint8(ndo, s, &db_antnoise); 2916 if (rc != 0) 2917 goto trunc; 2918 ND_PRINT("%udB noise ", db_antnoise); 2919 break; 2920 } 2921 2922 case IEEE80211_RADIOTAP_RX_FLAGS: { 2923 uint16_t rx_flags; 2924 2925 rc = nd_cpack_uint16(ndo, s, &rx_flags); 2926 if (rc != 0) 2927 goto trunc; 2928 /* Do nothing for now */ 2929 break; 2930 } 2931 2932 case IEEE80211_RADIOTAP_XCHANNEL: { 2933 uint32_t flags; 2934 uint16_t frequency; 2935 uint8_t channel; 2936 uint8_t maxpower; 2937 2938 rc = nd_cpack_uint32(ndo, s, &flags); 2939 if (rc != 0) 2940 goto trunc; 2941 rc = nd_cpack_uint16(ndo, s, &frequency); 2942 if (rc != 0) 2943 goto trunc; 2944 rc = nd_cpack_uint8(ndo, s, &channel); 2945 if (rc != 0) 2946 goto trunc; 2947 rc = nd_cpack_uint8(ndo, s, &maxpower); 2948 if (rc != 0) 2949 goto trunc; 2950 print_chaninfo(ndo, frequency, flags, presentflags); 2951 break; 2952 } 2953 2954 case IEEE80211_RADIOTAP_MCS: { 2955 uint8_t known; 2956 uint8_t flags; 2957 uint8_t mcs_index; 2958 static const char *ht_bandwidth[4] = { 2959 "20 MHz", 2960 "40 MHz", 2961 "20 MHz (L)", 2962 "20 MHz (U)" 2963 }; 2964 float htrate; 2965 2966 rc = nd_cpack_uint8(ndo, s, &known); 2967 if (rc != 0) 2968 goto trunc; 2969 rc = nd_cpack_uint8(ndo, s, &flags); 2970 if (rc != 0) 2971 goto trunc; 2972 rc = nd_cpack_uint8(ndo, s, &mcs_index); 2973 if (rc != 0) 2974 goto trunc; 2975 if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) { 2976 /* 2977 * We know the MCS index. 2978 */ 2979 if (mcs_index <= MAX_MCS_INDEX) { 2980 /* 2981 * And it's in-range. 2982 */ 2983 if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) { 2984 /* 2985 * And we know both the bandwidth and 2986 * the guard interval, so we can look 2987 * up the rate. 2988 */ 2989 htrate = 2990 ieee80211_float_htrates 2991 [mcs_index] 2992 [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)] 2993 [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)]; 2994 } else { 2995 /* 2996 * We don't know both the bandwidth 2997 * and the guard interval, so we can 2998 * only report the MCS index. 2999 */ 3000 htrate = 0.0; 3001 } 3002 } else { 3003 /* 3004 * The MCS value is out of range. 3005 */ 3006 htrate = 0.0; 3007 } 3008 if (htrate != 0.0) { 3009 /* 3010 * We have the rate. 3011 * Print it. 3012 */ 3013 ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index); 3014 } else { 3015 /* 3016 * We at least have the MCS index. 3017 * Print it. 3018 */ 3019 ND_PRINT("MCS %u ", mcs_index); 3020 } 3021 } 3022 if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) { 3023 ND_PRINT("%s ", 3024 ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]); 3025 } 3026 if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) { 3027 ND_PRINT("%s GI ", 3028 (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 3029 "short" : "long"); 3030 } 3031 if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) { 3032 ND_PRINT("%s ", 3033 (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ? 3034 "greenfield" : "mixed"); 3035 } 3036 if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) { 3037 ND_PRINT("%s FEC ", 3038 (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ? 3039 "LDPC" : "BCC"); 3040 } 3041 if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) { 3042 ND_PRINT("RX-STBC%u ", 3043 (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT); 3044 } 3045 break; 3046 } 3047 3048 case IEEE80211_RADIOTAP_AMPDU_STATUS: { 3049 uint32_t reference_num; 3050 uint16_t flags; 3051 uint8_t delim_crc; 3052 uint8_t reserved; 3053 3054 rc = nd_cpack_uint32(ndo, s, &reference_num); 3055 if (rc != 0) 3056 goto trunc; 3057 rc = nd_cpack_uint16(ndo, s, &flags); 3058 if (rc != 0) 3059 goto trunc; 3060 rc = nd_cpack_uint8(ndo, s, &delim_crc); 3061 if (rc != 0) 3062 goto trunc; 3063 rc = nd_cpack_uint8(ndo, s, &reserved); 3064 if (rc != 0) 3065 goto trunc; 3066 /* Do nothing for now */ 3067 break; 3068 } 3069 3070 case IEEE80211_RADIOTAP_VHT: { 3071 uint16_t known; 3072 uint8_t flags; 3073 uint8_t bandwidth; 3074 uint8_t mcs_nss[4]; 3075 uint8_t coding; 3076 uint8_t group_id; 3077 uint16_t partial_aid; 3078 static const char *vht_bandwidth[32] = { 3079 "20 MHz", 3080 "40 MHz", 3081 "20 MHz (L)", 3082 "20 MHz (U)", 3083 "80 MHz", 3084 "80 MHz (L)", 3085 "80 MHz (U)", 3086 "80 MHz (LL)", 3087 "80 MHz (LU)", 3088 "80 MHz (UL)", 3089 "80 MHz (UU)", 3090 "160 MHz", 3091 "160 MHz (L)", 3092 "160 MHz (U)", 3093 "160 MHz (LL)", 3094 "160 MHz (LU)", 3095 "160 MHz (UL)", 3096 "160 MHz (UU)", 3097 "160 MHz (LLL)", 3098 "160 MHz (LLU)", 3099 "160 MHz (LUL)", 3100 "160 MHz (UUU)", 3101 "160 MHz (ULL)", 3102 "160 MHz (ULU)", 3103 "160 MHz (UUL)", 3104 "160 MHz (UUU)", 3105 "unknown (26)", 3106 "unknown (27)", 3107 "unknown (28)", 3108 "unknown (29)", 3109 "unknown (30)", 3110 "unknown (31)" 3111 }; 3112 3113 rc = nd_cpack_uint16(ndo, s, &known); 3114 if (rc != 0) 3115 goto trunc; 3116 rc = nd_cpack_uint8(ndo, s, &flags); 3117 if (rc != 0) 3118 goto trunc; 3119 rc = nd_cpack_uint8(ndo, s, &bandwidth); 3120 if (rc != 0) 3121 goto trunc; 3122 for (i = 0; i < 4; i++) { 3123 rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]); 3124 if (rc != 0) 3125 goto trunc; 3126 } 3127 rc = nd_cpack_uint8(ndo, s, &coding); 3128 if (rc != 0) 3129 goto trunc; 3130 rc = nd_cpack_uint8(ndo, s, &group_id); 3131 if (rc != 0) 3132 goto trunc; 3133 rc = nd_cpack_uint16(ndo, s, &partial_aid); 3134 if (rc != 0) 3135 goto trunc; 3136 for (i = 0; i < 4; i++) { 3137 u_int nss, mcs; 3138 nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK; 3139 mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT; 3140 3141 if (nss == 0) 3142 continue; 3143 3144 ND_PRINT("User %u MCS %u ", i, mcs); 3145 ND_PRINT("%s FEC ", 3146 (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ? 3147 "LDPC" : "BCC"); 3148 } 3149 if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) { 3150 ND_PRINT("%s ", 3151 vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]); 3152 } 3153 if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) { 3154 ND_PRINT("%s GI ", 3155 (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ? 3156 "short" : "long"); 3157 } 3158 break; 3159 } 3160 3161 default: 3162 /* this bit indicates a field whose 3163 * size we do not know, so we cannot 3164 * proceed. Just print the bit number. 3165 */ 3166 ND_PRINT("[bit %u] ", bit); 3167 return -1; 3168 } 3169 3170 return 0; 3171 3172 trunc: 3173 nd_print_trunc(ndo); 3174 return rc; 3175 } 3176 3177 3178 static int 3179 print_in_radiotap_namespace(netdissect_options *ndo, 3180 struct cpack_state *s, uint8_t *flags, 3181 uint32_t presentflags, int bit0) 3182 { 3183 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x))) 3184 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x))) 3185 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x))) 3186 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x))) 3187 #define BITNO_2(x) (((x) & 2) ? 1 : 0) 3188 uint32_t present, next_present; 3189 int bitno; 3190 enum ieee80211_radiotap_type bit; 3191 int rc; 3192 3193 for (present = presentflags; present; present = next_present) { 3194 /* 3195 * Clear the least significant bit that is set. 3196 */ 3197 next_present = present & (present - 1); 3198 3199 /* 3200 * Get the bit number, within this presence word, 3201 * of the remaining least significant bit that 3202 * is set. 3203 */ 3204 bitno = BITNO_32(present ^ next_present); 3205 3206 /* 3207 * Stop if this is one of the "same meaning 3208 * in all presence flags" bits. 3209 */ 3210 if (bitno >= IEEE80211_RADIOTAP_NAMESPACE) 3211 break; 3212 3213 /* 3214 * Get the radiotap bit number of that bit. 3215 */ 3216 bit = (enum ieee80211_radiotap_type)(bit0 + bitno); 3217 3218 rc = print_radiotap_field(ndo, s, bit, flags, presentflags); 3219 if (rc != 0) 3220 return rc; 3221 } 3222 3223 return 0; 3224 } 3225 3226 u_int 3227 ieee802_11_radio_print(netdissect_options *ndo, 3228 const u_char *p, u_int length, u_int caplen) 3229 { 3230 #define BIT(n) (1U << n) 3231 #define IS_EXTENDED(__p) \ 3232 (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0 3233 3234 struct cpack_state cpacker; 3235 const struct ieee80211_radiotap_header *hdr; 3236 uint32_t presentflags; 3237 const nd_uint32_t *presentp, *last_presentp; 3238 int vendor_namespace; 3239 uint8_t vendor_oui[3]; 3240 uint8_t vendor_subnamespace; 3241 uint16_t skip_length; 3242 int bit0; 3243 u_int len; 3244 uint8_t flags; 3245 int pad; 3246 u_int fcslen; 3247 3248 ndo->ndo_protocol = "802.11_radio"; 3249 if (caplen < sizeof(*hdr)) { 3250 nd_print_trunc(ndo); 3251 return caplen; 3252 } 3253 3254 hdr = (const struct ieee80211_radiotap_header *)p; 3255 3256 len = GET_LE_U_2(hdr->it_len); 3257 if (len < sizeof(*hdr)) { 3258 /* 3259 * The length is the length of the entire header, so 3260 * it must be as large as the fixed-length part of 3261 * the header. 3262 */ 3263 nd_print_trunc(ndo); 3264 return caplen; 3265 } 3266 3267 /* 3268 * If we don't have the entire radiotap header, just give up. 3269 */ 3270 if (caplen < len) { 3271 nd_print_trunc(ndo); 3272 return caplen; 3273 } 3274 nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */ 3275 nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */ 3276 for (last_presentp = &hdr->it_present; 3277 (const u_char*)(last_presentp + 1) <= p + len && 3278 IS_EXTENDED(last_presentp); 3279 last_presentp++) 3280 nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */ 3281 3282 /* are there more bitmap extensions than bytes in header? */ 3283 if ((const u_char*)(last_presentp + 1) > p + len) { 3284 nd_print_trunc(ndo); 3285 return caplen; 3286 } 3287 3288 /* 3289 * Start out at the beginning of the default radiotap namespace. 3290 */ 3291 bit0 = 0; 3292 vendor_namespace = 0; 3293 memset(vendor_oui, 0, 3); 3294 vendor_subnamespace = 0; 3295 skip_length = 0; 3296 /* Assume no flags */ 3297 flags = 0; 3298 /* Assume no Atheros padding between 802.11 header and body */ 3299 pad = 0; 3300 /* Assume no FCS at end of frame */ 3301 fcslen = 0; 3302 for (presentp = &hdr->it_present; presentp <= last_presentp; 3303 presentp++) { 3304 presentflags = GET_LE_U_4(presentp); 3305 3306 /* 3307 * If this is a vendor namespace, we don't handle it. 3308 */ 3309 if (vendor_namespace) { 3310 /* 3311 * Skip past the stuff we don't understand. 3312 * If we add support for any vendor namespaces, 3313 * it'd be added here; use vendor_oui and 3314 * vendor_subnamespace to interpret the fields. 3315 */ 3316 if (nd_cpack_advance(&cpacker, skip_length) != 0) { 3317 /* 3318 * Ran out of space in the packet. 3319 */ 3320 break; 3321 } 3322 3323 /* 3324 * We've skipped it all; nothing more to 3325 * skip. 3326 */ 3327 skip_length = 0; 3328 } else { 3329 if (print_in_radiotap_namespace(ndo, &cpacker, 3330 &flags, presentflags, bit0) != 0) { 3331 /* 3332 * Fatal error - can't process anything 3333 * more in the radiotap header. 3334 */ 3335 break; 3336 } 3337 } 3338 3339 /* 3340 * Handle the namespace switch bits; we've already handled 3341 * the extension bit in all but the last word above. 3342 */ 3343 switch (presentflags & 3344 (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) { 3345 3346 case 0: 3347 /* 3348 * We're not changing namespaces. 3349 * advance to the next 32 bits in the current 3350 * namespace. 3351 */ 3352 bit0 += 32; 3353 break; 3354 3355 case BIT(IEEE80211_RADIOTAP_NAMESPACE): 3356 /* 3357 * We're switching to the radiotap namespace. 3358 * Reset the presence-bitmap index to 0, and 3359 * reset the namespace to the default radiotap 3360 * namespace. 3361 */ 3362 bit0 = 0; 3363 vendor_namespace = 0; 3364 memset(vendor_oui, 0, 3); 3365 vendor_subnamespace = 0; 3366 skip_length = 0; 3367 break; 3368 3369 case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE): 3370 /* 3371 * We're switching to a vendor namespace. 3372 * Reset the presence-bitmap index to 0, 3373 * note that we're in a vendor namespace, 3374 * and fetch the fields of the Vendor Namespace 3375 * item. 3376 */ 3377 bit0 = 0; 3378 vendor_namespace = 1; 3379 if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) { 3380 nd_print_trunc(ndo); 3381 break; 3382 } 3383 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) { 3384 nd_print_trunc(ndo); 3385 break; 3386 } 3387 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) { 3388 nd_print_trunc(ndo); 3389 break; 3390 } 3391 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) { 3392 nd_print_trunc(ndo); 3393 break; 3394 } 3395 if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) { 3396 nd_print_trunc(ndo); 3397 break; 3398 } 3399 if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) { 3400 nd_print_trunc(ndo); 3401 break; 3402 } 3403 break; 3404 3405 default: 3406 /* 3407 * Illegal combination. The behavior in this 3408 * case is undefined by the radiotap spec; we 3409 * just ignore both bits. 3410 */ 3411 break; 3412 } 3413 } 3414 3415 if (flags & IEEE80211_RADIOTAP_F_DATAPAD) 3416 pad = 1; /* Atheros padding */ 3417 if (flags & IEEE80211_RADIOTAP_F_FCS) 3418 fcslen = 4; /* FCS at end of packet */ 3419 return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad, 3420 fcslen); 3421 #undef BITNO_32 3422 #undef BITNO_16 3423 #undef BITNO_8 3424 #undef BITNO_4 3425 #undef BITNO_2 3426 #undef BIT 3427 } 3428 3429 static u_int 3430 ieee802_11_radio_avs_print(netdissect_options *ndo, 3431 const u_char *p, u_int length, u_int caplen) 3432 { 3433 uint32_t caphdr_len; 3434 3435 ndo->ndo_protocol = "802.11_radio_avs"; 3436 if (caplen < 8) { 3437 nd_print_trunc(ndo); 3438 return caplen; 3439 } 3440 3441 caphdr_len = GET_BE_U_4(p + 4); 3442 if (caphdr_len < 8) { 3443 /* 3444 * Yow! The capture header length is claimed not 3445 * to be large enough to include even the version 3446 * cookie or capture header length! 3447 */ 3448 nd_print_trunc(ndo); 3449 return caplen; 3450 } 3451 3452 if (caplen < caphdr_len) { 3453 nd_print_trunc(ndo); 3454 return caplen; 3455 } 3456 3457 return caphdr_len + ieee802_11_print(ndo, p + caphdr_len, 3458 length - caphdr_len, caplen - caphdr_len, 0, 0); 3459 } 3460 3461 #define PRISM_HDR_LEN 144 3462 3463 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 3464 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001 3465 #define WLANCAP_MAGIC_COOKIE_V2 0x80211002 3466 3467 /* 3468 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header, 3469 * containing information such as radio information, which we 3470 * currently ignore. 3471 * 3472 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or 3473 * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS 3474 * (currently, on Linux, there's no ARPHRD_ type for 3475 * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM 3476 * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for 3477 * the AVS header, and the first 4 bytes of the header are used to 3478 * indicate whether it's a Prism header or an AVS header). 3479 */ 3480 void 3481 prism_if_print(netdissect_options *ndo, 3482 const struct pcap_pkthdr *h, const u_char *p) 3483 { 3484 u_int caplen = h->caplen; 3485 u_int length = h->len; 3486 uint32_t msgcode; 3487 3488 ndo->ndo_protocol = "prism"; 3489 if (caplen < 4) { 3490 nd_print_trunc(ndo); 3491 ndo->ndo_ll_hdr_len += caplen; 3492 return; 3493 } 3494 3495 msgcode = GET_BE_U_4(p); 3496 if (msgcode == WLANCAP_MAGIC_COOKIE_V1 || 3497 msgcode == WLANCAP_MAGIC_COOKIE_V2) { 3498 ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen); 3499 return; 3500 } 3501 3502 if (caplen < PRISM_HDR_LEN) { 3503 nd_print_trunc(ndo); 3504 ndo->ndo_ll_hdr_len += caplen; 3505 return; 3506 } 3507 3508 p += PRISM_HDR_LEN; 3509 length -= PRISM_HDR_LEN; 3510 caplen -= PRISM_HDR_LEN; 3511 ndo->ndo_ll_hdr_len += PRISM_HDR_LEN; 3512 ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0); 3513 } 3514 3515 /* 3516 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra 3517 * header, containing information such as radio information. 3518 */ 3519 void 3520 ieee802_11_radio_if_print(netdissect_options *ndo, 3521 const struct pcap_pkthdr *h, const u_char *p) 3522 { 3523 ndo->ndo_protocol = "802.11_radio"; 3524 ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen); 3525 } 3526 3527 /* 3528 * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an 3529 * extra header, containing information such as radio information, 3530 * which we currently ignore. 3531 */ 3532 void 3533 ieee802_11_radio_avs_if_print(netdissect_options *ndo, 3534 const struct pcap_pkthdr *h, const u_char *p) 3535 { 3536 ndo->ndo_protocol = "802.11_radio_avs"; 3537 ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen); 3538 } 3539