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