10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 2001 30f74e101Schristos * Fortress Technologies, Inc. All rights reserved. 40f74e101Schristos * Charlie Lenahan (clenahan@fortresstech.com) 50f74e101Schristos * 60f74e101Schristos * Redistribution and use in source and binary forms, with or without 70f74e101Schristos * modification, are permitted provided that: (1) source code distributions 80f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 90f74e101Schristos * distributions including binary code include the above copyright notice and 100f74e101Schristos * this paragraph in its entirety in the documentation or other materials 110f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 120f74e101Schristos * features or use of this software display the following acknowledgement: 130f74e101Schristos * ``This product includes software developed by the University of California, 140f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 150f74e101Schristos * the University nor the names of its contributors may be used to endorse 160f74e101Schristos * or promote products derived from this software without specific prior 170f74e101Schristos * written permission. 180f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 190f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 200f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 210f74e101Schristos */ 220f74e101Schristos 2311b3aaa1Schristos #include <sys/cdefs.h> 240f74e101Schristos #ifndef lint 25*26ba0b50Schristos __RCSID("$NetBSD: print-802_11.c,v 1.11 2024/09/02 16:15:30 christos Exp $"); 260f74e101Schristos #endif 270f74e101Schristos 28dc860a36Sspz /* \summary: IEEE 802.11 printer */ 29dc860a36Sspz 30c74ad251Schristos #include <config.h> 310f74e101Schristos 32c74ad251Schristos #include "netdissect-stdinc.h" 330f74e101Schristos 340f74e101Schristos #include <string.h> 350f74e101Schristos 36fdccd7e4Schristos #include "netdissect.h" 370f74e101Schristos #include "addrtoname.h" 380f74e101Schristos 390f74e101Schristos #include "extract.h" 400f74e101Schristos 410f74e101Schristos #include "cpack.h" 420f74e101Schristos 43b3a00663Schristos 44b3a00663Schristos /* Lengths of 802.11 header components. */ 45b3a00663Schristos #define IEEE802_11_FC_LEN 2 46b3a00663Schristos #define IEEE802_11_DUR_LEN 2 47b3a00663Schristos #define IEEE802_11_DA_LEN 6 48b3a00663Schristos #define IEEE802_11_SA_LEN 6 49b3a00663Schristos #define IEEE802_11_BSSID_LEN 6 50b3a00663Schristos #define IEEE802_11_RA_LEN 6 51b3a00663Schristos #define IEEE802_11_TA_LEN 6 52fdccd7e4Schristos #define IEEE802_11_ADDR1_LEN 6 53b3a00663Schristos #define IEEE802_11_SEQ_LEN 2 54b3a00663Schristos #define IEEE802_11_CTL_LEN 2 55fdccd7e4Schristos #define IEEE802_11_CARRIED_FC_LEN 2 56fdccd7e4Schristos #define IEEE802_11_HT_CONTROL_LEN 4 57b3a00663Schristos #define IEEE802_11_IV_LEN 3 58b3a00663Schristos #define IEEE802_11_KID_LEN 1 59b3a00663Schristos 60b3a00663Schristos /* Frame check sequence length. */ 61b3a00663Schristos #define IEEE802_11_FCS_LEN 4 62b3a00663Schristos 63b3a00663Schristos /* Lengths of beacon components. */ 64b3a00663Schristos #define IEEE802_11_TSTAMP_LEN 8 65b3a00663Schristos #define IEEE802_11_BCNINT_LEN 2 66b3a00663Schristos #define IEEE802_11_CAPINFO_LEN 2 67b3a00663Schristos #define IEEE802_11_LISTENINT_LEN 2 68b3a00663Schristos 69b3a00663Schristos #define IEEE802_11_AID_LEN 2 70b3a00663Schristos #define IEEE802_11_STATUS_LEN 2 71b3a00663Schristos #define IEEE802_11_REASON_LEN 2 72b3a00663Schristos 73*26ba0b50Schristos /* Length of previous AP in reassociation frame */ 74b3a00663Schristos #define IEEE802_11_AP_LEN 6 75b3a00663Schristos 76b3a00663Schristos #define T_MGMT 0x0 /* management */ 77b3a00663Schristos #define T_CTRL 0x1 /* control */ 78b3a00663Schristos #define T_DATA 0x2 /* data */ 79b3a00663Schristos #define T_RESV 0x3 /* reserved */ 80b3a00663Schristos 81b3a00663Schristos #define ST_ASSOC_REQUEST 0x0 82b3a00663Schristos #define ST_ASSOC_RESPONSE 0x1 83b3a00663Schristos #define ST_REASSOC_REQUEST 0x2 84b3a00663Schristos #define ST_REASSOC_RESPONSE 0x3 85b3a00663Schristos #define ST_PROBE_REQUEST 0x4 86b3a00663Schristos #define ST_PROBE_RESPONSE 0x5 87b3a00663Schristos /* RESERVED 0x6 */ 88b3a00663Schristos /* RESERVED 0x7 */ 89b3a00663Schristos #define ST_BEACON 0x8 90b3a00663Schristos #define ST_ATIM 0x9 91b3a00663Schristos #define ST_DISASSOC 0xA 92b3a00663Schristos #define ST_AUTH 0xB 93b3a00663Schristos #define ST_DEAUTH 0xC 94b3a00663Schristos #define ST_ACTION 0xD 95b3a00663Schristos /* RESERVED 0xE */ 96b3a00663Schristos /* RESERVED 0xF */ 97b3a00663Schristos 98b3a00663Schristos static const struct tok st_str[] = { 99b3a00663Schristos { ST_ASSOC_REQUEST, "Assoc Request" }, 100b3a00663Schristos { ST_ASSOC_RESPONSE, "Assoc Response" }, 101b3a00663Schristos { ST_REASSOC_REQUEST, "ReAssoc Request" }, 102b3a00663Schristos { ST_REASSOC_RESPONSE, "ReAssoc Response" }, 103b3a00663Schristos { ST_PROBE_REQUEST, "Probe Request" }, 104b3a00663Schristos { ST_PROBE_RESPONSE, "Probe Response" }, 105b3a00663Schristos { ST_BEACON, "Beacon" }, 106b3a00663Schristos { ST_ATIM, "ATIM" }, 107b3a00663Schristos { ST_DISASSOC, "Disassociation" }, 108b3a00663Schristos { ST_AUTH, "Authentication" }, 109b3a00663Schristos { ST_DEAUTH, "DeAuthentication" }, 110b3a00663Schristos { ST_ACTION, "Action" }, 111b3a00663Schristos { 0, NULL } 112b3a00663Schristos }; 113b3a00663Schristos 114b3a00663Schristos #define CTRL_CONTROL_WRAPPER 0x7 115b3a00663Schristos #define CTRL_BAR 0x8 116b3a00663Schristos #define CTRL_BA 0x9 117b3a00663Schristos #define CTRL_PS_POLL 0xA 118b3a00663Schristos #define CTRL_RTS 0xB 119b3a00663Schristos #define CTRL_CTS 0xC 120b3a00663Schristos #define CTRL_ACK 0xD 121b3a00663Schristos #define CTRL_CF_END 0xE 122b3a00663Schristos #define CTRL_END_ACK 0xF 123b3a00663Schristos 124b3a00663Schristos static const struct tok ctrl_str[] = { 125b3a00663Schristos { CTRL_CONTROL_WRAPPER, "Control Wrapper" }, 126b3a00663Schristos { CTRL_BAR, "BAR" }, 127b3a00663Schristos { CTRL_BA, "BA" }, 128b3a00663Schristos { CTRL_PS_POLL, "Power Save-Poll" }, 129b3a00663Schristos { CTRL_RTS, "Request-To-Send" }, 130b3a00663Schristos { CTRL_CTS, "Clear-To-Send" }, 131b3a00663Schristos { CTRL_ACK, "Acknowledgment" }, 132b3a00663Schristos { CTRL_CF_END, "CF-End" }, 133b3a00663Schristos { CTRL_END_ACK, "CF-End+CF-Ack" }, 134b3a00663Schristos { 0, NULL } 135b3a00663Schristos }; 136b3a00663Schristos 137b3a00663Schristos #define DATA_DATA 0x0 138b3a00663Schristos #define DATA_DATA_CF_ACK 0x1 139b3a00663Schristos #define DATA_DATA_CF_POLL 0x2 140b3a00663Schristos #define DATA_DATA_CF_ACK_POLL 0x3 141b3a00663Schristos #define DATA_NODATA 0x4 142b3a00663Schristos #define DATA_NODATA_CF_ACK 0x5 143b3a00663Schristos #define DATA_NODATA_CF_POLL 0x6 144b3a00663Schristos #define DATA_NODATA_CF_ACK_POLL 0x7 145b3a00663Schristos 146b3a00663Schristos #define DATA_QOS_DATA 0x8 147b3a00663Schristos #define DATA_QOS_DATA_CF_ACK 0x9 148b3a00663Schristos #define DATA_QOS_DATA_CF_POLL 0xA 149b3a00663Schristos #define DATA_QOS_DATA_CF_ACK_POLL 0xB 150b3a00663Schristos #define DATA_QOS_NODATA 0xC 151b3a00663Schristos #define DATA_QOS_CF_POLL_NODATA 0xE 152b3a00663Schristos #define DATA_QOS_CF_ACK_POLL_NODATA 0xF 153b3a00663Schristos 154b3a00663Schristos /* 155b3a00663Schristos * The subtype field of a data frame is, in effect, composed of 4 flag 156b3a00663Schristos * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have 157b3a00663Schristos * any data), and QoS. 158b3a00663Schristos */ 159b3a00663Schristos #define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01) 160b3a00663Schristos #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02) 161b3a00663Schristos #define DATA_FRAME_IS_NULL(x) ((x) & 0x04) 162b3a00663Schristos #define DATA_FRAME_IS_QOS(x) ((x) & 0x08) 163b3a00663Schristos 164b3a00663Schristos /* 165b3a00663Schristos * Bits in the frame control field. 166b3a00663Schristos */ 167b3a00663Schristos #define FC_VERSION(fc) ((fc) & 0x3) 168b3a00663Schristos #define FC_TYPE(fc) (((fc) >> 2) & 0x3) 169b3a00663Schristos #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF) 170b3a00663Schristos #define FC_TO_DS(fc) ((fc) & 0x0100) 171b3a00663Schristos #define FC_FROM_DS(fc) ((fc) & 0x0200) 172b3a00663Schristos #define FC_MORE_FLAG(fc) ((fc) & 0x0400) 173b3a00663Schristos #define FC_RETRY(fc) ((fc) & 0x0800) 174b3a00663Schristos #define FC_POWER_MGMT(fc) ((fc) & 0x1000) 175b3a00663Schristos #define FC_MORE_DATA(fc) ((fc) & 0x2000) 176fdccd7e4Schristos #define FC_PROTECTED(fc) ((fc) & 0x4000) 177b3a00663Schristos #define FC_ORDER(fc) ((fc) & 0x8000) 178b3a00663Schristos 179b3a00663Schristos struct mgmt_header_t { 180c74ad251Schristos nd_uint16_t fc; 181c74ad251Schristos nd_uint16_t duration; 182c74ad251Schristos nd_mac_addr da; 183c74ad251Schristos nd_mac_addr sa; 184c74ad251Schristos nd_mac_addr bssid; 185c74ad251Schristos nd_uint16_t seq_ctrl; 186b3a00663Schristos }; 187b3a00663Schristos 188b3a00663Schristos #define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 189b3a00663Schristos IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\ 190b3a00663Schristos IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN) 191b3a00663Schristos 192b3a00663Schristos #define CAPABILITY_ESS(cap) ((cap) & 0x0001) 193b3a00663Schristos #define CAPABILITY_IBSS(cap) ((cap) & 0x0002) 194b3a00663Schristos #define CAPABILITY_CFP(cap) ((cap) & 0x0004) 195b3a00663Schristos #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008) 196b3a00663Schristos #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010) 197b3a00663Schristos 198b3a00663Schristos struct ssid_t { 199*26ba0b50Schristos u_int length; 200b3a00663Schristos u_char ssid[33]; /* 32 + 1 for null */ 201b3a00663Schristos }; 202b3a00663Schristos 203b3a00663Schristos struct rates_t { 204*26ba0b50Schristos u_int length; 205b3a00663Schristos uint8_t rate[16]; 206b3a00663Schristos }; 207b3a00663Schristos 208b3a00663Schristos struct challenge_t { 209*26ba0b50Schristos u_int length; 210b3a00663Schristos uint8_t text[254]; /* 1-253 + 1 for null */ 211b3a00663Schristos }; 212b3a00663Schristos 213b3a00663Schristos struct fh_t { 214*26ba0b50Schristos u_int length; 215b3a00663Schristos uint16_t dwell_time; 216b3a00663Schristos uint8_t hop_set; 217b3a00663Schristos uint8_t hop_pattern; 218b3a00663Schristos uint8_t hop_index; 219b3a00663Schristos }; 220b3a00663Schristos 221b3a00663Schristos struct ds_t { 222*26ba0b50Schristos u_int length; 223b3a00663Schristos uint8_t channel; 224b3a00663Schristos }; 225b3a00663Schristos 226b3a00663Schristos struct cf_t { 227*26ba0b50Schristos u_int length; 228b3a00663Schristos uint8_t count; 229b3a00663Schristos uint8_t period; 230b3a00663Schristos uint16_t max_duration; 231c74ad251Schristos uint16_t dur_remaining; 232b3a00663Schristos }; 233b3a00663Schristos 234b3a00663Schristos struct tim_t { 235*26ba0b50Schristos u_int length; 236b3a00663Schristos uint8_t count; 237b3a00663Schristos uint8_t period; 238b3a00663Schristos uint8_t bitmap_control; 239b3a00663Schristos uint8_t bitmap[251]; 240b3a00663Schristos }; 241b3a00663Schristos 242b3a00663Schristos #define E_SSID 0 243b3a00663Schristos #define E_RATES 1 244b3a00663Schristos #define E_FH 2 245b3a00663Schristos #define E_DS 3 246b3a00663Schristos #define E_CF 4 247b3a00663Schristos #define E_TIM 5 248b3a00663Schristos #define E_IBSS 6 249b3a00663Schristos /* reserved 7 */ 250b3a00663Schristos /* reserved 8 */ 251b3a00663Schristos /* reserved 9 */ 252b3a00663Schristos /* reserved 10 */ 253b3a00663Schristos /* reserved 11 */ 254b3a00663Schristos /* reserved 12 */ 255b3a00663Schristos /* reserved 13 */ 256b3a00663Schristos /* reserved 14 */ 257b3a00663Schristos /* reserved 15 */ 258b3a00663Schristos /* reserved 16 */ 259b3a00663Schristos 260b3a00663Schristos #define E_CHALLENGE 16 261b3a00663Schristos /* reserved 17 */ 262b3a00663Schristos /* reserved 18 */ 263b3a00663Schristos /* reserved 19 */ 264b3a00663Schristos /* reserved 16 */ 265b3a00663Schristos /* reserved 16 */ 266b3a00663Schristos 267b3a00663Schristos 268b3a00663Schristos struct mgmt_body_t { 269b3a00663Schristos uint8_t timestamp[IEEE802_11_TSTAMP_LEN]; 270b3a00663Schristos uint16_t beacon_interval; 271b3a00663Schristos uint16_t listen_interval; 272b3a00663Schristos uint16_t status_code; 273b3a00663Schristos uint16_t aid; 274b3a00663Schristos u_char ap[IEEE802_11_AP_LEN]; 275b3a00663Schristos uint16_t reason_code; 276b3a00663Schristos uint16_t auth_alg; 277b3a00663Schristos uint16_t auth_trans_seq_num; 278b3a00663Schristos int challenge_present; 279b3a00663Schristos struct challenge_t challenge; 280b3a00663Schristos uint16_t capability_info; 281b3a00663Schristos int ssid_present; 282b3a00663Schristos struct ssid_t ssid; 283b3a00663Schristos int rates_present; 284b3a00663Schristos struct rates_t rates; 285b3a00663Schristos int ds_present; 286b3a00663Schristos struct ds_t ds; 287b3a00663Schristos int cf_present; 288b3a00663Schristos struct cf_t cf; 289b3a00663Schristos int fh_present; 290b3a00663Schristos struct fh_t fh; 291b3a00663Schristos int tim_present; 292b3a00663Schristos struct tim_t tim; 293b3a00663Schristos }; 294b3a00663Schristos 295fdccd7e4Schristos struct ctrl_control_wrapper_hdr_t { 296c74ad251Schristos nd_uint16_t fc; 297c74ad251Schristos nd_uint16_t duration; 298c74ad251Schristos nd_mac_addr addr1; 299c74ad251Schristos nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN]; 300c74ad251Schristos nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN]; 301fdccd7e4Schristos }; 302fdccd7e4Schristos 303fdccd7e4Schristos #define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 304fdccd7e4Schristos IEEE802_11_ADDR1_LEN+\ 305fdccd7e4Schristos IEEE802_11_CARRIED_FC_LEN+\ 306fdccd7e4Schristos IEEE802_11_HT_CONTROL_LEN) 307fdccd7e4Schristos 308fdccd7e4Schristos struct ctrl_rts_hdr_t { 309c74ad251Schristos nd_uint16_t fc; 310c74ad251Schristos nd_uint16_t duration; 311c74ad251Schristos nd_mac_addr ra; 312c74ad251Schristos nd_mac_addr ta; 313b3a00663Schristos }; 314b3a00663Schristos 315b3a00663Schristos #define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 316b3a00663Schristos IEEE802_11_RA_LEN+IEEE802_11_TA_LEN) 317b3a00663Schristos 318fdccd7e4Schristos struct ctrl_cts_hdr_t { 319c74ad251Schristos nd_uint16_t fc; 320c74ad251Schristos nd_uint16_t duration; 321c74ad251Schristos nd_mac_addr ra; 322b3a00663Schristos }; 323b3a00663Schristos 324b3a00663Schristos #define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 325b3a00663Schristos 326fdccd7e4Schristos struct ctrl_ack_hdr_t { 327c74ad251Schristos nd_uint16_t fc; 328c74ad251Schristos nd_uint16_t duration; 329c74ad251Schristos nd_mac_addr ra; 330b3a00663Schristos }; 331b3a00663Schristos 332b3a00663Schristos #define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 333b3a00663Schristos 334fdccd7e4Schristos struct ctrl_ps_poll_hdr_t { 335c74ad251Schristos nd_uint16_t fc; 336c74ad251Schristos nd_uint16_t aid; 337c74ad251Schristos nd_mac_addr bssid; 338c74ad251Schristos nd_mac_addr ta; 339b3a00663Schristos }; 340b3a00663Schristos 341b3a00663Schristos #define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\ 342b3a00663Schristos IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN) 343b3a00663Schristos 344fdccd7e4Schristos struct ctrl_end_hdr_t { 345c74ad251Schristos nd_uint16_t fc; 346c74ad251Schristos nd_uint16_t duration; 347c74ad251Schristos nd_mac_addr ra; 348c74ad251Schristos nd_mac_addr bssid; 349b3a00663Schristos }; 350b3a00663Schristos 351b3a00663Schristos #define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 352b3a00663Schristos IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) 353b3a00663Schristos 354fdccd7e4Schristos struct ctrl_end_ack_hdr_t { 355c74ad251Schristos nd_uint16_t fc; 356c74ad251Schristos nd_uint16_t duration; 357c74ad251Schristos nd_mac_addr ra; 358c74ad251Schristos nd_mac_addr bssid; 359b3a00663Schristos }; 360b3a00663Schristos 361b3a00663Schristos #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 362b3a00663Schristos IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) 363b3a00663Schristos 364fdccd7e4Schristos struct ctrl_ba_hdr_t { 365c74ad251Schristos nd_uint16_t fc; 366c74ad251Schristos nd_uint16_t duration; 367c74ad251Schristos nd_mac_addr ra; 368*26ba0b50Schristos nd_mac_addr ta; 369b3a00663Schristos }; 370b3a00663Schristos 371*26ba0b50Schristos #define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 372*26ba0b50Schristos IEEE802_11_RA_LEN+IEEE802_11_TA_LEN) 373b3a00663Schristos 374fdccd7e4Schristos struct ctrl_bar_hdr_t { 375c74ad251Schristos nd_uint16_t fc; 376c74ad251Schristos nd_uint16_t dur; 377c74ad251Schristos nd_mac_addr ra; 378c74ad251Schristos nd_mac_addr ta; 379c74ad251Schristos nd_uint16_t ctl; 380c74ad251Schristos nd_uint16_t seq; 381b3a00663Schristos }; 382b3a00663Schristos 383b3a00663Schristos #define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 384b3a00663Schristos IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\ 385b3a00663Schristos IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN) 386b3a00663Schristos 387b3a00663Schristos struct meshcntl_t { 388c74ad251Schristos nd_uint8_t flags; 389c74ad251Schristos nd_uint8_t ttl; 390c74ad251Schristos nd_uint32_t seq; 391c74ad251Schristos nd_mac_addr addr4; 392c74ad251Schristos nd_mac_addr addr5; 393c74ad251Schristos nd_mac_addr addr6; 394b3a00663Schristos }; 395b3a00663Schristos 396b3a00663Schristos #define IV_IV(iv) ((iv) & 0xFFFFFF) 397b3a00663Schristos #define IV_PAD(iv) (((iv) >> 24) & 0x3F) 398b3a00663Schristos #define IV_KEYID(iv) (((iv) >> 30) & 0x03) 399b3a00663Schristos 4000f74e101Schristos #define PRINT_SSID(p) \ 4010f74e101Schristos if (p.ssid_present) { \ 402c74ad251Schristos ND_PRINT(" ("); \ 403c74ad251Schristos fn_print_str(ndo, p.ssid.ssid); \ 404c74ad251Schristos ND_PRINT(")"); \ 4050f74e101Schristos } 4060f74e101Schristos 4070f74e101Schristos #define PRINT_RATE(_sep, _r, _suf) \ 408c74ad251Schristos ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf) 4090f74e101Schristos #define PRINT_RATES(p) \ 4100f74e101Schristos if (p.rates_present) { \ 4110f74e101Schristos const char *sep = " ["; \ 412*26ba0b50Schristos if (p.rates.length != 0) { \ 413*26ba0b50Schristos for (u_int z = 0; z < p.rates.length ; z++) { \ 4140f74e101Schristos PRINT_RATE(sep, p.rates.rate[z], \ 4150f74e101Schristos (p.rates.rate[z] & 0x80 ? "*" : "")); \ 4160f74e101Schristos sep = " "; \ 4170f74e101Schristos } \ 418c74ad251Schristos ND_PRINT(" Mbit]"); \ 419*26ba0b50Schristos } \ 4200f74e101Schristos } 4210f74e101Schristos 4220f74e101Schristos #define PRINT_DS_CHANNEL(p) \ 4230f74e101Schristos if (p.ds_present) \ 424c74ad251Schristos ND_PRINT(" CH: %u", p.ds.channel); \ 425c74ad251Schristos ND_PRINT("%s", \ 426c74ad251Schristos CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : ""); 4270f74e101Schristos 4280e9868baSchristos #define MAX_MCS_INDEX 76 4290e9868baSchristos 4300e9868baSchristos /* 4310e9868baSchristos * Indices are: 4320e9868baSchristos * 4330e9868baSchristos * the MCS index (0-76); 4340e9868baSchristos * 4350e9868baSchristos * 0 for 20 MHz, 1 for 40 MHz; 4360e9868baSchristos * 4370e9868baSchristos * 0 for a long guard interval, 1 for a short guard interval. 4380e9868baSchristos */ 4390e9868baSchristos static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = { 4400e9868baSchristos /* MCS 0 */ 441c74ad251Schristos { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, }, 442c74ad251Schristos /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, }, 4430e9868baSchristos }, 4440e9868baSchristos 4450e9868baSchristos /* MCS 1 */ 446c74ad251Schristos { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, 447c74ad251Schristos /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, 4480e9868baSchristos }, 4490e9868baSchristos 4500e9868baSchristos /* MCS 2 */ 451c74ad251Schristos { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, 452c74ad251Schristos /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, 4530e9868baSchristos }, 4540e9868baSchristos 4550e9868baSchristos /* MCS 3 */ 456c74ad251Schristos { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, 457c74ad251Schristos /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, 4580e9868baSchristos }, 4590e9868baSchristos 4600e9868baSchristos /* MCS 4 */ 461c74ad251Schristos { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 462c74ad251Schristos /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 4630e9868baSchristos }, 4640e9868baSchristos 4650e9868baSchristos /* MCS 5 */ 466c74ad251Schristos { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 467c74ad251Schristos /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 4680e9868baSchristos }, 4690e9868baSchristos 4700e9868baSchristos /* MCS 6 */ 471c74ad251Schristos { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, 472c74ad251Schristos /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, 4730e9868baSchristos }, 4740e9868baSchristos 4750e9868baSchristos /* MCS 7 */ 476c74ad251Schristos { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 477c74ad251Schristos /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 4780e9868baSchristos }, 4790e9868baSchristos 4800e9868baSchristos /* MCS 8 */ 481c74ad251Schristos { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, 482c74ad251Schristos /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, 4830e9868baSchristos }, 4840e9868baSchristos 4850e9868baSchristos /* MCS 9 */ 486c74ad251Schristos { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, 487c74ad251Schristos /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, 4880e9868baSchristos }, 4890e9868baSchristos 4900e9868baSchristos /* MCS 10 */ 491c74ad251Schristos { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 492c74ad251Schristos /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 4930e9868baSchristos }, 4940e9868baSchristos 4950e9868baSchristos /* MCS 11 */ 496c74ad251Schristos { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 497c74ad251Schristos /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 4980e9868baSchristos }, 4990e9868baSchristos 5000e9868baSchristos /* MCS 12 */ 501c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 502c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 5030e9868baSchristos }, 5040e9868baSchristos 5050e9868baSchristos /* MCS 13 */ 506c74ad251Schristos { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 507c74ad251Schristos /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 5080e9868baSchristos }, 5090e9868baSchristos 5100e9868baSchristos /* MCS 14 */ 511c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 512c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 5130e9868baSchristos }, 5140e9868baSchristos 5150e9868baSchristos /* MCS 15 */ 516c74ad251Schristos { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, 517c74ad251Schristos /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, 5180e9868baSchristos }, 5190e9868baSchristos 5200e9868baSchristos /* MCS 16 */ 521c74ad251Schristos { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, 522c74ad251Schristos /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, 5230e9868baSchristos }, 5240e9868baSchristos 5250e9868baSchristos /* MCS 17 */ 526c74ad251Schristos { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 527c74ad251Schristos /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 5280e9868baSchristos }, 5290e9868baSchristos 5300e9868baSchristos /* MCS 18 */ 531c74ad251Schristos { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, 532c74ad251Schristos /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, 5330e9868baSchristos }, 5340e9868baSchristos 5350e9868baSchristos /* MCS 19 */ 536c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 537c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 5380e9868baSchristos }, 5390e9868baSchristos 5400e9868baSchristos /* MCS 20 */ 541c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 542c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 5430e9868baSchristos }, 5440e9868baSchristos 5450e9868baSchristos /* MCS 21 */ 546c74ad251Schristos { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 547c74ad251Schristos /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 5480e9868baSchristos }, 5490e9868baSchristos 5500e9868baSchristos /* MCS 22 */ 551c74ad251Schristos { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, 552c74ad251Schristos /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, 5530e9868baSchristos }, 5540e9868baSchristos 5550e9868baSchristos /* MCS 23 */ 556c74ad251Schristos { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, 557c74ad251Schristos /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, 5580e9868baSchristos }, 5590e9868baSchristos 5600e9868baSchristos /* MCS 24 */ 561c74ad251Schristos { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, 562c74ad251Schristos /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, 5630e9868baSchristos }, 5640e9868baSchristos 5650e9868baSchristos /* MCS 25 */ 566c74ad251Schristos { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 567c74ad251Schristos /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 5680e9868baSchristos }, 5690e9868baSchristos 5700e9868baSchristos /* MCS 26 */ 571c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 572c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 5730e9868baSchristos }, 5740e9868baSchristos 5750e9868baSchristos /* MCS 27 */ 576c74ad251Schristos { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 577c74ad251Schristos /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 5780e9868baSchristos }, 5790e9868baSchristos 5800e9868baSchristos /* MCS 28 */ 581c74ad251Schristos { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 582c74ad251Schristos /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 5830e9868baSchristos }, 5840e9868baSchristos 5850e9868baSchristos /* MCS 29 */ 586c74ad251Schristos { /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, }, 587c74ad251Schristos /* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, }, 5880e9868baSchristos }, 5890e9868baSchristos 5900e9868baSchristos /* MCS 30 */ 591c74ad251Schristos { /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, }, 592c74ad251Schristos /* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, }, 5930e9868baSchristos }, 5940e9868baSchristos 5950e9868baSchristos /* MCS 31 */ 596c74ad251Schristos { /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, }, 597c74ad251Schristos /* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, }, 5980e9868baSchristos }, 5990e9868baSchristos 6000e9868baSchristos /* MCS 32 */ 601c74ad251Schristos { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */ 602c74ad251Schristos /* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, }, 6030e9868baSchristos }, 6040e9868baSchristos 6050e9868baSchristos /* MCS 33 */ 606c74ad251Schristos { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, 607c74ad251Schristos /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, 6080e9868baSchristos }, 6090e9868baSchristos 6100e9868baSchristos /* MCS 34 */ 611c74ad251Schristos { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 612c74ad251Schristos /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 6130e9868baSchristos }, 6140e9868baSchristos 6150e9868baSchristos /* MCS 35 */ 616c74ad251Schristos { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 617c74ad251Schristos /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 6180e9868baSchristos }, 6190e9868baSchristos 6200e9868baSchristos /* MCS 36 */ 621c74ad251Schristos { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, 622c74ad251Schristos /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, 6230e9868baSchristos }, 6240e9868baSchristos 6250e9868baSchristos /* MCS 37 */ 626c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 627c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 6280e9868baSchristos }, 6290e9868baSchristos 6300e9868baSchristos /* MCS 38 */ 631c74ad251Schristos { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 632c74ad251Schristos /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 6330e9868baSchristos }, 6340e9868baSchristos 6350e9868baSchristos /* MCS 39 */ 636c74ad251Schristos { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, 637c74ad251Schristos /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, 6380e9868baSchristos }, 6390e9868baSchristos 6400e9868baSchristos /* MCS 40 */ 641c74ad251Schristos { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 642c74ad251Schristos /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 6430e9868baSchristos }, 6440e9868baSchristos 6450e9868baSchristos /* MCS 41 */ 646c74ad251Schristos { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 647c74ad251Schristos /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 6480e9868baSchristos }, 6490e9868baSchristos 6500e9868baSchristos /* MCS 42 */ 651c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 652c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 6530e9868baSchristos }, 6540e9868baSchristos 6550e9868baSchristos /* MCS 43 */ 656c74ad251Schristos { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 657c74ad251Schristos /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 6580e9868baSchristos }, 6590e9868baSchristos 6600e9868baSchristos /* MCS 44 */ 661c74ad251Schristos { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 662c74ad251Schristos /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 6630e9868baSchristos }, 6640e9868baSchristos 6650e9868baSchristos /* MCS 45 */ 666c74ad251Schristos { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 667c74ad251Schristos /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 6680e9868baSchristos }, 6690e9868baSchristos 6700e9868baSchristos /* MCS 46 */ 671c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 672c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 6730e9868baSchristos }, 6740e9868baSchristos 6750e9868baSchristos /* MCS 47 */ 676c74ad251Schristos { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 677c74ad251Schristos /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 6780e9868baSchristos }, 6790e9868baSchristos 6800e9868baSchristos /* MCS 48 */ 681c74ad251Schristos { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 682c74ad251Schristos /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 6830e9868baSchristos }, 6840e9868baSchristos 6850e9868baSchristos /* MCS 49 */ 686c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 687c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 6880e9868baSchristos }, 6890e9868baSchristos 6900e9868baSchristos /* MCS 50 */ 691c74ad251Schristos { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 692c74ad251Schristos /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 6930e9868baSchristos }, 6940e9868baSchristos 6950e9868baSchristos /* MCS 51 */ 696c74ad251Schristos { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 697c74ad251Schristos /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 6980e9868baSchristos }, 6990e9868baSchristos 7000e9868baSchristos /* MCS 52 */ 701c74ad251Schristos { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 702c74ad251Schristos /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 7030e9868baSchristos }, 7040e9868baSchristos 7050e9868baSchristos /* MCS 53 */ 706c74ad251Schristos { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, 707c74ad251Schristos /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, 7080e9868baSchristos }, 7090e9868baSchristos 7100e9868baSchristos /* MCS 54 */ 711c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 712c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 7130e9868baSchristos }, 7140e9868baSchristos 7150e9868baSchristos /* MCS 55 */ 716c74ad251Schristos { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 717c74ad251Schristos /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 7180e9868baSchristos }, 7190e9868baSchristos 7200e9868baSchristos /* MCS 56 */ 721c74ad251Schristos { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, 722c74ad251Schristos /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, 7230e9868baSchristos }, 7240e9868baSchristos 7250e9868baSchristos /* MCS 57 */ 726c74ad251Schristos { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, 727c74ad251Schristos /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, 7280e9868baSchristos }, 7290e9868baSchristos 7300e9868baSchristos /* MCS 58 */ 731c74ad251Schristos { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 732c74ad251Schristos /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 7330e9868baSchristos }, 7340e9868baSchristos 7350e9868baSchristos /* MCS 59 */ 736c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 737c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 7380e9868baSchristos }, 7390e9868baSchristos 7400e9868baSchristos /* MCS 60 */ 741c74ad251Schristos { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, 742c74ad251Schristos /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, 7430e9868baSchristos }, 7440e9868baSchristos 7450e9868baSchristos /* MCS 61 */ 746c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 747c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 7480e9868baSchristos }, 7490e9868baSchristos 7500e9868baSchristos /* MCS 62 */ 751c74ad251Schristos { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, 752c74ad251Schristos /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, 7530e9868baSchristos }, 7540e9868baSchristos 7550e9868baSchristos /* MCS 63 */ 756c74ad251Schristos { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, 757c74ad251Schristos /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, 7580e9868baSchristos }, 7590e9868baSchristos 7600e9868baSchristos /* MCS 64 */ 761c74ad251Schristos { /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, }, 762c74ad251Schristos /* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, }, 7630e9868baSchristos }, 7640e9868baSchristos 7650e9868baSchristos /* MCS 65 */ 766c74ad251Schristos { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, 767c74ad251Schristos /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, 7680e9868baSchristos }, 7690e9868baSchristos 7700e9868baSchristos /* MCS 66 */ 771c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 772c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 7730e9868baSchristos }, 7740e9868baSchristos 7750e9868baSchristos /* MCS 67 */ 776c74ad251Schristos { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 777c74ad251Schristos /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 7780e9868baSchristos }, 7790e9868baSchristos 7800e9868baSchristos /* MCS 68 */ 781c74ad251Schristos { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, 782c74ad251Schristos /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, 7830e9868baSchristos }, 7840e9868baSchristos 7850e9868baSchristos /* MCS 69 */ 786c74ad251Schristos { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, 787c74ad251Schristos /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, 7880e9868baSchristos }, 7890e9868baSchristos 7900e9868baSchristos /* MCS 70 */ 791c74ad251Schristos { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 792c74ad251Schristos /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 7930e9868baSchristos }, 7940e9868baSchristos 7950e9868baSchristos /* MCS 71 */ 796c74ad251Schristos { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, 797c74ad251Schristos /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, 7980e9868baSchristos }, 7990e9868baSchristos 8000e9868baSchristos /* MCS 72 */ 801c74ad251Schristos { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, 802c74ad251Schristos /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, 8030e9868baSchristos }, 8040e9868baSchristos 8050e9868baSchristos /* MCS 73 */ 806c74ad251Schristos { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, 807c74ad251Schristos /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, 8080e9868baSchristos }, 8090e9868baSchristos 8100e9868baSchristos /* MCS 74 */ 811c74ad251Schristos { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, 812c74ad251Schristos /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, 8130e9868baSchristos }, 8140e9868baSchristos 8150e9868baSchristos /* MCS 75 */ 816c74ad251Schristos { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, 817c74ad251Schristos /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, 8180e9868baSchristos }, 8190e9868baSchristos 8200e9868baSchristos /* MCS 76 */ 821c74ad251Schristos { /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, }, 822c74ad251Schristos /* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, }, 8230e9868baSchristos }, 8240f74e101Schristos }; 8250f74e101Schristos 8260f74e101Schristos static const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; 827c74ad251Schristos #define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0])) 8280f74e101Schristos 8290f74e101Schristos static const char *status_text[] = { 8300e9868baSchristos "Successful", /* 0 */ 8310f74e101Schristos "Unspecified failure", /* 1 */ 832c74ad251Schristos "TDLS wakeup schedule rejected but alternative schedule " 833c74ad251Schristos "provided", /* 2 */ 834c74ad251Schristos "TDLS wakeup schedule rejected",/* 3 */ 8350f74e101Schristos "Reserved", /* 4 */ 836c74ad251Schristos "Security disabled", /* 5 */ 837c74ad251Schristos "Unacceptable lifetime", /* 6 */ 838c74ad251Schristos "Not in same BSS", /* 7 */ 8390f74e101Schristos "Reserved", /* 8 */ 8400f74e101Schristos "Reserved", /* 9 */ 8410f74e101Schristos "Cannot Support all requested capabilities in the Capability " 8420f74e101Schristos "Information field", /* 10 */ 8430f74e101Schristos "Reassociation denied due to inability to confirm that association " 8440f74e101Schristos "exists", /* 11 */ 845c74ad251Schristos "Association denied due to reason outside the scope of this " 8460f74e101Schristos "standard", /* 12 */ 847c74ad251Schristos "Responding STA does not support the specified authentication " 8480f74e101Schristos "algorithm", /* 13 */ 8490f74e101Schristos "Received an Authentication frame with authentication transaction " 8500f74e101Schristos "sequence number out of expected sequence", /* 14 */ 8510f74e101Schristos "Authentication rejected because of challenge failure", /* 15 */ 8520f74e101Schristos "Authentication rejected due to timeout waiting for next frame in " 8530f74e101Schristos "sequence", /* 16 */ 854c74ad251Schristos "Association denied because AP is unable to handle " 855c74ad251Schristos "additional associated STAs", /* 17 */ 856c74ad251Schristos "Association denied due to requesting STA not supporting " 857c74ad251Schristos "all of the data rates in the BSSBasicRateSet parameter, " 858c74ad251Schristos "the Basic HT-MCS Set field of the HT Operation " 859c74ad251Schristos "parameter, or the Basic VHT-MCS and NSS Set field in " 860c74ad251Schristos "the VHT Operation parameter", /* 18 */ 861c74ad251Schristos "Association denied due to requesting STA not supporting " 862c74ad251Schristos "the short preamble option", /* 19 */ 863c74ad251Schristos "Reserved", /* 20 */ 864c74ad251Schristos "Reserved", /* 21 */ 8650f74e101Schristos "Association request rejected because Spectrum Management " 8660f74e101Schristos "capability is required", /* 22 */ 8670f74e101Schristos "Association request rejected because the information in the " 8680f74e101Schristos "Power Capability element is unacceptable", /* 23 */ 8690f74e101Schristos "Association request rejected because the information in the " 8700f74e101Schristos "Supported Channels element is unacceptable", /* 24 */ 871c74ad251Schristos "Association denied due to requesting STA not supporting " 872c74ad251Schristos "the Short Slot Time option", /* 25 */ 873c74ad251Schristos "Reserved", /* 26 */ 8740f74e101Schristos "Association denied because the requested STA does not support HT " 8750f74e101Schristos "features", /* 27 */ 876c74ad251Schristos "R0KH unreachable", /* 28 */ 877c74ad251Schristos "Association denied because the requesting STA does not " 878c74ad251Schristos "support the phased coexistence operation (PCO) " 879c74ad251Schristos "transition time required by the AP", /* 29 */ 880c74ad251Schristos "Association request rejected temporarily; try again " 881c74ad251Schristos "later", /* 30 */ 882c74ad251Schristos "Robust management frame policy violation", /* 31 */ 8830f74e101Schristos "Unspecified, QoS-related failure", /* 32 */ 884c74ad251Schristos "Association denied because QoS AP or PCP has " 885c74ad251Schristos "insufficient bandwidth to handle another QoS " 886c74ad251Schristos "STA", /* 33 */ 8870f74e101Schristos "Association denied due to excessive frame loss rates and/or " 8880f74e101Schristos "poor conditions on current operating channel", /* 34 */ 889c74ad251Schristos "Association (with QoS BSS) denied because the requesting STA " 890c74ad251Schristos "does not support the QoS facility", /* 35 */ 891c74ad251Schristos "Reserved", /* 36 */ 8920f74e101Schristos "The request has been declined", /* 37 */ 8930f74e101Schristos "The request has not been successful as one or more parameters " 8940f74e101Schristos "have invalid values", /* 38 */ 895c74ad251Schristos "The allocation or TS has not been created because the request " 896c74ad251Schristos "cannot be honored; however, a suggested TSPEC/DMG TSPEC is " 897c74ad251Schristos "provided so that the initiating STA can attempt to set " 898c74ad251Schristos "another allocation or TS with the suggested changes to the " 899c74ad251Schristos "TSPEC/DMG TSPEC", /* 39 */ 900c74ad251Schristos "Invalid element, i.e., an element defined in this standard " 901c74ad251Schristos "for which the content does not meet the specifications in " 902c74ad251Schristos "Clause 9", /* 40 */ 903c74ad251Schristos "Invalid group cipher", /* 41 */ 904c74ad251Schristos "Invalid pairwise cipher", /* 42 */ 905c74ad251Schristos "Invalid AKMP", /* 43 */ 906c74ad251Schristos "Unsupported RSNE version", /* 44 */ 907c74ad251Schristos "Invalid RSNE capabilities", /* 45 */ 908c74ad251Schristos "Cipher suite rejected because of security policy", /* 46 */ 909c74ad251Schristos "The TS or allocation has not been created; however, the " 910c74ad251Schristos "HC or PCP might be capable of creating a TS or " 911c74ad251Schristos "allocation, in response to a request, after the time " 912c74ad251Schristos "indicated in the TS Delay element", /* 47 */ 9130f74e101Schristos "Direct Link is not allowed in the BSS by policy", /* 48 */ 914c74ad251Schristos "The Destination STA is not present within this BSS", /* 49 */ 915c74ad251Schristos "The Destination STA is not a QoS STA", /* 50 */ 9160f74e101Schristos 917c74ad251Schristos "Association denied because the listen interval is " 918c74ad251Schristos "too large", /* 51 */ 919c74ad251Schristos "Invalid FT Action frame count", /* 52 */ 920c74ad251Schristos "Invalid pairwise master key identifier (PMKID)", /* 53 */ 921c74ad251Schristos "Invalid MDE", /* 54 */ 922c74ad251Schristos "Invalid FTE", /* 55 */ 923c74ad251Schristos "Requested TCLAS processing is not supported by the AP " 924c74ad251Schristos "or PCP", /* 56 */ 925c74ad251Schristos "The AP or PCP has insufficient TCLAS processing " 926c74ad251Schristos "resources to satisfy the request", /* 57 */ 927c74ad251Schristos "The TS has not been created because the request " 928c74ad251Schristos "cannot be honored; however, the HC or PCP suggests " 929c74ad251Schristos "that the STA transition to a different BSS to set up " 930c74ad251Schristos "the TS", /* 58 */ 931c74ad251Schristos "GAS Advertisement Protocol not supported", /* 59 */ 932c74ad251Schristos "No outstanding GAS request", /* 60 */ 933c74ad251Schristos "GAS Response not received from the Advertisement " 934c74ad251Schristos "Server", /* 61 */ 935c74ad251Schristos "STA timed out waiting for GAS Query Response", /* 62 */ 936c74ad251Schristos "LARGE GAS Response is larger than query response " 937c74ad251Schristos "length limit", /* 63 */ 938c74ad251Schristos "Request refused because home network does not support " 939c74ad251Schristos "request", /* 64 */ 940c74ad251Schristos "Advertisement Server in the network is not currently " 941c74ad251Schristos "reachable", /* 65 */ 942c74ad251Schristos "Reserved", /* 66 */ 943c74ad251Schristos "Request refused due to permissions received via SSPN " 944c74ad251Schristos "interface", /* 67 */ 945c74ad251Schristos "Request refused because the AP or PCP does not " 946c74ad251Schristos "support unauthenticated access", /* 68 */ 947c74ad251Schristos "Reserved", /* 69 */ 948c74ad251Schristos "Reserved", /* 70 */ 949c74ad251Schristos "Reserved", /* 71 */ 950c74ad251Schristos "Invalid contents of RSNE", /* 72 */ 951c74ad251Schristos "U-APSD coexistence is not supported", /* 73 */ 952c74ad251Schristos "Requested U-APSD coexistence mode is not supported", /* 74 */ 953c74ad251Schristos "Requested Interval/Duration value cannot be " 954c74ad251Schristos "supported with U-APSD coexistence", /* 75 */ 955c74ad251Schristos "Authentication is rejected because an Anti-Clogging " 956c74ad251Schristos "Token is required", /* 76 */ 957c74ad251Schristos "Authentication is rejected because the offered " 958c74ad251Schristos "finite cyclic group is not supported", /* 77 */ 959c74ad251Schristos "The TBTT adjustment request has not been successful " 960c74ad251Schristos "because the STA could not find an alternative TBTT", /* 78 */ 961c74ad251Schristos "Transmission failure", /* 79 */ 962c74ad251Schristos "Requested TCLAS Not Supported", /* 80 */ 963c74ad251Schristos "TCLAS Resources Exhausted", /* 81 */ 964c74ad251Schristos "Rejected with Suggested BSS transition", /* 82 */ 965c74ad251Schristos "Reject with recommended schedule", /* 83 */ 966c74ad251Schristos "Reject because no wakeup schedule specified", /* 84 */ 967c74ad251Schristos "Success, the destination STA is in power save mode", /* 85 */ 968c74ad251Schristos "FST pending, in process of admitting FST session", /* 86 */ 969c74ad251Schristos "Performing FST now", /* 87 */ 970c74ad251Schristos "FST pending, gap(s) in block ack window", /* 88 */ 971c74ad251Schristos "Reject because of U-PID setting", /* 89 */ 972c74ad251Schristos "Reserved", /* 90 */ 973c74ad251Schristos "Reserved", /* 91 */ 974c74ad251Schristos "(Re)Association refused for some external reason", /* 92 */ 975c74ad251Schristos "(Re)Association refused because of memory limits " 976c74ad251Schristos "at the AP", /* 93 */ 977c74ad251Schristos "(Re)Association refused because emergency services " 978c74ad251Schristos "are not supported at the AP", /* 94 */ 979c74ad251Schristos "GAS query response not yet received", /* 95 */ 980c74ad251Schristos "Reject since the request is for transition to a " 981c74ad251Schristos "frequency band subject to DSE procedures and " 982c74ad251Schristos "FST Initiator is a dependent STA", /* 96 */ 983c74ad251Schristos "Requested TCLAS processing has been terminated by " 984c74ad251Schristos "the AP", /* 97 */ 985c74ad251Schristos "The TS schedule conflicts with an existing " 986c74ad251Schristos "schedule; an alternative schedule is provided", /* 98 */ 987c74ad251Schristos "The association has been denied; however, one or " 988c74ad251Schristos "more Multi-band elements are included that can " 989c74ad251Schristos "be used by the receiving STA to join the BSS", /* 99 */ 990c74ad251Schristos "The request failed due to a reservation conflict", /* 100 */ 991c74ad251Schristos "The request failed due to exceeded MAF limit", /* 101 */ 992c74ad251Schristos "The request failed due to exceeded MCCA track " 993c74ad251Schristos "limit", /* 102 */ 994c74ad251Schristos "Association denied because the information in the" 995c74ad251Schristos "Spectrum Management field is unacceptable", /* 103 */ 996c74ad251Schristos "Association denied because the requesting STA " 997c74ad251Schristos "does not support VHT features", /* 104 */ 998c74ad251Schristos "Enablement denied", /* 105 */ 999c74ad251Schristos "Enablement denied due to restriction from an " 1000c74ad251Schristos "authorized GDB", /* 106 */ 1001c74ad251Schristos "Authorization deenabled", /* 107 */ 10020f74e101Schristos }; 1003c74ad251Schristos #define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0])) 10040f74e101Schristos 10050f74e101Schristos static const char *reason_text[] = { 10060f74e101Schristos "Reserved", /* 0 */ 10070f74e101Schristos "Unspecified reason", /* 1 */ 10080f74e101Schristos "Previous authentication no longer valid", /* 2 */ 1009c74ad251Schristos "Deauthenticated because sending STA is leaving (or has left) " 10100f74e101Schristos "IBSS or ESS", /* 3 */ 10110f74e101Schristos "Disassociated due to inactivity", /* 4 */ 10120f74e101Schristos "Disassociated because AP is unable to handle all currently " 1013c74ad251Schristos " associated STAs", /* 5 */ 1014c74ad251Schristos "Class 2 frame received from nonauthenticated STA", /* 6 */ 1015c74ad251Schristos "Class 3 frame received from nonassociated STA", /* 7 */ 1016c74ad251Schristos "Disassociated because sending STA is leaving " 10170f74e101Schristos "(or has left) BSS", /* 8 */ 1018c74ad251Schristos "STA requesting (re)association is not authenticated with " 1019c74ad251Schristos "responding STA", /* 9 */ 10200f74e101Schristos "Disassociated because the information in the Power Capability " 10210f74e101Schristos "element is unacceptable", /* 10 */ 10220f74e101Schristos "Disassociated because the information in the Supported Channels " 10230f74e101Schristos "element is unacceptable", /* 11 */ 1024c74ad251Schristos "Disassociated due to BSS transition management", /* 12 */ 1025c74ad251Schristos "Invalid element, i.e., an element defined in this standard for " 1026c74ad251Schristos "which the content does not meet the specifications " 1027c74ad251Schristos "in Clause 9", /* 13 */ 1028c74ad251Schristos "Message integrity code (MIC) failure", /* 14 */ 10290f74e101Schristos "4-Way Handshake timeout", /* 15 */ 1030c74ad251Schristos "Group key handshake timeout", /* 16 */ 10310f74e101Schristos "Information element in 4-Way Handshake different from (Re)Association" 1032c74ad251Schristos "Request/Probe Response/Beacon frame", /* 17 */ 1033c74ad251Schristos "Invalid group cipher", /* 18 */ 1034c74ad251Schristos "Invalid pairwise cipher", /* 19 */ 1035c74ad251Schristos "Invalid AKMP", /* 20 */ 1036c74ad251Schristos "Unsupported RSNE version", /* 21 */ 1037c74ad251Schristos "Invalid RSNE capabilities", /* 22 */ 1038c74ad251Schristos "IEEE 802.1X authentication failed", /* 23 */ 1039c74ad251Schristos "Cipher suite rejected because of the security policy", /* 24 */ 1040c74ad251Schristos "TDLS direct-link teardown due to TDLS peer STA " 1041c74ad251Schristos "unreachable via the TDLS direct link", /* 25 */ 1042c74ad251Schristos "TDLS direct-link teardown for unspecified reason", /* 26 */ 1043c74ad251Schristos "Disassociated because session terminated by SSP request",/* 27 */ 1044c74ad251Schristos "Disassociated because of lack of SSP roaming agreement",/* 28 */ 1045c74ad251Schristos "Requested service rejected because of SSP cipher suite or " 1046c74ad251Schristos "AKM requirement", /* 29 */ 1047c74ad251Schristos "Requested service not authorized in this location", /* 30 */ 10480f74e101Schristos "TS deleted because QoS AP lacks sufficient bandwidth for this " 10490f74e101Schristos "QoS STA due to a change in BSS service characteristics or " 10500f74e101Schristos "operational mode (e.g. an HT BSS change from 40 MHz channel " 10510f74e101Schristos "to 20 MHz channel)", /* 31 */ 10520f74e101Schristos "Disassociated for unspecified, QoS-related reason", /* 32 */ 10530f74e101Schristos "Disassociated because QoS AP lacks sufficient bandwidth for this " 10540f74e101Schristos "QoS STA", /* 33 */ 10550f74e101Schristos "Disassociated because of excessive number of frames that need to be " 1056c74ad251Schristos "acknowledged, but are not acknowledged due to AP transmissions " 10570f74e101Schristos "and/or poor channel conditions", /* 34 */ 10580f74e101Schristos "Disassociated because STA is transmitting outside the limits " 10590f74e101Schristos "of its TXOPs", /* 35 */ 10600f74e101Schristos "Requested from peer STA as the STA is leaving the BSS " 10610f74e101Schristos "(or resetting)", /* 36 */ 10620f74e101Schristos "Requested from peer STA as it does not want to use the " 10630f74e101Schristos "mechanism", /* 37 */ 10640f74e101Schristos "Requested from peer STA as the STA received frames using the " 10650f74e101Schristos "mechanism for which a set up is required", /* 38 */ 10660f74e101Schristos "Requested from peer STA due to time out", /* 39 */ 10670f74e101Schristos "Reserved", /* 40 */ 10680f74e101Schristos "Reserved", /* 41 */ 10690f74e101Schristos "Reserved", /* 42 */ 10700f74e101Schristos "Reserved", /* 43 */ 10710f74e101Schristos "Reserved", /* 44 */ 10720f74e101Schristos "Peer STA does not support the requested cipher suite", /* 45 */ 1073c74ad251Schristos "In a DLS Teardown frame: The teardown was initiated by the " 1074c74ad251Schristos "DLS peer. In a Disassociation frame: Disassociated because " 1075c74ad251Schristos "authorized access limit reached", /* 46 */ 1076c74ad251Schristos "In a DLS Teardown frame: The teardown was initiated by the " 1077c74ad251Schristos "AP. In a Disassociation frame: Disassociated due to external " 1078c74ad251Schristos "service requirements", /* 47 */ 1079c74ad251Schristos "Invalid FT Action frame count", /* 48 */ 1080c74ad251Schristos "Invalid pairwise master key identifier (PMKID)", /* 49 */ 1081c74ad251Schristos "Invalid MDE", /* 50 */ 1082c74ad251Schristos "Invalid FTE", /* 51 */ 1083c74ad251Schristos "Mesh peering canceled for unknown reasons", /* 52 */ 1084c74ad251Schristos "The mesh STA has reached the supported maximum number of " 1085c74ad251Schristos "peer mesh STAs", /* 53 */ 1086c74ad251Schristos "The received information violates the Mesh Configuration " 1087c74ad251Schristos "policy configured in the mesh STA profile", /* 54 */ 1088c74ad251Schristos "The mesh STA has received a Mesh Peering Close frame " 1089c74ad251Schristos "requesting to close the mesh peering", /* 55 */ 1090c74ad251Schristos "The mesh STA has resent dot11MeshMaxRetries Mesh " 1091c74ad251Schristos "Peering Open frames, without receiving a Mesh Peering " 1092c74ad251Schristos "Confirm frame", /* 56 */ 1093c74ad251Schristos "The confirmTimer for the mesh peering instance times out", /* 57 */ 1094c74ad251Schristos "The mesh STA fails to unwrap the GTK or the values in the " 1095c74ad251Schristos "wrapped contents do not match", /* 58 */ 1096c74ad251Schristos "The mesh STA receives inconsistent information about the " 1097c74ad251Schristos "mesh parameters between mesh peering Management frames", /* 59 */ 1098c74ad251Schristos "The mesh STA fails the authenticated mesh peering exchange " 1099c74ad251Schristos "because due to failure in selecting either the pairwise " 1100c74ad251Schristos "ciphersuite or group ciphersuite", /* 60 */ 1101c74ad251Schristos "The mesh STA does not have proxy information for this " 1102c74ad251Schristos "external destination", /* 61 */ 1103c74ad251Schristos "The mesh STA does not have forwarding information for this " 1104c74ad251Schristos "destination", /* 62 */ 1105c74ad251Schristos "The mesh STA determines that the link to the next hop of an " 1106c74ad251Schristos "active path in its forwarding information is no longer " 1107c74ad251Schristos "usable", /* 63 */ 1108c74ad251Schristos "The Deauthentication frame was sent because the MAC " 1109c74ad251Schristos "address of the STA already exists in the mesh BSS", /* 64 */ 1110c74ad251Schristos "The mesh STA performs channel switch to meet regulatory " 1111c74ad251Schristos "requirements", /* 65 */ 1112c74ad251Schristos "The mesh STA performs channel switching with unspecified " 1113c74ad251Schristos "reason", /* 66 */ 11140f74e101Schristos }; 1115c74ad251Schristos #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0])) 11160f74e101Schristos 11170f74e101Schristos static int 1118b3a00663Schristos wep_print(netdissect_options *ndo, 1119b3a00663Schristos const u_char *p) 11200f74e101Schristos { 1121b3a00663Schristos uint32_t iv; 11220f74e101Schristos 1123c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN); 1124c74ad251Schristos iv = GET_LE_U_4(p); 11250f74e101Schristos 1126c74ad251Schristos ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), 1127c74ad251Schristos IV_KEYID(iv)); 11280f74e101Schristos 11290f74e101Schristos return 1; 1130c74ad251Schristos trunc: 1131c74ad251Schristos return 0; 11320f74e101Schristos } 11330f74e101Schristos 11340f74e101Schristos static int 1135b3a00663Schristos parse_elements(netdissect_options *ndo, 1136b3a00663Schristos struct mgmt_body_t *pbody, const u_char *p, int offset, 11370f74e101Schristos u_int length) 11380f74e101Schristos { 11390e9868baSchristos u_int elementlen; 11400f74e101Schristos struct ssid_t ssid; 11410f74e101Schristos struct challenge_t challenge; 11420f74e101Schristos struct rates_t rates; 11430f74e101Schristos struct ds_t ds; 11440f74e101Schristos struct cf_t cf; 11450f74e101Schristos struct tim_t tim; 11460f74e101Schristos 11470f74e101Schristos /* 11480f74e101Schristos * We haven't seen any elements yet. 11490f74e101Schristos */ 11500f74e101Schristos pbody->challenge_present = 0; 11510f74e101Schristos pbody->ssid_present = 0; 11520f74e101Schristos pbody->rates_present = 0; 11530f74e101Schristos pbody->ds_present = 0; 11540f74e101Schristos pbody->cf_present = 0; 11550f74e101Schristos pbody->tim_present = 0; 11560f74e101Schristos 11570f74e101Schristos while (length != 0) { 1158b3a00663Schristos /* Make sure we at least have the element ID and length. */ 1159c74ad251Schristos ND_TCHECK_2(p + offset); 11600f74e101Schristos if (length < 2) 1161c74ad251Schristos goto trunc; 1162c74ad251Schristos elementlen = GET_U_1(p + offset + 1); 1163b3a00663Schristos 1164b3a00663Schristos /* Make sure we have the entire element. */ 1165c74ad251Schristos ND_TCHECK_LEN(p + offset + 2, elementlen); 1166b3a00663Schristos if (length < elementlen + 2) 1167c74ad251Schristos goto trunc; 1168b3a00663Schristos 1169c74ad251Schristos switch (GET_U_1(p + offset)) { 1170b3a00663Schristos case E_SSID: 1171*26ba0b50Schristos ssid.length = elementlen; 11720f74e101Schristos offset += 2; 11730f74e101Schristos length -= 2; 11740f74e101Schristos if (ssid.length != 0) { 11750f74e101Schristos if (ssid.length > sizeof(ssid.ssid) - 1) 11760f74e101Schristos return 0; 11770f74e101Schristos memcpy(&ssid.ssid, p + offset, ssid.length); 11780f74e101Schristos offset += ssid.length; 11790f74e101Schristos length -= ssid.length; 11800f74e101Schristos } 11810f74e101Schristos ssid.ssid[ssid.length] = '\0'; 11820f74e101Schristos /* 11830f74e101Schristos * Present and not truncated. 11840f74e101Schristos * 11850f74e101Schristos * If we haven't already seen an SSID IE, 11860f74e101Schristos * copy this one, otherwise ignore this one, 11870f74e101Schristos * so we later report the first one we saw. 11880f74e101Schristos */ 11890f74e101Schristos if (!pbody->ssid_present) { 11900f74e101Schristos pbody->ssid = ssid; 11910f74e101Schristos pbody->ssid_present = 1; 11920f74e101Schristos } 11930f74e101Schristos break; 11940f74e101Schristos case E_CHALLENGE: 1195*26ba0b50Schristos challenge.length = elementlen; 11960f74e101Schristos offset += 2; 11970f74e101Schristos length -= 2; 11980f74e101Schristos if (challenge.length != 0) { 11990f74e101Schristos if (challenge.length > 12000f74e101Schristos sizeof(challenge.text) - 1) 12010f74e101Schristos return 0; 12020f74e101Schristos memcpy(&challenge.text, p + offset, 12030f74e101Schristos challenge.length); 12040f74e101Schristos offset += challenge.length; 12050f74e101Schristos length -= challenge.length; 12060f74e101Schristos } 12070f74e101Schristos challenge.text[challenge.length] = '\0'; 12080f74e101Schristos /* 12090f74e101Schristos * Present and not truncated. 12100f74e101Schristos * 12110f74e101Schristos * If we haven't already seen a challenge IE, 12120f74e101Schristos * copy this one, otherwise ignore this one, 12130f74e101Schristos * so we later report the first one we saw. 12140f74e101Schristos */ 12150f74e101Schristos if (!pbody->challenge_present) { 12160f74e101Schristos pbody->challenge = challenge; 12170f74e101Schristos pbody->challenge_present = 1; 12180f74e101Schristos } 12190f74e101Schristos break; 12200f74e101Schristos case E_RATES: 1221*26ba0b50Schristos rates.length = elementlen; 12220f74e101Schristos offset += 2; 12230f74e101Schristos length -= 2; 12240f74e101Schristos if (rates.length != 0) { 1225c74ad251Schristos if (rates.length > sizeof(rates.rate)) 12260f74e101Schristos return 0; 12270f74e101Schristos memcpy(&rates.rate, p + offset, rates.length); 12280f74e101Schristos offset += rates.length; 12290f74e101Schristos length -= rates.length; 12300f74e101Schristos } 12310f74e101Schristos /* 12320f74e101Schristos * Present and not truncated. 12330f74e101Schristos * 12340f74e101Schristos * If we haven't already seen a rates IE, 12350f74e101Schristos * copy this one if it's not zero-length, 12360f74e101Schristos * otherwise ignore this one, so we later 12370f74e101Schristos * report the first one we saw. 12380f74e101Schristos * 12390f74e101Schristos * We ignore zero-length rates IEs as some 12400f74e101Schristos * devices seem to put a zero-length rates 12410f74e101Schristos * IE, followed by an SSID IE, followed by 12420f74e101Schristos * a non-zero-length rates IE into frames, 12430f74e101Schristos * even though IEEE Std 802.11-2007 doesn't 12440f74e101Schristos * seem to indicate that a zero-length rates 12450f74e101Schristos * IE is valid. 12460f74e101Schristos */ 12470f74e101Schristos if (!pbody->rates_present && rates.length != 0) { 12480f74e101Schristos pbody->rates = rates; 12490f74e101Schristos pbody->rates_present = 1; 12500f74e101Schristos } 12510f74e101Schristos break; 12520f74e101Schristos case E_DS: 1253*26ba0b50Schristos ds.length = elementlen; 1254b3a00663Schristos offset += 2; 1255b3a00663Schristos length -= 2; 1256b3a00663Schristos if (ds.length != 1) { 1257b3a00663Schristos offset += ds.length; 1258b3a00663Schristos length -= ds.length; 1259b3a00663Schristos break; 1260b3a00663Schristos } 1261c74ad251Schristos ds.channel = GET_U_1(p + offset); 1262b3a00663Schristos offset += 1; 1263b3a00663Schristos length -= 1; 12640f74e101Schristos /* 12650f74e101Schristos * Present and not truncated. 12660f74e101Schristos * 12670f74e101Schristos * If we haven't already seen a DS IE, 12680f74e101Schristos * copy this one, otherwise ignore this one, 12690f74e101Schristos * so we later report the first one we saw. 12700f74e101Schristos */ 12710f74e101Schristos if (!pbody->ds_present) { 12720f74e101Schristos pbody->ds = ds; 12730f74e101Schristos pbody->ds_present = 1; 12740f74e101Schristos } 12750f74e101Schristos break; 12760f74e101Schristos case E_CF: 1277*26ba0b50Schristos cf.length = elementlen; 1278b3a00663Schristos offset += 2; 1279b3a00663Schristos length -= 2; 1280b3a00663Schristos if (cf.length != 6) { 1281b3a00663Schristos offset += cf.length; 1282b3a00663Schristos length -= cf.length; 1283b3a00663Schristos break; 1284b3a00663Schristos } 1285c74ad251Schristos cf.count = GET_U_1(p + offset); 1286c74ad251Schristos offset += 1; 1287c74ad251Schristos length -= 1; 1288c74ad251Schristos cf.period = GET_U_1(p + offset); 1289c74ad251Schristos offset += 1; 1290c74ad251Schristos length -= 1; 1291c74ad251Schristos cf.max_duration = GET_LE_U_2(p + offset); 1292c74ad251Schristos offset += 2; 1293c74ad251Schristos length -= 2; 1294c74ad251Schristos cf.dur_remaining = GET_LE_U_2(p + offset); 1295c74ad251Schristos offset += 2; 1296c74ad251Schristos length -= 2; 12970f74e101Schristos /* 12980f74e101Schristos * Present and not truncated. 12990f74e101Schristos * 13000f74e101Schristos * If we haven't already seen a CF IE, 13010f74e101Schristos * copy this one, otherwise ignore this one, 13020f74e101Schristos * so we later report the first one we saw. 13030f74e101Schristos */ 13040f74e101Schristos if (!pbody->cf_present) { 13050f74e101Schristos pbody->cf = cf; 13060f74e101Schristos pbody->cf_present = 1; 13070f74e101Schristos } 13080f74e101Schristos break; 13090f74e101Schristos case E_TIM: 1310*26ba0b50Schristos tim.length = elementlen; 13110f74e101Schristos offset += 2; 13120f74e101Schristos length -= 2; 1313c74ad251Schristos if (tim.length <= 3U) { 1314b3a00663Schristos offset += tim.length; 1315b3a00663Schristos length -= tim.length; 1316b3a00663Schristos break; 1317b3a00663Schristos } 1318c74ad251Schristos if (tim.length - 3U > sizeof(tim.bitmap)) 13190f74e101Schristos return 0; 1320c74ad251Schristos tim.count = GET_U_1(p + offset); 1321c74ad251Schristos offset += 1; 1322c74ad251Schristos length -= 1; 1323c74ad251Schristos tim.period = GET_U_1(p + offset); 1324c74ad251Schristos offset += 1; 1325c74ad251Schristos length -= 1; 1326c74ad251Schristos tim.bitmap_control = GET_U_1(p + offset); 1327c74ad251Schristos offset += 1; 1328c74ad251Schristos length -= 1; 132972c96ff3Schristos memcpy(tim.bitmap, p + offset, tim.length - 3); 13300f74e101Schristos offset += tim.length - 3; 13310f74e101Schristos length -= tim.length - 3; 13320f74e101Schristos /* 13330f74e101Schristos * Present and not truncated. 13340f74e101Schristos * 13350f74e101Schristos * If we haven't already seen a TIM IE, 13360f74e101Schristos * copy this one, otherwise ignore this one, 13370f74e101Schristos * so we later report the first one we saw. 13380f74e101Schristos */ 13390f74e101Schristos if (!pbody->tim_present) { 13400f74e101Schristos pbody->tim = tim; 13410f74e101Schristos pbody->tim_present = 1; 13420f74e101Schristos } 13430f74e101Schristos break; 13440f74e101Schristos default: 13450f74e101Schristos #if 0 1346c74ad251Schristos ND_PRINT("(1) unhandled element_id (%u) ", 1347c74ad251Schristos GET_U_1(p + offset)); 13480f74e101Schristos #endif 1349b3a00663Schristos offset += 2 + elementlen; 1350b3a00663Schristos length -= 2 + elementlen; 13510f74e101Schristos break; 13520f74e101Schristos } 13530f74e101Schristos } 13540f74e101Schristos 13550f74e101Schristos /* No problems found. */ 13560f74e101Schristos return 1; 1357c74ad251Schristos trunc: 1358c74ad251Schristos return 0; 13590f74e101Schristos } 13600f74e101Schristos 13610f74e101Schristos /********************************************************************************* 13620f74e101Schristos * Print Handle functions for the management frame types 13630f74e101Schristos *********************************************************************************/ 13640f74e101Schristos 13650f74e101Schristos static int 1366b3a00663Schristos handle_beacon(netdissect_options *ndo, 1367b3a00663Schristos const u_char *p, u_int length) 13680f74e101Schristos { 13690f74e101Schristos struct mgmt_body_t pbody; 13700f74e101Schristos int offset = 0; 13710f74e101Schristos int ret; 13720f74e101Schristos 13730f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 13740f74e101Schristos 1375c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1376c74ad251Schristos IEEE802_11_CAPINFO_LEN); 13770f74e101Schristos if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 13780f74e101Schristos IEEE802_11_CAPINFO_LEN) 1379c74ad251Schristos goto trunc; 13800f74e101Schristos memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); 13810f74e101Schristos offset += IEEE802_11_TSTAMP_LEN; 13820f74e101Schristos length -= IEEE802_11_TSTAMP_LEN; 1383c74ad251Schristos pbody.beacon_interval = GET_LE_U_2(p + offset); 13840f74e101Schristos offset += IEEE802_11_BCNINT_LEN; 13850f74e101Schristos length -= IEEE802_11_BCNINT_LEN; 1386c74ad251Schristos pbody.capability_info = GET_LE_U_2(p + offset); 13870f74e101Schristos offset += IEEE802_11_CAPINFO_LEN; 13880f74e101Schristos length -= IEEE802_11_CAPINFO_LEN; 13890f74e101Schristos 1390b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 13910f74e101Schristos 13920f74e101Schristos PRINT_SSID(pbody); 13930f74e101Schristos PRINT_RATES(pbody); 1394c74ad251Schristos ND_PRINT(" %s", 1395c74ad251Schristos CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS"); 13960f74e101Schristos PRINT_DS_CHANNEL(pbody); 13970f74e101Schristos 13980f74e101Schristos return ret; 1399c74ad251Schristos trunc: 1400c74ad251Schristos return 0; 14010f74e101Schristos } 14020f74e101Schristos 14030f74e101Schristos static int 1404b3a00663Schristos handle_assoc_request(netdissect_options *ndo, 1405b3a00663Schristos const u_char *p, u_int length) 14060f74e101Schristos { 14070f74e101Schristos struct mgmt_body_t pbody; 14080f74e101Schristos int offset = 0; 14090f74e101Schristos int ret; 14100f74e101Schristos 14110f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 14120f74e101Schristos 1413c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN); 14140f74e101Schristos if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN) 1415c74ad251Schristos goto trunc; 1416c74ad251Schristos pbody.capability_info = GET_LE_U_2(p); 14170f74e101Schristos offset += IEEE802_11_CAPINFO_LEN; 14180f74e101Schristos length -= IEEE802_11_CAPINFO_LEN; 1419c74ad251Schristos pbody.listen_interval = GET_LE_U_2(p + offset); 14200f74e101Schristos offset += IEEE802_11_LISTENINT_LEN; 14210f74e101Schristos length -= IEEE802_11_LISTENINT_LEN; 14220f74e101Schristos 1423b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 14240f74e101Schristos 14250f74e101Schristos PRINT_SSID(pbody); 14260f74e101Schristos PRINT_RATES(pbody); 14270f74e101Schristos return ret; 1428c74ad251Schristos trunc: 1429c74ad251Schristos return 0; 14300f74e101Schristos } 14310f74e101Schristos 14320f74e101Schristos static int 1433b3a00663Schristos handle_assoc_response(netdissect_options *ndo, 1434b3a00663Schristos const u_char *p, u_int length) 14350f74e101Schristos { 14360f74e101Schristos struct mgmt_body_t pbody; 14370f74e101Schristos int offset = 0; 14380f74e101Schristos int ret; 14390f74e101Schristos 14400f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 14410f74e101Schristos 1442c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + 1443c74ad251Schristos IEEE802_11_AID_LEN); 14440f74e101Schristos if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + 14450f74e101Schristos IEEE802_11_AID_LEN) 1446c74ad251Schristos goto trunc; 1447c74ad251Schristos pbody.capability_info = GET_LE_U_2(p); 14480f74e101Schristos offset += IEEE802_11_CAPINFO_LEN; 14490f74e101Schristos length -= IEEE802_11_CAPINFO_LEN; 1450c74ad251Schristos pbody.status_code = GET_LE_U_2(p + offset); 14510f74e101Schristos offset += IEEE802_11_STATUS_LEN; 14520f74e101Schristos length -= IEEE802_11_STATUS_LEN; 1453c74ad251Schristos pbody.aid = GET_LE_U_2(p + offset); 14540f74e101Schristos offset += IEEE802_11_AID_LEN; 14550f74e101Schristos length -= IEEE802_11_AID_LEN; 14560f74e101Schristos 1457b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 14580f74e101Schristos 1459c74ad251Schristos ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 , 14600f74e101Schristos CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "", 14610f74e101Schristos (pbody.status_code < NUM_STATUSES 14620f74e101Schristos ? status_text[pbody.status_code] 1463c74ad251Schristos : "n/a")); 14640f74e101Schristos 14650f74e101Schristos return ret; 1466c74ad251Schristos trunc: 1467c74ad251Schristos return 0; 14680f74e101Schristos } 14690f74e101Schristos 14700f74e101Schristos static int 1471b3a00663Schristos handle_reassoc_request(netdissect_options *ndo, 1472b3a00663Schristos const u_char *p, u_int length) 14730f74e101Schristos { 14740f74e101Schristos struct mgmt_body_t pbody; 14750f74e101Schristos int offset = 0; 14760f74e101Schristos int ret; 14770f74e101Schristos 14780f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 14790f74e101Schristos 1480c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + 1481c74ad251Schristos IEEE802_11_AP_LEN); 14820f74e101Schristos if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + 14830f74e101Schristos IEEE802_11_AP_LEN) 1484c74ad251Schristos goto trunc; 1485c74ad251Schristos pbody.capability_info = GET_LE_U_2(p); 14860f74e101Schristos offset += IEEE802_11_CAPINFO_LEN; 14870f74e101Schristos length -= IEEE802_11_CAPINFO_LEN; 1488c74ad251Schristos pbody.listen_interval = GET_LE_U_2(p + offset); 14890f74e101Schristos offset += IEEE802_11_LISTENINT_LEN; 14900f74e101Schristos length -= IEEE802_11_LISTENINT_LEN; 14910f74e101Schristos memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN); 14920f74e101Schristos offset += IEEE802_11_AP_LEN; 14930f74e101Schristos length -= IEEE802_11_AP_LEN; 14940f74e101Schristos 1495b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 14960f74e101Schristos 14970f74e101Schristos PRINT_SSID(pbody); 1498c74ad251Schristos ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap )); 14990f74e101Schristos 15000f74e101Schristos return ret; 1501c74ad251Schristos trunc: 1502c74ad251Schristos return 0; 15030f74e101Schristos } 15040f74e101Schristos 15050f74e101Schristos static int 1506b3a00663Schristos handle_reassoc_response(netdissect_options *ndo, 1507b3a00663Schristos const u_char *p, u_int length) 15080f74e101Schristos { 1509c74ad251Schristos /* Same as a Association Response */ 1510b3a00663Schristos return handle_assoc_response(ndo, p, length); 15110f74e101Schristos } 15120f74e101Schristos 15130f74e101Schristos static int 1514b3a00663Schristos handle_probe_request(netdissect_options *ndo, 1515b3a00663Schristos const u_char *p, u_int length) 15160f74e101Schristos { 15170f74e101Schristos struct mgmt_body_t pbody; 15180f74e101Schristos int offset = 0; 15190f74e101Schristos int ret; 15200f74e101Schristos 15210f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 15220f74e101Schristos 1523b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 15240f74e101Schristos 15250f74e101Schristos PRINT_SSID(pbody); 15260f74e101Schristos PRINT_RATES(pbody); 15270f74e101Schristos 15280f74e101Schristos return ret; 15290f74e101Schristos } 15300f74e101Schristos 15310f74e101Schristos static int 1532b3a00663Schristos handle_probe_response(netdissect_options *ndo, 1533b3a00663Schristos const u_char *p, u_int length) 15340f74e101Schristos { 15350f74e101Schristos struct mgmt_body_t pbody; 15360f74e101Schristos int offset = 0; 15370f74e101Schristos int ret; 15380f74e101Schristos 15390f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 15400f74e101Schristos 1541c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1542c74ad251Schristos IEEE802_11_CAPINFO_LEN); 15430f74e101Schristos if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 15440f74e101Schristos IEEE802_11_CAPINFO_LEN) 1545c74ad251Schristos goto trunc; 15460f74e101Schristos memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); 15470f74e101Schristos offset += IEEE802_11_TSTAMP_LEN; 15480f74e101Schristos length -= IEEE802_11_TSTAMP_LEN; 1549c74ad251Schristos pbody.beacon_interval = GET_LE_U_2(p + offset); 15500f74e101Schristos offset += IEEE802_11_BCNINT_LEN; 15510f74e101Schristos length -= IEEE802_11_BCNINT_LEN; 1552c74ad251Schristos pbody.capability_info = GET_LE_U_2(p + offset); 15530f74e101Schristos offset += IEEE802_11_CAPINFO_LEN; 15540f74e101Schristos length -= IEEE802_11_CAPINFO_LEN; 15550f74e101Schristos 1556b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 15570f74e101Schristos 15580f74e101Schristos PRINT_SSID(pbody); 15590f74e101Schristos PRINT_RATES(pbody); 15600f74e101Schristos PRINT_DS_CHANNEL(pbody); 15610f74e101Schristos 15620f74e101Schristos return ret; 1563c74ad251Schristos trunc: 1564c74ad251Schristos return 0; 15650f74e101Schristos } 15660f74e101Schristos 15670f74e101Schristos static int 15680f74e101Schristos handle_atim(void) 15690f74e101Schristos { 15700f74e101Schristos /* the frame body for ATIM is null. */ 15710f74e101Schristos return 1; 15720f74e101Schristos } 15730f74e101Schristos 15740f74e101Schristos static int 1575b3a00663Schristos handle_disassoc(netdissect_options *ndo, 1576b3a00663Schristos const u_char *p, u_int length) 15770f74e101Schristos { 15780f74e101Schristos struct mgmt_body_t pbody; 15790f74e101Schristos 15800f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 15810f74e101Schristos 1582c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN); 15830f74e101Schristos if (length < IEEE802_11_REASON_LEN) 1584c74ad251Schristos goto trunc; 1585c74ad251Schristos pbody.reason_code = GET_LE_U_2(p); 15860f74e101Schristos 1587c74ad251Schristos ND_PRINT(": %s", 15880f74e101Schristos (pbody.reason_code < NUM_REASONS) 15890f74e101Schristos ? reason_text[pbody.reason_code] 1590c74ad251Schristos : "Reserved"); 15910f74e101Schristos 15920f74e101Schristos return 1; 1593c74ad251Schristos trunc: 1594c74ad251Schristos return 0; 15950f74e101Schristos } 15960f74e101Schristos 15970f74e101Schristos static int 1598b3a00663Schristos handle_auth(netdissect_options *ndo, 1599b3a00663Schristos const u_char *p, u_int length) 16000f74e101Schristos { 16010f74e101Schristos struct mgmt_body_t pbody; 16020f74e101Schristos int offset = 0; 16030f74e101Schristos int ret; 16040f74e101Schristos 16050f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 16060f74e101Schristos 1607c74ad251Schristos ND_TCHECK_6(p); 16080f74e101Schristos if (length < 6) 1609c74ad251Schristos goto trunc; 1610c74ad251Schristos pbody.auth_alg = GET_LE_U_2(p); 16110f74e101Schristos offset += 2; 16120f74e101Schristos length -= 2; 1613c74ad251Schristos pbody.auth_trans_seq_num = GET_LE_U_2(p + offset); 16140f74e101Schristos offset += 2; 16150f74e101Schristos length -= 2; 1616c74ad251Schristos pbody.status_code = GET_LE_U_2(p + offset); 16170f74e101Schristos offset += 2; 16180f74e101Schristos length -= 2; 16190f74e101Schristos 1620b3a00663Schristos ret = parse_elements(ndo, &pbody, p, offset, length); 16210f74e101Schristos 16220f74e101Schristos if ((pbody.auth_alg == 1) && 16230f74e101Schristos ((pbody.auth_trans_seq_num == 2) || 16240f74e101Schristos (pbody.auth_trans_seq_num == 3))) { 1625c74ad251Schristos ND_PRINT(" (%s)-%x [Challenge Text] %s", 16260f74e101Schristos (pbody.auth_alg < NUM_AUTH_ALGS) 16270f74e101Schristos ? auth_alg_text[pbody.auth_alg] 16280f74e101Schristos : "Reserved", 16290f74e101Schristos pbody.auth_trans_seq_num, 16300f74e101Schristos ((pbody.auth_trans_seq_num % 2) 16310f74e101Schristos ? ((pbody.status_code < NUM_STATUSES) 16320f74e101Schristos ? status_text[pbody.status_code] 1633c74ad251Schristos : "n/a") : "")); 16340f74e101Schristos return ret; 16350f74e101Schristos } 1636c74ad251Schristos ND_PRINT(" (%s)-%x: %s", 16370f74e101Schristos (pbody.auth_alg < NUM_AUTH_ALGS) 16380f74e101Schristos ? auth_alg_text[pbody.auth_alg] 16390f74e101Schristos : "Reserved", 16400f74e101Schristos pbody.auth_trans_seq_num, 16410f74e101Schristos (pbody.auth_trans_seq_num % 2) 16420f74e101Schristos ? ((pbody.status_code < NUM_STATUSES) 16430f74e101Schristos ? status_text[pbody.status_code] 16440f74e101Schristos : "n/a") 1645c74ad251Schristos : ""); 16460f74e101Schristos 16470f74e101Schristos return ret; 1648c74ad251Schristos trunc: 1649c74ad251Schristos return 0; 16500f74e101Schristos } 16510f74e101Schristos 16520f74e101Schristos static int 1653b3a00663Schristos handle_deauth(netdissect_options *ndo, 1654fdccd7e4Schristos const uint8_t *src, const u_char *p, u_int length) 16550f74e101Schristos { 16560f74e101Schristos struct mgmt_body_t pbody; 16570f74e101Schristos const char *reason = NULL; 16580f74e101Schristos 16590f74e101Schristos memset(&pbody, 0, sizeof(pbody)); 16600f74e101Schristos 1661c74ad251Schristos ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN); 16620f74e101Schristos if (length < IEEE802_11_REASON_LEN) 1663c74ad251Schristos goto trunc; 1664c74ad251Schristos pbody.reason_code = GET_LE_U_2(p); 16650f74e101Schristos 16660f74e101Schristos reason = (pbody.reason_code < NUM_REASONS) 16670f74e101Schristos ? reason_text[pbody.reason_code] 16680f74e101Schristos : "Reserved"; 16690f74e101Schristos 1670b3a00663Schristos if (ndo->ndo_eflag) { 1671c74ad251Schristos ND_PRINT(": %s", reason); 16720f74e101Schristos } else { 1673c74ad251Schristos ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason); 16740f74e101Schristos } 16750f74e101Schristos return 1; 1676c74ad251Schristos trunc: 1677c74ad251Schristos return 0; 16780f74e101Schristos } 16790f74e101Schristos 16800f74e101Schristos #define PRINT_HT_ACTION(v) (\ 1681c74ad251Schristos (v) == 0 ? ND_PRINT("TxChWidth"): \ 1682c74ad251Schristos (v) == 1 ? ND_PRINT("MIMOPwrSave"): \ 1683c74ad251Schristos ND_PRINT("Act#%u", (v))) 16840f74e101Schristos #define PRINT_BA_ACTION(v) (\ 1685c74ad251Schristos (v) == 0 ? ND_PRINT("ADDBA Request"): \ 1686c74ad251Schristos (v) == 1 ? ND_PRINT("ADDBA Response"): \ 1687c74ad251Schristos (v) == 2 ? ND_PRINT("DELBA"): \ 1688c74ad251Schristos ND_PRINT("Act#%u", (v))) 16890f74e101Schristos #define PRINT_MESHLINK_ACTION(v) (\ 1690c74ad251Schristos (v) == 0 ? ND_PRINT("Request"): \ 1691c74ad251Schristos (v) == 1 ? ND_PRINT("Report"): \ 1692c74ad251Schristos ND_PRINT("Act#%u", (v))) 16930f74e101Schristos #define PRINT_MESHPEERING_ACTION(v) (\ 1694c74ad251Schristos (v) == 0 ? ND_PRINT("Open"): \ 1695c74ad251Schristos (v) == 1 ? ND_PRINT("Confirm"): \ 1696c74ad251Schristos (v) == 2 ? ND_PRINT("Close"): \ 1697c74ad251Schristos ND_PRINT("Act#%u", (v))) 16980f74e101Schristos #define PRINT_MESHPATH_ACTION(v) (\ 1699c74ad251Schristos (v) == 0 ? ND_PRINT("Request"): \ 1700c74ad251Schristos (v) == 1 ? ND_PRINT("Report"): \ 1701c74ad251Schristos (v) == 2 ? ND_PRINT("Error"): \ 1702c74ad251Schristos (v) == 3 ? ND_PRINT("RootAnnouncement"): \ 1703c74ad251Schristos ND_PRINT("Act#%u", (v))) 17040f74e101Schristos 1705870189d2Schristos #define PRINT_MESH_ACTION(v) (\ 1706c74ad251Schristos (v) == 0 ? ND_PRINT("MeshLink"): \ 1707c74ad251Schristos (v) == 1 ? ND_PRINT("HWMP"): \ 1708c74ad251Schristos (v) == 2 ? ND_PRINT("Gate Announcement"): \ 1709c74ad251Schristos (v) == 3 ? ND_PRINT("Congestion Control"): \ 1710c74ad251Schristos (v) == 4 ? ND_PRINT("MCCA Setup Request"): \ 1711c74ad251Schristos (v) == 5 ? ND_PRINT("MCCA Setup Reply"): \ 1712c74ad251Schristos (v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \ 1713c74ad251Schristos (v) == 7 ? ND_PRINT("MCCA Advertisement"): \ 1714c74ad251Schristos (v) == 8 ? ND_PRINT("MCCA Teardown"): \ 1715c74ad251Schristos (v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \ 1716c74ad251Schristos (v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \ 1717c74ad251Schristos ND_PRINT("Act#%u", (v))) 1718870189d2Schristos #define PRINT_MULTIHOP_ACTION(v) (\ 1719c74ad251Schristos (v) == 0 ? ND_PRINT("Proxy Update"): \ 1720c74ad251Schristos (v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \ 1721c74ad251Schristos ND_PRINT("Act#%u", (v))) 1722870189d2Schristos #define PRINT_SELFPROT_ACTION(v) (\ 1723c74ad251Schristos (v) == 1 ? ND_PRINT("Peering Open"): \ 1724c74ad251Schristos (v) == 2 ? ND_PRINT("Peering Confirm"): \ 1725c74ad251Schristos (v) == 3 ? ND_PRINT("Peering Close"): \ 1726c74ad251Schristos (v) == 4 ? ND_PRINT("Group Key Inform"): \ 1727c74ad251Schristos (v) == 5 ? ND_PRINT("Group Key Acknowledge"): \ 1728c74ad251Schristos ND_PRINT("Act#%u", (v))) 1729870189d2Schristos 17300f74e101Schristos static int 1731b3a00663Schristos handle_action(netdissect_options *ndo, 1732fdccd7e4Schristos const uint8_t *src, const u_char *p, u_int length) 17330f74e101Schristos { 1734c74ad251Schristos ND_TCHECK_2(p); 17350f74e101Schristos if (length < 2) 1736c74ad251Schristos goto trunc; 1737b3a00663Schristos if (ndo->ndo_eflag) { 1738c74ad251Schristos ND_PRINT(": "); 17390f74e101Schristos } else { 1740c74ad251Schristos ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src)); 17410f74e101Schristos } 1742c74ad251Schristos switch (GET_U_1(p)) { 1743c74ad251Schristos case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break; 1744c74ad251Schristos case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break; 1745c74ad251Schristos case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break; 1746c74ad251Schristos case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break; 1747c74ad251Schristos case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break; 1748c74ad251Schristos case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break; 1749870189d2Schristos case 14: 1750*26ba0b50Schristos ND_PRINT("MultihopAction"); 1751c74ad251Schristos PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break; 1752870189d2Schristos case 15: 1753c74ad251Schristos ND_PRINT("SelfprotectAction "); 1754c74ad251Schristos PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break; 1755c74ad251Schristos case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break; 17560f74e101Schristos default: 1757c74ad251Schristos ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1)); 17580f74e101Schristos break; 17590f74e101Schristos } 17600f74e101Schristos return 1; 1761c74ad251Schristos trunc: 1762c74ad251Schristos return 0; 17630f74e101Schristos } 17640f74e101Schristos 17650f74e101Schristos 17660f74e101Schristos /********************************************************************************* 17670f74e101Schristos * Print Body funcs 17680f74e101Schristos *********************************************************************************/ 17690f74e101Schristos 17700f74e101Schristos 17710f74e101Schristos static int 1772b3a00663Schristos mgmt_body_print(netdissect_options *ndo, 1773fdccd7e4Schristos uint16_t fc, const uint8_t *src, const u_char *p, u_int length) 17740f74e101Schristos { 1775c74ad251Schristos ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc))); 1776fdccd7e4Schristos 1777fdccd7e4Schristos /* There may be a problem w/ AP not having this bit set */ 1778fdccd7e4Schristos if (FC_PROTECTED(fc)) 1779fdccd7e4Schristos return wep_print(ndo, p); 17800f74e101Schristos switch (FC_SUBTYPE(fc)) { 17810f74e101Schristos case ST_ASSOC_REQUEST: 1782b3a00663Schristos return handle_assoc_request(ndo, p, length); 17830f74e101Schristos case ST_ASSOC_RESPONSE: 1784b3a00663Schristos return handle_assoc_response(ndo, p, length); 17850f74e101Schristos case ST_REASSOC_REQUEST: 1786b3a00663Schristos return handle_reassoc_request(ndo, p, length); 17870f74e101Schristos case ST_REASSOC_RESPONSE: 1788b3a00663Schristos return handle_reassoc_response(ndo, p, length); 17890f74e101Schristos case ST_PROBE_REQUEST: 1790b3a00663Schristos return handle_probe_request(ndo, p, length); 17910f74e101Schristos case ST_PROBE_RESPONSE: 1792b3a00663Schristos return handle_probe_response(ndo, p, length); 17930f74e101Schristos case ST_BEACON: 1794b3a00663Schristos return handle_beacon(ndo, p, length); 17950f74e101Schristos case ST_ATIM: 17960f74e101Schristos return handle_atim(); 17970f74e101Schristos case ST_DISASSOC: 1798b3a00663Schristos return handle_disassoc(ndo, p, length); 17990f74e101Schristos case ST_AUTH: 1800b3a00663Schristos return handle_auth(ndo, p, length); 18010f74e101Schristos case ST_DEAUTH: 1802fdccd7e4Schristos return handle_deauth(ndo, src, p, length); 18030f74e101Schristos case ST_ACTION: 1804fdccd7e4Schristos return handle_action(ndo, src, p, length); 18050f74e101Schristos default: 18060f74e101Schristos return 1; 18070f74e101Schristos } 18080f74e101Schristos } 18090f74e101Schristos 18100f74e101Schristos 18110f74e101Schristos /********************************************************************************* 18120f74e101Schristos * Handles printing all the control frame types 18130f74e101Schristos *********************************************************************************/ 18140f74e101Schristos 18150f74e101Schristos static int 1816b3a00663Schristos ctrl_body_print(netdissect_options *ndo, 1817b3a00663Schristos uint16_t fc, const u_char *p) 18180f74e101Schristos { 1819c74ad251Schristos ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc))); 18200f74e101Schristos switch (FC_SUBTYPE(fc)) { 18210f74e101Schristos case CTRL_CONTROL_WRAPPER: 18220f74e101Schristos /* XXX - requires special handling */ 18230f74e101Schristos break; 18240f74e101Schristos case CTRL_BAR: 1825c74ad251Schristos ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN); 1826b3a00663Schristos if (!ndo->ndo_eflag) 1827c74ad251Schristos ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ", 1828c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra), 1829c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta), 1830c74ad251Schristos GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl), 1831c74ad251Schristos GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq)); 18320f74e101Schristos break; 18330f74e101Schristos case CTRL_BA: 1834c74ad251Schristos ND_TCHECK_LEN(p, CTRL_BA_HDRLEN); 1835b3a00663Schristos if (!ndo->ndo_eflag) 1836c74ad251Schristos ND_PRINT(" RA:%s ", 1837c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra)); 18380f74e101Schristos break; 18390f74e101Schristos case CTRL_PS_POLL: 1840c74ad251Schristos ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN); 1841c74ad251Schristos ND_PRINT(" AID(%x)", 1842c74ad251Schristos GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid)); 18430f74e101Schristos break; 18440f74e101Schristos case CTRL_RTS: 1845c74ad251Schristos ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN); 1846b3a00663Schristos if (!ndo->ndo_eflag) 1847c74ad251Schristos ND_PRINT(" TA:%s ", 1848c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta)); 18490f74e101Schristos break; 18500f74e101Schristos case CTRL_CTS: 1851c74ad251Schristos ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN); 1852b3a00663Schristos if (!ndo->ndo_eflag) 1853c74ad251Schristos ND_PRINT(" RA:%s ", 1854c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra)); 18550f74e101Schristos break; 18560f74e101Schristos case CTRL_ACK: 1857c74ad251Schristos ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN); 1858b3a00663Schristos if (!ndo->ndo_eflag) 1859c74ad251Schristos ND_PRINT(" RA:%s ", 1860c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra)); 18610f74e101Schristos break; 18620f74e101Schristos case CTRL_CF_END: 1863c74ad251Schristos ND_TCHECK_LEN(p, CTRL_END_HDRLEN); 1864b3a00663Schristos if (!ndo->ndo_eflag) 1865c74ad251Schristos ND_PRINT(" RA:%s ", 1866c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra)); 18670f74e101Schristos break; 18680f74e101Schristos case CTRL_END_ACK: 1869c74ad251Schristos ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN); 1870b3a00663Schristos if (!ndo->ndo_eflag) 1871c74ad251Schristos ND_PRINT(" RA:%s ", 1872c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra)); 18730f74e101Schristos break; 18740f74e101Schristos } 18750f74e101Schristos return 1; 1876c74ad251Schristos trunc: 1877c74ad251Schristos return 0; 18780f74e101Schristos } 18790f74e101Schristos 18800f74e101Schristos /* 18810f74e101Schristos * Data Frame - Address field contents 18820f74e101Schristos * 18830f74e101Schristos * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4 18840f74e101Schristos * 0 | 0 | DA | SA | BSSID | n/a 18850f74e101Schristos * 0 | 1 | DA | BSSID | SA | n/a 18860f74e101Schristos * 1 | 0 | BSSID | SA | DA | n/a 18870f74e101Schristos * 1 | 1 | RA | TA | DA | SA 18880f74e101Schristos */ 18890f74e101Schristos 1890fdccd7e4Schristos /* 1891fdccd7e4Schristos * Function to get source and destination MAC addresses for a data frame. 1892fdccd7e4Schristos */ 18930f74e101Schristos static void 1894fdccd7e4Schristos get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp, 1895b3a00663Schristos const uint8_t **dstp) 18960f74e101Schristos { 1897fdccd7e4Schristos #define ADDR1 (p + 4) 1898fdccd7e4Schristos #define ADDR2 (p + 10) 1899fdccd7e4Schristos #define ADDR3 (p + 16) 1900fdccd7e4Schristos #define ADDR4 (p + 24) 1901fdccd7e4Schristos 1902fdccd7e4Schristos if (!FC_TO_DS(fc)) { 1903fdccd7e4Schristos if (!FC_FROM_DS(fc)) { 1904fdccd7e4Schristos /* not To DS and not From DS */ 1905fdccd7e4Schristos *srcp = ADDR2; 1906fdccd7e4Schristos *dstp = ADDR1; 1907fdccd7e4Schristos } else { 1908fdccd7e4Schristos /* not To DS and From DS */ 1909fdccd7e4Schristos *srcp = ADDR3; 1910fdccd7e4Schristos *dstp = ADDR1; 1911fdccd7e4Schristos } 1912fdccd7e4Schristos } else { 1913fdccd7e4Schristos if (!FC_FROM_DS(fc)) { 1914c74ad251Schristos /* To DS and not From DS */ 1915fdccd7e4Schristos *srcp = ADDR2; 1916fdccd7e4Schristos *dstp = ADDR3; 1917fdccd7e4Schristos } else { 1918fdccd7e4Schristos /* To DS and From DS */ 1919fdccd7e4Schristos *srcp = ADDR4; 1920fdccd7e4Schristos *dstp = ADDR3; 1921fdccd7e4Schristos } 1922fdccd7e4Schristos } 1923fdccd7e4Schristos 1924fdccd7e4Schristos #undef ADDR1 1925fdccd7e4Schristos #undef ADDR2 1926fdccd7e4Schristos #undef ADDR3 1927fdccd7e4Schristos #undef ADDR4 1928fdccd7e4Schristos } 1929fdccd7e4Schristos 1930fdccd7e4Schristos static void 1931fdccd7e4Schristos get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp) 1932fdccd7e4Schristos { 1933fdccd7e4Schristos const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 1934fdccd7e4Schristos 1935fdccd7e4Schristos if (srcp != NULL) 1936fdccd7e4Schristos *srcp = hp->sa; 1937fdccd7e4Schristos if (dstp != NULL) 1938fdccd7e4Schristos *dstp = hp->da; 1939fdccd7e4Schristos } 1940fdccd7e4Schristos 1941fdccd7e4Schristos /* 1942fdccd7e4Schristos * Print Header funcs 1943fdccd7e4Schristos */ 1944fdccd7e4Schristos 1945fdccd7e4Schristos static void 1946fdccd7e4Schristos data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) 1947fdccd7e4Schristos { 19480f74e101Schristos u_int subtype = FC_SUBTYPE(fc); 19490f74e101Schristos 19500f74e101Schristos if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) || 19510f74e101Schristos DATA_FRAME_IS_QOS(subtype)) { 1952c74ad251Schristos ND_PRINT("CF "); 19530f74e101Schristos if (DATA_FRAME_IS_CF_ACK(subtype)) { 19540f74e101Schristos if (DATA_FRAME_IS_CF_POLL(subtype)) 1955c74ad251Schristos ND_PRINT("Ack/Poll"); 19560f74e101Schristos else 1957c74ad251Schristos ND_PRINT("Ack"); 19580f74e101Schristos } else { 19590f74e101Schristos if (DATA_FRAME_IS_CF_POLL(subtype)) 1960c74ad251Schristos ND_PRINT("Poll"); 19610f74e101Schristos } 19620f74e101Schristos if (DATA_FRAME_IS_QOS(subtype)) 1963c74ad251Schristos ND_PRINT("+QoS"); 1964c74ad251Schristos ND_PRINT(" "); 19650f74e101Schristos } 19660f74e101Schristos 19670f74e101Schristos #define ADDR1 (p + 4) 19680f74e101Schristos #define ADDR2 (p + 10) 19690f74e101Schristos #define ADDR3 (p + 16) 19700f74e101Schristos #define ADDR4 (p + 24) 19710f74e101Schristos 19720f74e101Schristos if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) { 1973c74ad251Schristos ND_PRINT("DA:%s SA:%s BSSID:%s ", 1974c74ad251Schristos GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1975c74ad251Schristos GET_ETHERADDR_STRING(ADDR3)); 19760f74e101Schristos } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) { 1977c74ad251Schristos ND_PRINT("DA:%s BSSID:%s SA:%s ", 1978c74ad251Schristos GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1979c74ad251Schristos GET_ETHERADDR_STRING(ADDR3)); 19800f74e101Schristos } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) { 1981c74ad251Schristos ND_PRINT("BSSID:%s SA:%s DA:%s ", 1982c74ad251Schristos GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1983c74ad251Schristos GET_ETHERADDR_STRING(ADDR3)); 19840f74e101Schristos } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { 1985c74ad251Schristos ND_PRINT("RA:%s TA:%s DA:%s SA:%s ", 1986c74ad251Schristos GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), 1987c74ad251Schristos GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4)); 19880f74e101Schristos } 19890f74e101Schristos 19900f74e101Schristos #undef ADDR1 19910f74e101Schristos #undef ADDR2 19920f74e101Schristos #undef ADDR3 19930f74e101Schristos #undef ADDR4 19940f74e101Schristos } 19950f74e101Schristos 19960f74e101Schristos static void 1997fdccd7e4Schristos mgmt_header_print(netdissect_options *ndo, const u_char *p) 19980f74e101Schristos { 19990f74e101Schristos const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 20000f74e101Schristos 2001c74ad251Schristos ND_PRINT("BSSID:%s DA:%s SA:%s ", 2002c74ad251Schristos GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da), 2003c74ad251Schristos GET_ETHERADDR_STRING((hp)->sa)); 20040f74e101Schristos } 20050f74e101Schristos 20060f74e101Schristos static void 2007fdccd7e4Schristos ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) 20080f74e101Schristos { 20090f74e101Schristos switch (FC_SUBTYPE(fc)) { 20100f74e101Schristos case CTRL_BAR: 2011c74ad251Schristos ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ", 2012c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra), 2013c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta), 2014c74ad251Schristos GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl), 2015c74ad251Schristos GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq)); 20160f74e101Schristos break; 20170f74e101Schristos case CTRL_BA: 2018*26ba0b50Schristos ND_PRINT("RA:%s TA:%s ", 2019*26ba0b50Schristos GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra), 2020*26ba0b50Schristos GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ta)); 20210f74e101Schristos break; 20220f74e101Schristos case CTRL_PS_POLL: 2023c74ad251Schristos ND_PRINT("BSSID:%s TA:%s ", 2024c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid), 2025c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta)); 20260f74e101Schristos break; 20270f74e101Schristos case CTRL_RTS: 2028c74ad251Schristos ND_PRINT("RA:%s TA:%s ", 2029c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra), 2030c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta)); 20310f74e101Schristos break; 20320f74e101Schristos case CTRL_CTS: 2033c74ad251Schristos ND_PRINT("RA:%s ", 2034c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra)); 20350f74e101Schristos break; 20360f74e101Schristos case CTRL_ACK: 2037c74ad251Schristos ND_PRINT("RA:%s ", 2038c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra)); 20390f74e101Schristos break; 20400f74e101Schristos case CTRL_CF_END: 2041c74ad251Schristos ND_PRINT("RA:%s BSSID:%s ", 2042c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra), 2043c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid)); 20440f74e101Schristos break; 20450f74e101Schristos case CTRL_END_ACK: 2046c74ad251Schristos ND_PRINT("RA:%s BSSID:%s ", 2047c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra), 2048c74ad251Schristos GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid)); 20490f74e101Schristos break; 20500f74e101Schristos default: 2051fdccd7e4Schristos /* We shouldn't get here - we should already have quit */ 20520f74e101Schristos break; 20530f74e101Schristos } 20540f74e101Schristos } 20550f74e101Schristos 20560f74e101Schristos static int 2057b3a00663Schristos extract_header_length(netdissect_options *ndo, 2058b3a00663Schristos uint16_t fc) 20590f74e101Schristos { 20600f74e101Schristos int len; 20610f74e101Schristos 20620f74e101Schristos switch (FC_TYPE(fc)) { 20630f74e101Schristos case T_MGMT: 20640f74e101Schristos return MGMT_HDRLEN; 20650f74e101Schristos case T_CTRL: 20660f74e101Schristos switch (FC_SUBTYPE(fc)) { 2067fdccd7e4Schristos case CTRL_CONTROL_WRAPPER: 2068fdccd7e4Schristos return CTRL_CONTROL_WRAPPER_HDRLEN; 20690f74e101Schristos case CTRL_BAR: 20700f74e101Schristos return CTRL_BAR_HDRLEN; 2071fdccd7e4Schristos case CTRL_BA: 2072fdccd7e4Schristos return CTRL_BA_HDRLEN; 20730f74e101Schristos case CTRL_PS_POLL: 20740f74e101Schristos return CTRL_PS_POLL_HDRLEN; 20750f74e101Schristos case CTRL_RTS: 20760f74e101Schristos return CTRL_RTS_HDRLEN; 20770f74e101Schristos case CTRL_CTS: 20780f74e101Schristos return CTRL_CTS_HDRLEN; 20790f74e101Schristos case CTRL_ACK: 20800f74e101Schristos return CTRL_ACK_HDRLEN; 20810f74e101Schristos case CTRL_CF_END: 20820f74e101Schristos return CTRL_END_HDRLEN; 20830f74e101Schristos case CTRL_END_ACK: 20840f74e101Schristos return CTRL_END_ACK_HDRLEN; 20850f74e101Schristos default: 2086c74ad251Schristos ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc)); 20870f74e101Schristos return 0; 20880f74e101Schristos } 20890f74e101Schristos case T_DATA: 20900f74e101Schristos len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24; 20910f74e101Schristos if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) 20920f74e101Schristos len += 2; 20930f74e101Schristos return len; 20940f74e101Schristos default: 2095c74ad251Schristos ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc)); 20960f74e101Schristos return 0; 20970f74e101Schristos } 20980f74e101Schristos } 20990f74e101Schristos 21000f74e101Schristos static int 2101c74ad251Schristos extract_mesh_header_length(netdissect_options *ndo, const u_char *p) 21020f74e101Schristos { 2103c74ad251Schristos return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3)); 21040f74e101Schristos } 21050f74e101Schristos 21060f74e101Schristos /* 2107fdccd7e4Schristos * Print the 802.11 MAC header. 21080f74e101Schristos */ 21090f74e101Schristos static void 2110b3a00663Schristos ieee_802_11_hdr_print(netdissect_options *ndo, 2111b3a00663Schristos uint16_t fc, const u_char *p, u_int hdrlen, 2112fdccd7e4Schristos u_int meshdrlen) 21130f74e101Schristos { 2114b3a00663Schristos if (ndo->ndo_vflag) { 21150f74e101Schristos if (FC_MORE_DATA(fc)) 2116c74ad251Schristos ND_PRINT("More Data "); 21170f74e101Schristos if (FC_MORE_FLAG(fc)) 2118c74ad251Schristos ND_PRINT("More Fragments "); 21190f74e101Schristos if (FC_POWER_MGMT(fc)) 2120c74ad251Schristos ND_PRINT("Pwr Mgmt "); 21210f74e101Schristos if (FC_RETRY(fc)) 2122c74ad251Schristos ND_PRINT("Retry "); 21230f74e101Schristos if (FC_ORDER(fc)) 2124c74ad251Schristos ND_PRINT("Strictly Ordered "); 2125fdccd7e4Schristos if (FC_PROTECTED(fc)) 2126c74ad251Schristos ND_PRINT("Protected "); 21270f74e101Schristos if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL) 2128c74ad251Schristos ND_PRINT("%uus ", 2129c74ad251Schristos GET_LE_U_2(((const struct mgmt_header_t *)p)->duration)); 21300f74e101Schristos } 21310f74e101Schristos if (meshdrlen != 0) { 21320f74e101Schristos const struct meshcntl_t *mc = 2133c74ad251Schristos (const struct meshcntl_t *)(p + hdrlen - meshdrlen); 2134c74ad251Schristos u_int ae = GET_U_1(mc->flags) & 3; 21350f74e101Schristos 2136c74ad251Schristos ND_PRINT("MeshData (AE %u TTL %u seq %u", ae, 2137c74ad251Schristos GET_U_1(mc->ttl), GET_LE_U_4(mc->seq)); 21380f74e101Schristos if (ae > 0) 2139c74ad251Schristos ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4)); 21400f74e101Schristos if (ae > 1) 2141c74ad251Schristos ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5)); 21420f74e101Schristos if (ae > 2) 2143c74ad251Schristos ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6)); 2144c74ad251Schristos ND_PRINT(") "); 21450f74e101Schristos } 21460f74e101Schristos 21470f74e101Schristos switch (FC_TYPE(fc)) { 21480f74e101Schristos case T_MGMT: 2149fdccd7e4Schristos mgmt_header_print(ndo, p); 21500f74e101Schristos break; 21510f74e101Schristos case T_CTRL: 2152fdccd7e4Schristos ctrl_header_print(ndo, fc, p); 21530f74e101Schristos break; 21540f74e101Schristos case T_DATA: 2155fdccd7e4Schristos data_header_print(ndo, fc, p); 21560f74e101Schristos break; 21570f74e101Schristos default: 21580f74e101Schristos break; 21590f74e101Schristos } 21600f74e101Schristos } 21610f74e101Schristos 21620f74e101Schristos static u_int 2163b3a00663Schristos ieee802_11_print(netdissect_options *ndo, 2164b3a00663Schristos const u_char *p, u_int length, u_int orig_caplen, int pad, 21650f74e101Schristos u_int fcslen) 21660f74e101Schristos { 2167b3a00663Schristos uint16_t fc; 21680f74e101Schristos u_int caplen, hdrlen, meshdrlen; 2169dc860a36Sspz struct lladdr_info src, dst; 2170fdccd7e4Schristos int llc_hdrlen; 21710f74e101Schristos 2172c74ad251Schristos ndo->ndo_protocol = "802.11"; 21730f74e101Schristos caplen = orig_caplen; 21740f74e101Schristos /* Remove FCS, if present */ 21750f74e101Schristos if (length < fcslen) { 2176c74ad251Schristos nd_print_trunc(ndo); 21770f74e101Schristos return caplen; 21780f74e101Schristos } 21790f74e101Schristos length -= fcslen; 21800f74e101Schristos if (caplen > length) { 21810f74e101Schristos /* Amount of FCS in actual packet data, if any */ 21820f74e101Schristos fcslen = caplen - length; 21830f74e101Schristos caplen -= fcslen; 2184b3a00663Schristos ndo->ndo_snapend -= fcslen; 21850f74e101Schristos } 21860f74e101Schristos 21870f74e101Schristos if (caplen < IEEE802_11_FC_LEN) { 2188c74ad251Schristos nd_print_trunc(ndo); 21890f74e101Schristos return orig_caplen; 21900f74e101Schristos } 21910f74e101Schristos 2192c74ad251Schristos fc = GET_LE_U_2(p); 2193b3a00663Schristos hdrlen = extract_header_length(ndo, fc); 2194fdccd7e4Schristos if (hdrlen == 0) { 2195fdccd7e4Schristos /* Unknown frame type or control frame subtype; quit. */ 2196fdccd7e4Schristos return (0); 2197fdccd7e4Schristos } 21980f74e101Schristos if (pad) 21990f74e101Schristos hdrlen = roundup2(hdrlen, 4); 2200b3a00663Schristos if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA && 22010e9868baSchristos DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) { 2202c74ad251Schristos if(!ND_TTEST_1(p + hdrlen)) { 2203c74ad251Schristos nd_print_trunc(ndo); 2204817e9a7eSchristos return hdrlen; 2205817e9a7eSchristos } 2206c74ad251Schristos meshdrlen = extract_mesh_header_length(ndo, p + hdrlen); 22070f74e101Schristos hdrlen += meshdrlen; 22080f74e101Schristos } else 22090f74e101Schristos meshdrlen = 0; 22100f74e101Schristos 22110f74e101Schristos if (caplen < hdrlen) { 2212c74ad251Schristos nd_print_trunc(ndo); 22130f74e101Schristos return hdrlen; 22140f74e101Schristos } 22150f74e101Schristos 2216fdccd7e4Schristos if (ndo->ndo_eflag) 2217fdccd7e4Schristos ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen); 22180f74e101Schristos 22190f74e101Schristos /* 22200f74e101Schristos * Go past the 802.11 header. 22210f74e101Schristos */ 22220f74e101Schristos length -= hdrlen; 22230f74e101Schristos caplen -= hdrlen; 22240f74e101Schristos p += hdrlen; 22250f74e101Schristos 2226dc860a36Sspz src.addr_string = etheraddr_string; 2227dc860a36Sspz dst.addr_string = etheraddr_string; 22280f74e101Schristos switch (FC_TYPE(fc)) { 22290f74e101Schristos case T_MGMT: 2230dc860a36Sspz get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr); 2231dc860a36Sspz if (!mgmt_body_print(ndo, fc, src.addr, p, length)) { 2232c74ad251Schristos nd_print_trunc(ndo); 22330f74e101Schristos return hdrlen; 22340f74e101Schristos } 22350f74e101Schristos break; 22360f74e101Schristos case T_CTRL: 2237b3a00663Schristos if (!ctrl_body_print(ndo, fc, p - hdrlen)) { 2238c74ad251Schristos nd_print_trunc(ndo); 22390f74e101Schristos return hdrlen; 22400f74e101Schristos } 22410f74e101Schristos break; 22420f74e101Schristos case T_DATA: 22430f74e101Schristos if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc))) 22440f74e101Schristos return hdrlen; /* no-data frame */ 22450f74e101Schristos /* There may be a problem w/ AP not having this bit set */ 2246fdccd7e4Schristos if (FC_PROTECTED(fc)) { 2247c74ad251Schristos ND_PRINT("Data"); 2248b3a00663Schristos if (!wep_print(ndo, p)) { 2249c74ad251Schristos nd_print_trunc(ndo); 22500f74e101Schristos return hdrlen; 22510f74e101Schristos } 2252fdccd7e4Schristos } else { 2253dc860a36Sspz get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr); 2254dc860a36Sspz llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); 2255fdccd7e4Schristos if (llc_hdrlen < 0) { 22560f74e101Schristos /* 22570f74e101Schristos * Some kinds of LLC packet we cannot 22580f74e101Schristos * handle intelligently 22590f74e101Schristos */ 2260b3a00663Schristos if (!ndo->ndo_suppress_default_print) 2261b3a00663Schristos ND_DEFAULTPRINT(p, caplen); 2262fdccd7e4Schristos llc_hdrlen = -llc_hdrlen; 2263fdccd7e4Schristos } 2264fdccd7e4Schristos hdrlen += llc_hdrlen; 22650f74e101Schristos } 22660f74e101Schristos break; 22670f74e101Schristos default: 2268fdccd7e4Schristos /* We shouldn't get here - we should already have quit */ 22690f74e101Schristos break; 22700f74e101Schristos } 22710f74e101Schristos 22720f74e101Schristos return hdrlen; 22730f74e101Schristos } 22740f74e101Schristos 22750f74e101Schristos /* 22760f74e101Schristos * This is the top level routine of the printer. 'p' points 22770f74e101Schristos * to the 802.11 header of the packet, 'h->ts' is the timestamp, 22780f74e101Schristos * 'h->len' is the length of the packet off the wire, and 'h->caplen' 22790f74e101Schristos * is the number of bytes actually captured. 22800f74e101Schristos */ 2281c74ad251Schristos void 2282b3a00663Schristos ieee802_11_if_print(netdissect_options *ndo, 2283b3a00663Schristos const struct pcap_pkthdr *h, const u_char *p) 22840f74e101Schristos { 2285c74ad251Schristos ndo->ndo_protocol = "802.11"; 2286c74ad251Schristos ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0); 22870f74e101Schristos } 22880f74e101Schristos 2289fdccd7e4Schristos 2290fdccd7e4Schristos /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ 2291fdccd7e4Schristos /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */ 2292fdccd7e4Schristos 2293fdccd7e4Schristos /*- 2294fdccd7e4Schristos * Copyright (c) 2003, 2004 David Young. All rights reserved. 2295fdccd7e4Schristos * 2296fdccd7e4Schristos * Redistribution and use in source and binary forms, with or without 2297fdccd7e4Schristos * modification, are permitted provided that the following conditions 2298fdccd7e4Schristos * are met: 2299fdccd7e4Schristos * 1. Redistributions of source code must retain the above copyright 2300fdccd7e4Schristos * notice, this list of conditions and the following disclaimer. 2301fdccd7e4Schristos * 2. Redistributions in binary form must reproduce the above copyright 2302fdccd7e4Schristos * notice, this list of conditions and the following disclaimer in the 2303fdccd7e4Schristos * documentation and/or other materials provided with the distribution. 2304fdccd7e4Schristos * 3. The name of David Young may not be used to endorse or promote 2305fdccd7e4Schristos * products derived from this software without specific prior 2306fdccd7e4Schristos * written permission. 2307fdccd7e4Schristos * 2308fdccd7e4Schristos * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY 2309fdccd7e4Schristos * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2310fdccd7e4Schristos * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 2311fdccd7e4Schristos * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID 2312fdccd7e4Schristos * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2313fdccd7e4Schristos * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2314fdccd7e4Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2315fdccd7e4Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2316fdccd7e4Schristos * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2317fdccd7e4Schristos * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2318fdccd7e4Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 2319fdccd7e4Schristos * OF SUCH DAMAGE. 2320fdccd7e4Schristos */ 2321fdccd7e4Schristos 2322fdccd7e4Schristos /* A generic radio capture format is desirable. It must be 2323fdccd7e4Schristos * rigidly defined (e.g., units for fields should be given), 2324fdccd7e4Schristos * and easily extensible. 2325fdccd7e4Schristos * 2326fdccd7e4Schristos * The following is an extensible radio capture format. It is 2327fdccd7e4Schristos * based on a bitmap indicating which fields are present. 2328fdccd7e4Schristos * 2329fdccd7e4Schristos * I am trying to describe precisely what the application programmer 2330fdccd7e4Schristos * should expect in the following, and for that reason I tell the 2331fdccd7e4Schristos * units and origin of each measurement (where it applies), or else I 2332fdccd7e4Schristos * use sufficiently weaselly language ("is a monotonically nondecreasing 2333fdccd7e4Schristos * function of...") that I cannot set false expectations for lawyerly 2334fdccd7e4Schristos * readers. 2335fdccd7e4Schristos */ 2336fdccd7e4Schristos 2337fdccd7e4Schristos /* 2338fdccd7e4Schristos * The radio capture header precedes the 802.11 header. 2339fdccd7e4Schristos * 2340fdccd7e4Schristos * Note well: all radiotap fields are little-endian. 2341fdccd7e4Schristos */ 2342fdccd7e4Schristos struct ieee80211_radiotap_header { 2343c74ad251Schristos nd_uint8_t it_version; /* Version 0. Only increases 2344fdccd7e4Schristos * for drastic changes, 2345fdccd7e4Schristos * introduction of compatible 2346fdccd7e4Schristos * new fields does not count. 2347fdccd7e4Schristos */ 2348c74ad251Schristos nd_uint8_t it_pad; 2349c74ad251Schristos nd_uint16_t it_len; /* length of the whole 2350fdccd7e4Schristos * header in bytes, including 2351fdccd7e4Schristos * it_version, it_pad, 2352fdccd7e4Schristos * it_len, and data fields. 2353fdccd7e4Schristos */ 2354c74ad251Schristos nd_uint32_t it_present; /* A bitmap telling which 2355fdccd7e4Schristos * fields are present. Set bit 31 2356fdccd7e4Schristos * (0x80000000) to extend the 2357fdccd7e4Schristos * bitmap by another 32 bits. 2358fdccd7e4Schristos * Additional extensions are made 2359fdccd7e4Schristos * by setting bit 31. 2360fdccd7e4Schristos */ 2361fdccd7e4Schristos }; 2362fdccd7e4Schristos 2363fdccd7e4Schristos /* Name Data type Units 2364fdccd7e4Schristos * ---- --------- ----- 2365fdccd7e4Schristos * 2366fdccd7e4Schristos * IEEE80211_RADIOTAP_TSFT uint64_t microseconds 2367fdccd7e4Schristos * 2368fdccd7e4Schristos * Value in microseconds of the MAC's 64-bit 802.11 Time 2369fdccd7e4Schristos * Synchronization Function timer when the first bit of the 2370fdccd7e4Schristos * MPDU arrived at the MAC. For received frames, only. 2371fdccd7e4Schristos * 2372fdccd7e4Schristos * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap 2373fdccd7e4Schristos * 2374fdccd7e4Schristos * Tx/Rx frequency in MHz, followed by flags (see below). 2375fdccd7e4Schristos * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to 2376fdccd7e4Schristos * represent an HT channel as there is not enough room in 2377fdccd7e4Schristos * the flags word. 2378fdccd7e4Schristos * 2379fdccd7e4Schristos * IEEE80211_RADIOTAP_FHSS uint16_t see below 2380fdccd7e4Schristos * 2381fdccd7e4Schristos * For frequency-hopping radios, the hop set (first byte) 2382fdccd7e4Schristos * and pattern (second byte). 2383fdccd7e4Schristos * 2384fdccd7e4Schristos * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index 2385fdccd7e4Schristos * 2386fdccd7e4Schristos * Tx/Rx data rate. If bit 0x80 is set then it represents an 2387fdccd7e4Schristos * an MCS index and not an IEEE rate. 2388fdccd7e4Schristos * 2389fdccd7e4Schristos * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from 2390fdccd7e4Schristos * one milliwatt (dBm) 2391fdccd7e4Schristos * 2392fdccd7e4Schristos * RF signal power at the antenna, decibel difference from 2393fdccd7e4Schristos * one milliwatt. 2394fdccd7e4Schristos * 2395fdccd7e4Schristos * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from 2396fdccd7e4Schristos * one milliwatt (dBm) 2397fdccd7e4Schristos * 2398fdccd7e4Schristos * RF noise power at the antenna, decibel difference from one 2399fdccd7e4Schristos * milliwatt. 2400fdccd7e4Schristos * 2401fdccd7e4Schristos * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) 2402fdccd7e4Schristos * 2403fdccd7e4Schristos * RF signal power at the antenna, decibel difference from an 2404fdccd7e4Schristos * arbitrary, fixed reference. 2405fdccd7e4Schristos * 2406fdccd7e4Schristos * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) 2407fdccd7e4Schristos * 2408fdccd7e4Schristos * RF noise power at the antenna, decibel difference from an 2409fdccd7e4Schristos * arbitrary, fixed reference point. 2410fdccd7e4Schristos * 2411fdccd7e4Schristos * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless 2412fdccd7e4Schristos * 2413fdccd7e4Schristos * Quality of Barker code lock. Unitless. Monotonically 2414fdccd7e4Schristos * nondecreasing with "better" lock strength. Called "Signal 2415fdccd7e4Schristos * Quality" in datasheets. (Is there a standard way to measure 2416fdccd7e4Schristos * this?) 2417fdccd7e4Schristos * 2418fdccd7e4Schristos * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless 2419fdccd7e4Schristos * 2420fdccd7e4Schristos * Transmit power expressed as unitless distance from max 2421fdccd7e4Schristos * power set at factory calibration. 0 is max power. 2422fdccd7e4Schristos * Monotonically nondecreasing with lower power levels. 2423fdccd7e4Schristos * 2424fdccd7e4Schristos * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) 2425fdccd7e4Schristos * 2426fdccd7e4Schristos * Transmit power expressed as decibel distance from max power 2427fdccd7e4Schristos * set at factory calibration. 0 is max power. Monotonically 2428fdccd7e4Schristos * nondecreasing with lower power levels. 2429fdccd7e4Schristos * 2430fdccd7e4Schristos * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from 2431fdccd7e4Schristos * one milliwatt (dBm) 2432fdccd7e4Schristos * 2433fdccd7e4Schristos * Transmit power expressed as dBm (decibels from a 1 milliwatt 2434fdccd7e4Schristos * reference). This is the absolute power level measured at 2435fdccd7e4Schristos * the antenna port. 2436fdccd7e4Schristos * 2437fdccd7e4Schristos * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap 2438fdccd7e4Schristos * 2439fdccd7e4Schristos * Properties of transmitted and received frames. See flags 2440fdccd7e4Schristos * defined below. 2441fdccd7e4Schristos * 2442fdccd7e4Schristos * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index 2443fdccd7e4Schristos * 2444fdccd7e4Schristos * Unitless indication of the Rx/Tx antenna for this packet. 2445fdccd7e4Schristos * The first antenna is antenna 0. 2446fdccd7e4Schristos * 2447fdccd7e4Schristos * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap 2448fdccd7e4Schristos * 2449fdccd7e4Schristos * Properties of received frames. See flags defined below. 2450fdccd7e4Schristos * 2451fdccd7e4Schristos * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap 2452fdccd7e4Schristos * uint16_t MHz 2453fdccd7e4Schristos * uint8_t channel number 2454fdccd7e4Schristos * uint8_t .5 dBm 2455fdccd7e4Schristos * 2456fdccd7e4Schristos * Extended channel specification: flags (see below) followed by 2457fdccd7e4Schristos * frequency in MHz, the corresponding IEEE channel number, and 2458fdccd7e4Schristos * finally the maximum regulatory transmit power cap in .5 dBm 2459fdccd7e4Schristos * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL 2460fdccd7e4Schristos * and only one of the two should be present. 2461fdccd7e4Schristos * 2462fdccd7e4Schristos * IEEE80211_RADIOTAP_MCS uint8_t known 2463fdccd7e4Schristos * uint8_t flags 2464fdccd7e4Schristos * uint8_t mcs 2465fdccd7e4Schristos * 2466fdccd7e4Schristos * Bitset indicating which fields have known values, followed 2467fdccd7e4Schristos * by bitset of flag values, followed by the MCS rate index as 2468fdccd7e4Schristos * in IEEE 802.11n. 2469fdccd7e4Schristos * 2470fdccd7e4Schristos * 2471fdccd7e4Schristos * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless 2472fdccd7e4Schristos * 2473fdccd7e4Schristos * Contains the AMPDU information for the subframe. 2474fdccd7e4Schristos * 2475fdccd7e4Schristos * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 2476fdccd7e4Schristos * 2477fdccd7e4Schristos * Contains VHT information about this frame. 2478fdccd7e4Schristos * 2479fdccd7e4Schristos * IEEE80211_RADIOTAP_VENDOR_NAMESPACE 2480fdccd7e4Schristos * uint8_t OUI[3] 2481fdccd7e4Schristos * uint8_t subspace 2482fdccd7e4Schristos * uint16_t length 2483fdccd7e4Schristos * 2484fdccd7e4Schristos * The Vendor Namespace Field contains three sub-fields. The first 2485fdccd7e4Schristos * sub-field is 3 bytes long. It contains the vendor's IEEE 802 2486fdccd7e4Schristos * Organizationally Unique Identifier (OUI). The fourth byte is a 2487fdccd7e4Schristos * vendor-specific "namespace selector." 2488fdccd7e4Schristos * 2489fdccd7e4Schristos */ 2490fdccd7e4Schristos enum ieee80211_radiotap_type { 2491fdccd7e4Schristos IEEE80211_RADIOTAP_TSFT = 0, 2492fdccd7e4Schristos IEEE80211_RADIOTAP_FLAGS = 1, 2493fdccd7e4Schristos IEEE80211_RADIOTAP_RATE = 2, 2494fdccd7e4Schristos IEEE80211_RADIOTAP_CHANNEL = 3, 2495fdccd7e4Schristos IEEE80211_RADIOTAP_FHSS = 4, 2496fdccd7e4Schristos IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, 2497fdccd7e4Schristos IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, 2498fdccd7e4Schristos IEEE80211_RADIOTAP_LOCK_QUALITY = 7, 2499fdccd7e4Schristos IEEE80211_RADIOTAP_TX_ATTENUATION = 8, 2500fdccd7e4Schristos IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, 2501fdccd7e4Schristos IEEE80211_RADIOTAP_DBM_TX_POWER = 10, 2502fdccd7e4Schristos IEEE80211_RADIOTAP_ANTENNA = 11, 2503fdccd7e4Schristos IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, 2504fdccd7e4Schristos IEEE80211_RADIOTAP_DB_ANTNOISE = 13, 2505fdccd7e4Schristos IEEE80211_RADIOTAP_RX_FLAGS = 14, 2506fdccd7e4Schristos /* NB: gap for netbsd definitions */ 2507fdccd7e4Schristos IEEE80211_RADIOTAP_XCHANNEL = 18, 2508fdccd7e4Schristos IEEE80211_RADIOTAP_MCS = 19, 2509fdccd7e4Schristos IEEE80211_RADIOTAP_AMPDU_STATUS = 20, 2510fdccd7e4Schristos IEEE80211_RADIOTAP_VHT = 21, 2511fdccd7e4Schristos IEEE80211_RADIOTAP_NAMESPACE = 29, 2512fdccd7e4Schristos IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, 2513fdccd7e4Schristos IEEE80211_RADIOTAP_EXT = 31 2514fdccd7e4Schristos }; 2515fdccd7e4Schristos 2516fdccd7e4Schristos /* channel attributes */ 2517fdccd7e4Schristos #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */ 2518fdccd7e4Schristos #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */ 2519fdccd7e4Schristos #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */ 2520fdccd7e4Schristos #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */ 2521fdccd7e4Schristos #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */ 2522fdccd7e4Schristos #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */ 2523fdccd7e4Schristos #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */ 2524fdccd7e4Schristos #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */ 2525fdccd7e4Schristos #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */ 2526fdccd7e4Schristos #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */ 2527fdccd7e4Schristos #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */ 2528fdccd7e4Schristos #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */ 2529fdccd7e4Schristos #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */ 2530fdccd7e4Schristos #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */ 2531fdccd7e4Schristos #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */ 2532fdccd7e4Schristos 2533fdccd7e4Schristos /* Useful combinations of channel characteristics, borrowed from Ethereal */ 2534fdccd7e4Schristos #define IEEE80211_CHAN_A \ 2535fdccd7e4Schristos (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 2536fdccd7e4Schristos #define IEEE80211_CHAN_B \ 2537fdccd7e4Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 2538fdccd7e4Schristos #define IEEE80211_CHAN_G \ 2539fdccd7e4Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 2540fdccd7e4Schristos #define IEEE80211_CHAN_TA \ 2541fdccd7e4Schristos (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) 2542fdccd7e4Schristos #define IEEE80211_CHAN_TG \ 2543fdccd7e4Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO) 2544fdccd7e4Schristos 2545fdccd7e4Schristos 2546fdccd7e4Schristos /* For IEEE80211_RADIOTAP_FLAGS */ 2547fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received 2548fdccd7e4Schristos * during CFP 2549fdccd7e4Schristos */ 2550fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received 2551fdccd7e4Schristos * with short 2552fdccd7e4Schristos * preamble 2553fdccd7e4Schristos */ 2554fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received 2555fdccd7e4Schristos * with WEP encryption 2556fdccd7e4Schristos */ 2557fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received 2558fdccd7e4Schristos * with fragmentation 2559fdccd7e4Schristos */ 2560fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ 2561fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between 2562fdccd7e4Schristos * 802.11 header and payload 2563fdccd7e4Schristos * (to 32-bit boundary) 2564fdccd7e4Schristos */ 2565fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */ 2566fdccd7e4Schristos 2567fdccd7e4Schristos /* For IEEE80211_RADIOTAP_RX_FLAGS */ 2568fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ 2569fdccd7e4Schristos #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */ 2570fdccd7e4Schristos 2571fdccd7e4Schristos /* For IEEE80211_RADIOTAP_MCS known */ 2572fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01 2573fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */ 2574fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04 2575fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08 2576fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10 2577fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20 2578fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40 2579fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80 2580fdccd7e4Schristos 2581fdccd7e4Schristos /* For IEEE80211_RADIOTAP_MCS flags */ 2582fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03 2583fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0 2584fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1 2585fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2 2586fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3 2587fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */ 2588fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08 2589fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 2590fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 2591fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_STBC_1 1 2592fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_STBC_2 2 2593fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_STBC_3 3 2594fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 2595fdccd7e4Schristos #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80 2596fdccd7e4Schristos 2597fdccd7e4Schristos /* For IEEE80211_RADIOTAP_AMPDU_STATUS */ 2598fdccd7e4Schristos #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 2599fdccd7e4Schristos #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 2600fdccd7e4Schristos #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 2601fdccd7e4Schristos #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 2602fdccd7e4Schristos #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 2603fdccd7e4Schristos #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 2604fdccd7e4Schristos 2605fdccd7e4Schristos /* For IEEE80211_RADIOTAP_VHT known */ 2606fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001 2607fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002 2608fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004 2609fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008 2610fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010 2611fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020 2612fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040 2613fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080 2614fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100 2615fdccd7e4Schristos 2616fdccd7e4Schristos /* For IEEE80211_RADIOTAP_VHT flags */ 2617fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_STBC 0x01 2618fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02 2619fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04 2620fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08 2621fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10 2622fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20 2623fdccd7e4Schristos 2624fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f 2625fdccd7e4Schristos 2626fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f 2627fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0 2628fdccd7e4Schristos #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4 2629fdccd7e4Schristos 2630fdccd7e4Schristos #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01 2631fdccd7e4Schristos 26320f74e101Schristos #define IEEE80211_CHAN_FHSS \ 26330f74e101Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) 26340f74e101Schristos #define IEEE80211_CHAN_A \ 26350f74e101Schristos (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 26360f74e101Schristos #define IEEE80211_CHAN_B \ 26370f74e101Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 26380f74e101Schristos #define IEEE80211_CHAN_PUREG \ 26390f74e101Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) 26400f74e101Schristos #define IEEE80211_CHAN_G \ 26410f74e101Schristos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 26420f74e101Schristos 26430f74e101Schristos #define IS_CHAN_FHSS(flags) \ 26440f74e101Schristos ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) 26450f74e101Schristos #define IS_CHAN_A(flags) \ 26460f74e101Schristos ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) 26470f74e101Schristos #define IS_CHAN_B(flags) \ 26480f74e101Schristos ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) 26490f74e101Schristos #define IS_CHAN_PUREG(flags) \ 26500f74e101Schristos ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) 26510f74e101Schristos #define IS_CHAN_G(flags) \ 26520f74e101Schristos ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) 26530f74e101Schristos #define IS_CHAN_ANYG(flags) \ 26540f74e101Schristos (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags)) 26550f74e101Schristos 26560f74e101Schristos static void 2657b3a00663Schristos print_chaninfo(netdissect_options *ndo, 2658c74ad251Schristos uint16_t freq, uint32_t flags, uint32_t presentflags) 26590f74e101Schristos { 2660c74ad251Schristos ND_PRINT("%u MHz", freq); 2661fdccd7e4Schristos if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) { 2662fdccd7e4Schristos /* 2663fdccd7e4Schristos * We have the MCS field, so this is 11n, regardless 2664fdccd7e4Schristos * of what the channel flags say. 2665fdccd7e4Schristos */ 2666c74ad251Schristos ND_PRINT(" 11n"); 2667fdccd7e4Schristos } else { 26680f74e101Schristos if (IS_CHAN_FHSS(flags)) 2669c74ad251Schristos ND_PRINT(" FHSS"); 26700f74e101Schristos if (IS_CHAN_A(flags)) { 26710f74e101Schristos if (flags & IEEE80211_CHAN_HALF) 2672c74ad251Schristos ND_PRINT(" 11a/10Mhz"); 26730f74e101Schristos else if (flags & IEEE80211_CHAN_QUARTER) 2674c74ad251Schristos ND_PRINT(" 11a/5Mhz"); 26750f74e101Schristos else 2676c74ad251Schristos ND_PRINT(" 11a"); 26770f74e101Schristos } 26780f74e101Schristos if (IS_CHAN_ANYG(flags)) { 26790f74e101Schristos if (flags & IEEE80211_CHAN_HALF) 2680c74ad251Schristos ND_PRINT(" 11g/10Mhz"); 26810f74e101Schristos else if (flags & IEEE80211_CHAN_QUARTER) 2682c74ad251Schristos ND_PRINT(" 11g/5Mhz"); 26830f74e101Schristos else 2684c74ad251Schristos ND_PRINT(" 11g"); 26850f74e101Schristos } else if (IS_CHAN_B(flags)) 2686c74ad251Schristos ND_PRINT(" 11b"); 26870f74e101Schristos if (flags & IEEE80211_CHAN_TURBO) 2688c74ad251Schristos ND_PRINT(" Turbo"); 2689fdccd7e4Schristos } 2690fdccd7e4Schristos /* 2691fdccd7e4Schristos * These apply to 11n. 2692fdccd7e4Schristos */ 26930f74e101Schristos if (flags & IEEE80211_CHAN_HT20) 2694c74ad251Schristos ND_PRINT(" ht/20"); 26950f74e101Schristos else if (flags & IEEE80211_CHAN_HT40D) 2696c74ad251Schristos ND_PRINT(" ht/40-"); 26970f74e101Schristos else if (flags & IEEE80211_CHAN_HT40U) 2698c74ad251Schristos ND_PRINT(" ht/40+"); 2699c74ad251Schristos ND_PRINT(" "); 27000f74e101Schristos } 27010f74e101Schristos 27020f74e101Schristos static int 2703b3a00663Schristos print_radiotap_field(netdissect_options *ndo, 2704fdccd7e4Schristos struct cpack_state *s, uint32_t bit, uint8_t *flagsp, 2705fdccd7e4Schristos uint32_t presentflags) 27060f74e101Schristos { 2707fdccd7e4Schristos u_int i; 27080f74e101Schristos int rc; 27090f74e101Schristos 27100f74e101Schristos switch (bit) { 27110e9868baSchristos 2712fdccd7e4Schristos case IEEE80211_RADIOTAP_TSFT: { 2713fdccd7e4Schristos uint64_t tsft; 27140e9868baSchristos 2715c74ad251Schristos rc = nd_cpack_uint64(ndo, s, &tsft); 2716fdccd7e4Schristos if (rc != 0) 2717fdccd7e4Schristos goto trunc; 2718c74ad251Schristos ND_PRINT("%" PRIu64 "us tsft ", tsft); 27190e9868baSchristos break; 27200e9868baSchristos } 27210e9868baSchristos 2722fdccd7e4Schristos case IEEE80211_RADIOTAP_FLAGS: { 2723fdccd7e4Schristos uint8_t flagsval; 27240e9868baSchristos 2725c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &flagsval); 2726fdccd7e4Schristos if (rc != 0) 2727fdccd7e4Schristos goto trunc; 2728fdccd7e4Schristos *flagsp = flagsval; 2729fdccd7e4Schristos if (flagsval & IEEE80211_RADIOTAP_F_CFP) 2730c74ad251Schristos ND_PRINT("cfp "); 2731fdccd7e4Schristos if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE) 2732c74ad251Schristos ND_PRINT("short preamble "); 2733fdccd7e4Schristos if (flagsval & IEEE80211_RADIOTAP_F_WEP) 2734c74ad251Schristos ND_PRINT("wep "); 2735fdccd7e4Schristos if (flagsval & IEEE80211_RADIOTAP_F_FRAG) 2736c74ad251Schristos ND_PRINT("fragmented "); 2737fdccd7e4Schristos if (flagsval & IEEE80211_RADIOTAP_F_BADFCS) 2738c74ad251Schristos ND_PRINT("bad-fcs "); 27390e9868baSchristos break; 27400e9868baSchristos } 27410f74e101Schristos 2742fdccd7e4Schristos case IEEE80211_RADIOTAP_RATE: { 2743fdccd7e4Schristos uint8_t rate; 27440f74e101Schristos 2745c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &rate); 2746fdccd7e4Schristos if (rc != 0) 2747fdccd7e4Schristos goto trunc; 27480e9868baSchristos /* 27490e9868baSchristos * XXX On FreeBSD rate & 0x80 means we have an MCS. On 27500e9868baSchristos * Linux and AirPcap it does not. (What about 2751c74ad251Schristos * macOS, NetBSD, OpenBSD, and DragonFly BSD?) 27520e9868baSchristos * 27530e9868baSchristos * This is an issue either for proprietary extensions 27540e9868baSchristos * to 11a or 11g, which do exist, or for 11n 27550e9868baSchristos * implementations that stuff a rate value into 27560e9868baSchristos * this field, which also appear to exist. 27570e9868baSchristos * 27580e9868baSchristos * We currently handle that by assuming that 27590e9868baSchristos * if the 0x80 bit is set *and* the remaining 27600e9868baSchristos * bits have a value between 0 and 15 it's 27610e9868baSchristos * an MCS value, otherwise it's a rate. If 27620e9868baSchristos * there are cases where systems that use 27630e9868baSchristos * "0x80 + MCS index" for MCS indices > 15, 27640e9868baSchristos * or stuff a rate value here between 64 and 27650e9868baSchristos * 71.5 Mb/s in here, we'll need a preference 27660e9868baSchristos * setting. Such rates do exist, e.g. 11n 27670e9868baSchristos * MCS 7 at 20 MHz with a long guard interval. 27680e9868baSchristos */ 2769fdccd7e4Schristos if (rate >= 0x80 && rate <= 0x8f) { 27700e9868baSchristos /* 27710e9868baSchristos * XXX - we don't know the channel width 27720e9868baSchristos * or guard interval length, so we can't 27730e9868baSchristos * convert this to a data rate. 27740e9868baSchristos * 27750e9868baSchristos * If you want us to show a data rate, 27760e9868baSchristos * use the MCS field, not the Rate field; 27770e9868baSchristos * the MCS field includes not only the 27780e9868baSchristos * MCS index, it also includes bandwidth 27790e9868baSchristos * and guard interval information. 27800e9868baSchristos * 27810e9868baSchristos * XXX - can we get the channel width 27820e9868baSchristos * from XChannel and the guard interval 27830e9868baSchristos * information from Flags, at least on 27840e9868baSchristos * FreeBSD? 27850e9868baSchristos */ 2786c74ad251Schristos ND_PRINT("MCS %u ", rate & 0x7f); 27870e9868baSchristos } else 2788c74ad251Schristos ND_PRINT("%2.1f Mb/s ", .5 * rate); 27890f74e101Schristos break; 2790fdccd7e4Schristos } 2791fdccd7e4Schristos 2792fdccd7e4Schristos case IEEE80211_RADIOTAP_CHANNEL: { 2793fdccd7e4Schristos uint16_t frequency; 2794fdccd7e4Schristos uint16_t flags; 2795fdccd7e4Schristos 2796c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &frequency); 2797fdccd7e4Schristos if (rc != 0) 2798fdccd7e4Schristos goto trunc; 2799c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &flags); 2800fdccd7e4Schristos if (rc != 0) 2801fdccd7e4Schristos goto trunc; 2802fdccd7e4Schristos /* 2803fdccd7e4Schristos * If CHANNEL and XCHANNEL are both present, skip 2804fdccd7e4Schristos * CHANNEL. 2805fdccd7e4Schristos */ 2806fdccd7e4Schristos if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL)) 28070f74e101Schristos break; 2808fdccd7e4Schristos print_chaninfo(ndo, frequency, flags, presentflags); 28090f74e101Schristos break; 2810fdccd7e4Schristos } 2811fdccd7e4Schristos 2812fdccd7e4Schristos case IEEE80211_RADIOTAP_FHSS: { 2813fdccd7e4Schristos uint8_t hopset; 2814fdccd7e4Schristos uint8_t hoppat; 2815fdccd7e4Schristos 2816c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &hopset); 2817fdccd7e4Schristos if (rc != 0) 2818fdccd7e4Schristos goto trunc; 2819c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &hoppat); 2820fdccd7e4Schristos if (rc != 0) 2821fdccd7e4Schristos goto trunc; 2822c74ad251Schristos ND_PRINT("fhset %u fhpat %u ", hopset, hoppat); 28230f74e101Schristos break; 2824fdccd7e4Schristos } 2825fdccd7e4Schristos 2826fdccd7e4Schristos case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: { 2827fdccd7e4Schristos int8_t dbm_antsignal; 2828fdccd7e4Schristos 2829c74ad251Schristos rc = nd_cpack_int8(ndo, s, &dbm_antsignal); 2830fdccd7e4Schristos if (rc != 0) 2831fdccd7e4Schristos goto trunc; 2832c74ad251Schristos ND_PRINT("%ddBm signal ", dbm_antsignal); 28330f74e101Schristos break; 2834fdccd7e4Schristos } 2835fdccd7e4Schristos 2836fdccd7e4Schristos case IEEE80211_RADIOTAP_DBM_ANTNOISE: { 2837fdccd7e4Schristos int8_t dbm_antnoise; 2838fdccd7e4Schristos 2839c74ad251Schristos rc = nd_cpack_int8(ndo, s, &dbm_antnoise); 2840fdccd7e4Schristos if (rc != 0) 2841fdccd7e4Schristos goto trunc; 2842c74ad251Schristos ND_PRINT("%ddBm noise ", dbm_antnoise); 28430f74e101Schristos break; 2844fdccd7e4Schristos } 2845fdccd7e4Schristos 2846fdccd7e4Schristos case IEEE80211_RADIOTAP_LOCK_QUALITY: { 2847fdccd7e4Schristos uint16_t lock_quality; 2848fdccd7e4Schristos 2849c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &lock_quality); 2850fdccd7e4Schristos if (rc != 0) 2851fdccd7e4Schristos goto trunc; 2852c74ad251Schristos ND_PRINT("%u sq ", lock_quality); 28530f74e101Schristos break; 2854fdccd7e4Schristos } 2855fdccd7e4Schristos 2856fdccd7e4Schristos case IEEE80211_RADIOTAP_TX_ATTENUATION: { 2857c74ad251Schristos int16_t tx_attenuation; 2858fdccd7e4Schristos 2859c74ad251Schristos rc = nd_cpack_int16(ndo, s, &tx_attenuation); 2860fdccd7e4Schristos if (rc != 0) 2861fdccd7e4Schristos goto trunc; 2862c74ad251Schristos ND_PRINT("%d tx power ", -tx_attenuation); 28630f74e101Schristos break; 2864fdccd7e4Schristos } 2865fdccd7e4Schristos 2866fdccd7e4Schristos case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: { 2867c74ad251Schristos int8_t db_tx_attenuation; 2868fdccd7e4Schristos 2869c74ad251Schristos rc = nd_cpack_int8(ndo, s, &db_tx_attenuation); 2870fdccd7e4Schristos if (rc != 0) 2871fdccd7e4Schristos goto trunc; 2872c74ad251Schristos ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation); 28730f74e101Schristos break; 2874fdccd7e4Schristos } 2875fdccd7e4Schristos 2876fdccd7e4Schristos case IEEE80211_RADIOTAP_DBM_TX_POWER: { 2877fdccd7e4Schristos int8_t dbm_tx_power; 2878fdccd7e4Schristos 2879c74ad251Schristos rc = nd_cpack_int8(ndo, s, &dbm_tx_power); 2880fdccd7e4Schristos if (rc != 0) 2881fdccd7e4Schristos goto trunc; 2882c74ad251Schristos ND_PRINT("%ddBm tx power ", dbm_tx_power); 28830f74e101Schristos break; 2884fdccd7e4Schristos } 2885fdccd7e4Schristos 2886fdccd7e4Schristos case IEEE80211_RADIOTAP_ANTENNA: { 2887fdccd7e4Schristos uint8_t antenna; 2888fdccd7e4Schristos 2889c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &antenna); 2890fdccd7e4Schristos if (rc != 0) 2891fdccd7e4Schristos goto trunc; 2892c74ad251Schristos ND_PRINT("antenna %u ", antenna); 28930f74e101Schristos break; 2894fdccd7e4Schristos } 2895fdccd7e4Schristos 2896fdccd7e4Schristos case IEEE80211_RADIOTAP_DB_ANTSIGNAL: { 2897fdccd7e4Schristos uint8_t db_antsignal; 2898fdccd7e4Schristos 2899c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &db_antsignal); 2900fdccd7e4Schristos if (rc != 0) 2901fdccd7e4Schristos goto trunc; 2902c74ad251Schristos ND_PRINT("%udB signal ", db_antsignal); 29030f74e101Schristos break; 2904fdccd7e4Schristos } 2905fdccd7e4Schristos 2906fdccd7e4Schristos case IEEE80211_RADIOTAP_DB_ANTNOISE: { 2907fdccd7e4Schristos uint8_t db_antnoise; 2908fdccd7e4Schristos 2909c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &db_antnoise); 2910fdccd7e4Schristos if (rc != 0) 2911fdccd7e4Schristos goto trunc; 2912c74ad251Schristos ND_PRINT("%udB noise ", db_antnoise); 2913fdccd7e4Schristos break; 2914fdccd7e4Schristos } 2915fdccd7e4Schristos 2916fdccd7e4Schristos case IEEE80211_RADIOTAP_RX_FLAGS: { 2917fdccd7e4Schristos uint16_t rx_flags; 2918fdccd7e4Schristos 2919c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &rx_flags); 2920fdccd7e4Schristos if (rc != 0) 2921fdccd7e4Schristos goto trunc; 29220e9868baSchristos /* Do nothing for now */ 29230e9868baSchristos break; 2924fdccd7e4Schristos } 2925fdccd7e4Schristos 2926fdccd7e4Schristos case IEEE80211_RADIOTAP_XCHANNEL: { 2927fdccd7e4Schristos uint32_t flags; 2928fdccd7e4Schristos uint16_t frequency; 2929fdccd7e4Schristos uint8_t channel; 2930fdccd7e4Schristos uint8_t maxpower; 2931fdccd7e4Schristos 2932c74ad251Schristos rc = nd_cpack_uint32(ndo, s, &flags); 2933fdccd7e4Schristos if (rc != 0) 2934fdccd7e4Schristos goto trunc; 2935c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &frequency); 2936fdccd7e4Schristos if (rc != 0) 2937fdccd7e4Schristos goto trunc; 2938c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &channel); 2939fdccd7e4Schristos if (rc != 0) 2940fdccd7e4Schristos goto trunc; 2941c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &maxpower); 2942fdccd7e4Schristos if (rc != 0) 2943fdccd7e4Schristos goto trunc; 2944fdccd7e4Schristos print_chaninfo(ndo, frequency, flags, presentflags); 29450f74e101Schristos break; 2946fdccd7e4Schristos } 2947fdccd7e4Schristos 29480e9868baSchristos case IEEE80211_RADIOTAP_MCS: { 2949fdccd7e4Schristos uint8_t known; 2950fdccd7e4Schristos uint8_t flags; 2951fdccd7e4Schristos uint8_t mcs_index; 2952fdccd7e4Schristos static const char *ht_bandwidth[4] = { 29530e9868baSchristos "20 MHz", 29540e9868baSchristos "40 MHz", 29550e9868baSchristos "20 MHz (L)", 29560e9868baSchristos "20 MHz (U)" 29570e9868baSchristos }; 29580e9868baSchristos float htrate; 29590e9868baSchristos 2960c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &known); 2961fdccd7e4Schristos if (rc != 0) 2962fdccd7e4Schristos goto trunc; 2963c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &flags); 2964fdccd7e4Schristos if (rc != 0) 2965fdccd7e4Schristos goto trunc; 2966c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &mcs_index); 2967fdccd7e4Schristos if (rc != 0) 2968fdccd7e4Schristos goto trunc; 2969fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) { 29700e9868baSchristos /* 29710e9868baSchristos * We know the MCS index. 29720e9868baSchristos */ 2973fdccd7e4Schristos if (mcs_index <= MAX_MCS_INDEX) { 29740e9868baSchristos /* 29750e9868baSchristos * And it's in-range. 29760e9868baSchristos */ 2977fdccd7e4Schristos if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) { 29780e9868baSchristos /* 29790e9868baSchristos * And we know both the bandwidth and 29800e9868baSchristos * the guard interval, so we can look 29810e9868baSchristos * up the rate. 29820e9868baSchristos */ 29830e9868baSchristos htrate = 2984c74ad251Schristos ieee80211_float_htrates 2985c74ad251Schristos [mcs_index] 2986c74ad251Schristos [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)] 2987fdccd7e4Schristos [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)]; 29880e9868baSchristos } else { 29890e9868baSchristos /* 29900e9868baSchristos * We don't know both the bandwidth 29910e9868baSchristos * and the guard interval, so we can 29920e9868baSchristos * only report the MCS index. 29930e9868baSchristos */ 29940e9868baSchristos htrate = 0.0; 29950e9868baSchristos } 29960e9868baSchristos } else { 29970e9868baSchristos /* 29980e9868baSchristos * The MCS value is out of range. 29990e9868baSchristos */ 30000e9868baSchristos htrate = 0.0; 30010e9868baSchristos } 30020e9868baSchristos if (htrate != 0.0) { 30030e9868baSchristos /* 30040e9868baSchristos * We have the rate. 30050e9868baSchristos * Print it. 30060e9868baSchristos */ 3007c74ad251Schristos ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index); 30080e9868baSchristos } else { 30090e9868baSchristos /* 30100e9868baSchristos * We at least have the MCS index. 30110e9868baSchristos * Print it. 30120e9868baSchristos */ 3013c74ad251Schristos ND_PRINT("MCS %u ", mcs_index); 30140e9868baSchristos } 30150e9868baSchristos } 3016fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) { 3017c74ad251Schristos ND_PRINT("%s ", 3018c74ad251Schristos ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]); 30190e9868baSchristos } 3020fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) { 3021c74ad251Schristos ND_PRINT("%s GI ", 3022fdccd7e4Schristos (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 3023c74ad251Schristos "short" : "long"); 30240e9868baSchristos } 3025fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) { 3026c74ad251Schristos ND_PRINT("%s ", 3027fdccd7e4Schristos (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ? 3028c74ad251Schristos "greenfield" : "mixed"); 30290e9868baSchristos } 3030fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) { 3031c74ad251Schristos ND_PRINT("%s FEC ", 3032fdccd7e4Schristos (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ? 3033c74ad251Schristos "LDPC" : "BCC"); 30340e9868baSchristos } 3035fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) { 3036c74ad251Schristos ND_PRINT("RX-STBC%u ", 3037c74ad251Schristos (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT); 3038870189d2Schristos } 30390e9868baSchristos break; 30400e9868baSchristos } 3041fdccd7e4Schristos 3042fdccd7e4Schristos case IEEE80211_RADIOTAP_AMPDU_STATUS: { 3043fdccd7e4Schristos uint32_t reference_num; 3044fdccd7e4Schristos uint16_t flags; 3045fdccd7e4Schristos uint8_t delim_crc; 3046fdccd7e4Schristos uint8_t reserved; 3047fdccd7e4Schristos 3048c74ad251Schristos rc = nd_cpack_uint32(ndo, s, &reference_num); 3049fdccd7e4Schristos if (rc != 0) 3050fdccd7e4Schristos goto trunc; 3051c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &flags); 3052fdccd7e4Schristos if (rc != 0) 3053fdccd7e4Schristos goto trunc; 3054c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &delim_crc); 3055fdccd7e4Schristos if (rc != 0) 3056fdccd7e4Schristos goto trunc; 3057c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &reserved); 3058fdccd7e4Schristos if (rc != 0) 3059fdccd7e4Schristos goto trunc; 3060fdccd7e4Schristos /* Do nothing for now */ 3061fdccd7e4Schristos break; 30620f74e101Schristos } 3063fdccd7e4Schristos 3064fdccd7e4Schristos case IEEE80211_RADIOTAP_VHT: { 3065fdccd7e4Schristos uint16_t known; 3066fdccd7e4Schristos uint8_t flags; 3067fdccd7e4Schristos uint8_t bandwidth; 3068fdccd7e4Schristos uint8_t mcs_nss[4]; 3069fdccd7e4Schristos uint8_t coding; 3070fdccd7e4Schristos uint8_t group_id; 3071fdccd7e4Schristos uint16_t partial_aid; 3072fdccd7e4Schristos static const char *vht_bandwidth[32] = { 3073fdccd7e4Schristos "20 MHz", 3074fdccd7e4Schristos "40 MHz", 3075fdccd7e4Schristos "20 MHz (L)", 3076fdccd7e4Schristos "20 MHz (U)", 3077fdccd7e4Schristos "80 MHz", 3078fdccd7e4Schristos "80 MHz (L)", 3079fdccd7e4Schristos "80 MHz (U)", 3080fdccd7e4Schristos "80 MHz (LL)", 3081fdccd7e4Schristos "80 MHz (LU)", 3082fdccd7e4Schristos "80 MHz (UL)", 3083fdccd7e4Schristos "80 MHz (UU)", 3084fdccd7e4Schristos "160 MHz", 3085fdccd7e4Schristos "160 MHz (L)", 3086fdccd7e4Schristos "160 MHz (U)", 3087fdccd7e4Schristos "160 MHz (LL)", 3088fdccd7e4Schristos "160 MHz (LU)", 3089fdccd7e4Schristos "160 MHz (UL)", 3090fdccd7e4Schristos "160 MHz (UU)", 3091fdccd7e4Schristos "160 MHz (LLL)", 3092fdccd7e4Schristos "160 MHz (LLU)", 3093fdccd7e4Schristos "160 MHz (LUL)", 3094fdccd7e4Schristos "160 MHz (UUU)", 3095fdccd7e4Schristos "160 MHz (ULL)", 3096fdccd7e4Schristos "160 MHz (ULU)", 3097fdccd7e4Schristos "160 MHz (UUL)", 3098fdccd7e4Schristos "160 MHz (UUU)", 3099fdccd7e4Schristos "unknown (26)", 3100fdccd7e4Schristos "unknown (27)", 3101fdccd7e4Schristos "unknown (28)", 3102fdccd7e4Schristos "unknown (29)", 3103fdccd7e4Schristos "unknown (30)", 3104fdccd7e4Schristos "unknown (31)" 3105fdccd7e4Schristos }; 3106fdccd7e4Schristos 3107c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &known); 3108fdccd7e4Schristos if (rc != 0) 3109fdccd7e4Schristos goto trunc; 3110c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &flags); 3111fdccd7e4Schristos if (rc != 0) 3112fdccd7e4Schristos goto trunc; 3113c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &bandwidth); 3114fdccd7e4Schristos if (rc != 0) 3115fdccd7e4Schristos goto trunc; 3116fdccd7e4Schristos for (i = 0; i < 4; i++) { 3117c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]); 3118fdccd7e4Schristos if (rc != 0) 3119fdccd7e4Schristos goto trunc; 3120fdccd7e4Schristos } 3121c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &coding); 3122fdccd7e4Schristos if (rc != 0) 3123fdccd7e4Schristos goto trunc; 3124c74ad251Schristos rc = nd_cpack_uint8(ndo, s, &group_id); 3125fdccd7e4Schristos if (rc != 0) 3126fdccd7e4Schristos goto trunc; 3127c74ad251Schristos rc = nd_cpack_uint16(ndo, s, &partial_aid); 3128fdccd7e4Schristos if (rc != 0) 3129fdccd7e4Schristos goto trunc; 3130fdccd7e4Schristos for (i = 0; i < 4; i++) { 3131fdccd7e4Schristos u_int nss, mcs; 3132fdccd7e4Schristos nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK; 3133fdccd7e4Schristos mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT; 3134fdccd7e4Schristos 3135fdccd7e4Schristos if (nss == 0) 3136fdccd7e4Schristos continue; 3137fdccd7e4Schristos 3138c74ad251Schristos ND_PRINT("User %u MCS %u ", i, mcs); 3139c74ad251Schristos ND_PRINT("%s FEC ", 3140fdccd7e4Schristos (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ? 3141c74ad251Schristos "LDPC" : "BCC"); 3142fdccd7e4Schristos } 3143fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) { 3144c74ad251Schristos ND_PRINT("%s ", 3145c74ad251Schristos vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]); 3146fdccd7e4Schristos } 3147fdccd7e4Schristos if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) { 3148c74ad251Schristos ND_PRINT("%s GI ", 3149fdccd7e4Schristos (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ? 3150c74ad251Schristos "short" : "long"); 3151fdccd7e4Schristos } 3152fdccd7e4Schristos break; 3153fdccd7e4Schristos } 3154fdccd7e4Schristos 3155fdccd7e4Schristos default: 3156fdccd7e4Schristos /* this bit indicates a field whose 3157fdccd7e4Schristos * size we do not know, so we cannot 3158fdccd7e4Schristos * proceed. Just print the bit number. 3159fdccd7e4Schristos */ 3160c74ad251Schristos ND_PRINT("[bit %u] ", bit); 3161fdccd7e4Schristos return -1; 3162fdccd7e4Schristos } 3163fdccd7e4Schristos 3164fdccd7e4Schristos return 0; 3165fdccd7e4Schristos 3166fdccd7e4Schristos trunc: 3167c74ad251Schristos nd_print_trunc(ndo); 3168fdccd7e4Schristos return rc; 3169fdccd7e4Schristos } 3170fdccd7e4Schristos 3171fdccd7e4Schristos 3172fdccd7e4Schristos static int 3173fdccd7e4Schristos print_in_radiotap_namespace(netdissect_options *ndo, 3174fdccd7e4Schristos struct cpack_state *s, uint8_t *flags, 3175fdccd7e4Schristos uint32_t presentflags, int bit0) 3176fdccd7e4Schristos { 3177fdccd7e4Schristos #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x))) 3178fdccd7e4Schristos #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x))) 3179fdccd7e4Schristos #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x))) 3180fdccd7e4Schristos #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x))) 3181fdccd7e4Schristos #define BITNO_2(x) (((x) & 2) ? 1 : 0) 3182fdccd7e4Schristos uint32_t present, next_present; 3183fdccd7e4Schristos int bitno; 3184fdccd7e4Schristos enum ieee80211_radiotap_type bit; 3185fdccd7e4Schristos int rc; 3186fdccd7e4Schristos 3187fdccd7e4Schristos for (present = presentflags; present; present = next_present) { 3188fdccd7e4Schristos /* 3189fdccd7e4Schristos * Clear the least significant bit that is set. 3190fdccd7e4Schristos */ 3191fdccd7e4Schristos next_present = present & (present - 1); 3192fdccd7e4Schristos 3193fdccd7e4Schristos /* 3194fdccd7e4Schristos * Get the bit number, within this presence word, 3195fdccd7e4Schristos * of the remaining least significant bit that 3196fdccd7e4Schristos * is set. 3197fdccd7e4Schristos */ 3198fdccd7e4Schristos bitno = BITNO_32(present ^ next_present); 3199fdccd7e4Schristos 3200fdccd7e4Schristos /* 3201fdccd7e4Schristos * Stop if this is one of the "same meaning 3202fdccd7e4Schristos * in all presence flags" bits. 3203fdccd7e4Schristos */ 3204fdccd7e4Schristos if (bitno >= IEEE80211_RADIOTAP_NAMESPACE) 3205fdccd7e4Schristos break; 3206fdccd7e4Schristos 3207fdccd7e4Schristos /* 3208fdccd7e4Schristos * Get the radiotap bit number of that bit. 3209fdccd7e4Schristos */ 3210fdccd7e4Schristos bit = (enum ieee80211_radiotap_type)(bit0 + bitno); 3211fdccd7e4Schristos 3212fdccd7e4Schristos rc = print_radiotap_field(ndo, s, bit, flags, presentflags); 3213fdccd7e4Schristos if (rc != 0) 3214fdccd7e4Schristos return rc; 3215fdccd7e4Schristos } 3216fdccd7e4Schristos 32170f74e101Schristos return 0; 32180f74e101Schristos } 32190f74e101Schristos 3220817e9a7eSchristos u_int 3221b3a00663Schristos ieee802_11_radio_print(netdissect_options *ndo, 3222b3a00663Schristos const u_char *p, u_int length, u_int caplen) 32230f74e101Schristos { 32240f74e101Schristos #define BIT(n) (1U << n) 32250f74e101Schristos #define IS_EXTENDED(__p) \ 3226c74ad251Schristos (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0 32270f74e101Schristos 32280f74e101Schristos struct cpack_state cpacker; 3229fdccd7e4Schristos const struct ieee80211_radiotap_header *hdr; 3230fdccd7e4Schristos uint32_t presentflags; 3231c74ad251Schristos const nd_uint32_t *presentp, *last_presentp; 3232fdccd7e4Schristos int vendor_namespace; 3233fdccd7e4Schristos uint8_t vendor_oui[3]; 3234fdccd7e4Schristos uint8_t vendor_subnamespace; 3235fdccd7e4Schristos uint16_t skip_length; 32360f74e101Schristos int bit0; 32370f74e101Schristos u_int len; 3238b3a00663Schristos uint8_t flags; 32390f74e101Schristos int pad; 32400f74e101Schristos u_int fcslen; 32410f74e101Schristos 3242c74ad251Schristos ndo->ndo_protocol = "802.11_radio"; 32430f74e101Schristos if (caplen < sizeof(*hdr)) { 3244c74ad251Schristos nd_print_trunc(ndo); 32450f74e101Schristos return caplen; 32460f74e101Schristos } 32470f74e101Schristos 3248fdccd7e4Schristos hdr = (const struct ieee80211_radiotap_header *)p; 32490f74e101Schristos 3250c74ad251Schristos len = GET_LE_U_2(hdr->it_len); 3251817e9a7eSchristos if (len < sizeof(*hdr)) { 3252817e9a7eSchristos /* 3253817e9a7eSchristos * The length is the length of the entire header, so 3254817e9a7eSchristos * it must be as large as the fixed-length part of 3255817e9a7eSchristos * the header. 3256817e9a7eSchristos */ 3257c74ad251Schristos nd_print_trunc(ndo); 3258817e9a7eSchristos return caplen; 3259817e9a7eSchristos } 32600f74e101Schristos 3261dc860a36Sspz /* 3262dc860a36Sspz * If we don't have the entire radiotap header, just give up. 3263dc860a36Sspz */ 32640f74e101Schristos if (caplen < len) { 3265c74ad251Schristos nd_print_trunc(ndo); 32660f74e101Schristos return caplen; 32670f74e101Schristos } 3268c74ad251Schristos nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */ 3269c74ad251Schristos nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */ 32700f74e101Schristos for (last_presentp = &hdr->it_present; 3271dc860a36Sspz (const u_char*)(last_presentp + 1) <= p + len && 3272dc860a36Sspz IS_EXTENDED(last_presentp); 3273870189d2Schristos last_presentp++) 3274c74ad251Schristos nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */ 32750f74e101Schristos 32760f74e101Schristos /* are there more bitmap extensions than bytes in header? */ 3277dc860a36Sspz if ((const u_char*)(last_presentp + 1) > p + len) { 3278c74ad251Schristos nd_print_trunc(ndo); 32790f74e101Schristos return caplen; 32800f74e101Schristos } 32810f74e101Schristos 3282fdccd7e4Schristos /* 3283fdccd7e4Schristos * Start out at the beginning of the default radiotap namespace. 3284fdccd7e4Schristos */ 3285fdccd7e4Schristos bit0 = 0; 3286fdccd7e4Schristos vendor_namespace = 0; 3287fdccd7e4Schristos memset(vendor_oui, 0, 3); 3288fdccd7e4Schristos vendor_subnamespace = 0; 3289fdccd7e4Schristos skip_length = 0; 32900f74e101Schristos /* Assume no flags */ 32910f74e101Schristos flags = 0; 32920f74e101Schristos /* Assume no Atheros padding between 802.11 header and body */ 32930f74e101Schristos pad = 0; 32940f74e101Schristos /* Assume no FCS at end of frame */ 32950f74e101Schristos fcslen = 0; 3296fdccd7e4Schristos for (presentp = &hdr->it_present; presentp <= last_presentp; 3297fdccd7e4Schristos presentp++) { 3298c74ad251Schristos presentflags = GET_LE_U_4(presentp); 32990e9868baSchristos 3300fdccd7e4Schristos /* 3301fdccd7e4Schristos * If this is a vendor namespace, we don't handle it. 3302fdccd7e4Schristos */ 3303fdccd7e4Schristos if (vendor_namespace) { 3304fdccd7e4Schristos /* 3305fdccd7e4Schristos * Skip past the stuff we don't understand. 3306fdccd7e4Schristos * If we add support for any vendor namespaces, 3307fdccd7e4Schristos * it'd be added here; use vendor_oui and 3308fdccd7e4Schristos * vendor_subnamespace to interpret the fields. 3309fdccd7e4Schristos */ 3310c74ad251Schristos if (nd_cpack_advance(&cpacker, skip_length) != 0) { 3311fdccd7e4Schristos /* 3312fdccd7e4Schristos * Ran out of space in the packet. 3313fdccd7e4Schristos */ 3314fdccd7e4Schristos break; 3315fdccd7e4Schristos } 33160e9868baSchristos 3317fdccd7e4Schristos /* 3318fdccd7e4Schristos * We've skipped it all; nothing more to 3319fdccd7e4Schristos * skip. 3320fdccd7e4Schristos */ 3321fdccd7e4Schristos skip_length = 0; 3322fdccd7e4Schristos } else { 3323fdccd7e4Schristos if (print_in_radiotap_namespace(ndo, &cpacker, 3324fdccd7e4Schristos &flags, presentflags, bit0) != 0) { 3325fdccd7e4Schristos /* 3326fdccd7e4Schristos * Fatal error - can't process anything 3327fdccd7e4Schristos * more in the radiotap header. 3328fdccd7e4Schristos */ 3329fdccd7e4Schristos break; 33300f74e101Schristos } 33310f74e101Schristos } 33320f74e101Schristos 3333fdccd7e4Schristos /* 3334fdccd7e4Schristos * Handle the namespace switch bits; we've already handled 3335fdccd7e4Schristos * the extension bit in all but the last word above. 3336fdccd7e4Schristos */ 3337fdccd7e4Schristos switch (presentflags & 3338fdccd7e4Schristos (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) { 3339fdccd7e4Schristos 3340fdccd7e4Schristos case 0: 3341fdccd7e4Schristos /* 3342fdccd7e4Schristos * We're not changing namespaces. 3343fdccd7e4Schristos * advance to the next 32 bits in the current 3344fdccd7e4Schristos * namespace. 3345fdccd7e4Schristos */ 3346fdccd7e4Schristos bit0 += 32; 3347fdccd7e4Schristos break; 3348fdccd7e4Schristos 3349fdccd7e4Schristos case BIT(IEEE80211_RADIOTAP_NAMESPACE): 3350fdccd7e4Schristos /* 3351fdccd7e4Schristos * We're switching to the radiotap namespace. 3352fdccd7e4Schristos * Reset the presence-bitmap index to 0, and 3353fdccd7e4Schristos * reset the namespace to the default radiotap 3354fdccd7e4Schristos * namespace. 3355fdccd7e4Schristos */ 3356fdccd7e4Schristos bit0 = 0; 3357fdccd7e4Schristos vendor_namespace = 0; 3358fdccd7e4Schristos memset(vendor_oui, 0, 3); 3359fdccd7e4Schristos vendor_subnamespace = 0; 3360fdccd7e4Schristos skip_length = 0; 3361fdccd7e4Schristos break; 3362fdccd7e4Schristos 3363fdccd7e4Schristos case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE): 3364fdccd7e4Schristos /* 3365fdccd7e4Schristos * We're switching to a vendor namespace. 3366fdccd7e4Schristos * Reset the presence-bitmap index to 0, 3367fdccd7e4Schristos * note that we're in a vendor namespace, 3368fdccd7e4Schristos * and fetch the fields of the Vendor Namespace 3369fdccd7e4Schristos * item. 3370fdccd7e4Schristos */ 3371fdccd7e4Schristos bit0 = 0; 3372fdccd7e4Schristos vendor_namespace = 1; 3373c74ad251Schristos if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) { 3374c74ad251Schristos nd_print_trunc(ndo); 3375fdccd7e4Schristos break; 3376fdccd7e4Schristos } 3377c74ad251Schristos if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) { 3378c74ad251Schristos nd_print_trunc(ndo); 3379fdccd7e4Schristos break; 3380fdccd7e4Schristos } 3381c74ad251Schristos if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) { 3382c74ad251Schristos nd_print_trunc(ndo); 3383fdccd7e4Schristos break; 3384fdccd7e4Schristos } 3385c74ad251Schristos if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) { 3386c74ad251Schristos nd_print_trunc(ndo); 3387fdccd7e4Schristos break; 3388fdccd7e4Schristos } 3389c74ad251Schristos if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) { 3390c74ad251Schristos nd_print_trunc(ndo); 3391fdccd7e4Schristos break; 3392fdccd7e4Schristos } 3393c74ad251Schristos if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) { 3394c74ad251Schristos nd_print_trunc(ndo); 3395fdccd7e4Schristos break; 3396fdccd7e4Schristos } 3397fdccd7e4Schristos break; 3398fdccd7e4Schristos 3399fdccd7e4Schristos default: 3400fdccd7e4Schristos /* 3401fdccd7e4Schristos * Illegal combination. The behavior in this 3402fdccd7e4Schristos * case is undefined by the radiotap spec; we 3403fdccd7e4Schristos * just ignore both bits. 3404fdccd7e4Schristos */ 3405fdccd7e4Schristos break; 3406fdccd7e4Schristos } 3407fdccd7e4Schristos } 3408fdccd7e4Schristos 34090f74e101Schristos if (flags & IEEE80211_RADIOTAP_F_DATAPAD) 34100f74e101Schristos pad = 1; /* Atheros padding */ 34110f74e101Schristos if (flags & IEEE80211_RADIOTAP_F_FCS) 34120f74e101Schristos fcslen = 4; /* FCS at end of packet */ 3413b3a00663Schristos return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad, 34140f74e101Schristos fcslen); 34150f74e101Schristos #undef BITNO_32 34160f74e101Schristos #undef BITNO_16 34170f74e101Schristos #undef BITNO_8 34180f74e101Schristos #undef BITNO_4 34190f74e101Schristos #undef BITNO_2 34200f74e101Schristos #undef BIT 34210f74e101Schristos } 34220f74e101Schristos 34230f74e101Schristos static u_int 3424c74ad251Schristos ieee802_11_radio_avs_print(netdissect_options *ndo, 3425b3a00663Schristos const u_char *p, u_int length, u_int caplen) 34260f74e101Schristos { 3427b3a00663Schristos uint32_t caphdr_len; 34280f74e101Schristos 3429c74ad251Schristos ndo->ndo_protocol = "802.11_radio_avs"; 34300f74e101Schristos if (caplen < 8) { 3431c74ad251Schristos nd_print_trunc(ndo); 34320f74e101Schristos return caplen; 34330f74e101Schristos } 34340f74e101Schristos 3435c74ad251Schristos caphdr_len = GET_BE_U_4(p + 4); 34360f74e101Schristos if (caphdr_len < 8) { 34370f74e101Schristos /* 34380f74e101Schristos * Yow! The capture header length is claimed not 34390f74e101Schristos * to be large enough to include even the version 34400f74e101Schristos * cookie or capture header length! 34410f74e101Schristos */ 3442c74ad251Schristos nd_print_trunc(ndo); 34430f74e101Schristos return caplen; 34440f74e101Schristos } 34450f74e101Schristos 34460f74e101Schristos if (caplen < caphdr_len) { 3447c74ad251Schristos nd_print_trunc(ndo); 34480f74e101Schristos return caplen; 34490f74e101Schristos } 34500f74e101Schristos 3451b3a00663Schristos return caphdr_len + ieee802_11_print(ndo, p + caphdr_len, 34520f74e101Schristos length - caphdr_len, caplen - caphdr_len, 0, 0); 34530f74e101Schristos } 34540f74e101Schristos 34550f74e101Schristos #define PRISM_HDR_LEN 144 34560f74e101Schristos 34570f74e101Schristos #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 34580f74e101Schristos #define WLANCAP_MAGIC_COOKIE_V1 0x80211001 34590f74e101Schristos #define WLANCAP_MAGIC_COOKIE_V2 0x80211002 34600f74e101Schristos 34610f74e101Schristos /* 34620f74e101Schristos * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header, 34630f74e101Schristos * containing information such as radio information, which we 34640f74e101Schristos * currently ignore. 34650f74e101Schristos * 34660f74e101Schristos * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or 34670f74e101Schristos * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS 34680f74e101Schristos * (currently, on Linux, there's no ARPHRD_ type for 34690f74e101Schristos * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM 34700f74e101Schristos * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for 34710f74e101Schristos * the AVS header, and the first 4 bytes of the header are used to 34720f74e101Schristos * indicate whether it's a Prism header or an AVS header). 34730f74e101Schristos */ 3474c74ad251Schristos void 3475b3a00663Schristos prism_if_print(netdissect_options *ndo, 3476b3a00663Schristos const struct pcap_pkthdr *h, const u_char *p) 34770f74e101Schristos { 34780f74e101Schristos u_int caplen = h->caplen; 34790f74e101Schristos u_int length = h->len; 3480b3a00663Schristos uint32_t msgcode; 34810f74e101Schristos 3482c74ad251Schristos ndo->ndo_protocol = "prism"; 34830f74e101Schristos if (caplen < 4) { 3484c74ad251Schristos nd_print_trunc(ndo); 3485c74ad251Schristos ndo->ndo_ll_hdr_len += caplen; 3486c74ad251Schristos return; 34870f74e101Schristos } 34880f74e101Schristos 3489c74ad251Schristos msgcode = GET_BE_U_4(p); 34900f74e101Schristos if (msgcode == WLANCAP_MAGIC_COOKIE_V1 || 3491c74ad251Schristos msgcode == WLANCAP_MAGIC_COOKIE_V2) { 3492c74ad251Schristos ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen); 3493c74ad251Schristos return; 3494c74ad251Schristos } 34950f74e101Schristos 34960f74e101Schristos if (caplen < PRISM_HDR_LEN) { 3497c74ad251Schristos nd_print_trunc(ndo); 3498c74ad251Schristos ndo->ndo_ll_hdr_len += caplen; 3499c74ad251Schristos return; 35000f74e101Schristos } 35010f74e101Schristos 3502c74ad251Schristos p += PRISM_HDR_LEN; 3503c74ad251Schristos length -= PRISM_HDR_LEN; 3504c74ad251Schristos caplen -= PRISM_HDR_LEN; 3505c74ad251Schristos ndo->ndo_ll_hdr_len += PRISM_HDR_LEN; 3506c74ad251Schristos ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0); 35070f74e101Schristos } 35080f74e101Schristos 35090f74e101Schristos /* 35100f74e101Schristos * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra 35110f74e101Schristos * header, containing information such as radio information. 35120f74e101Schristos */ 3513c74ad251Schristos void 3514b3a00663Schristos ieee802_11_radio_if_print(netdissect_options *ndo, 3515b3a00663Schristos const struct pcap_pkthdr *h, const u_char *p) 35160f74e101Schristos { 3517c74ad251Schristos ndo->ndo_protocol = "802.11_radio"; 3518c74ad251Schristos ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen); 35190f74e101Schristos } 35200f74e101Schristos 35210f74e101Schristos /* 35220f74e101Schristos * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an 35230f74e101Schristos * extra header, containing information such as radio information, 35240f74e101Schristos * which we currently ignore. 35250f74e101Schristos */ 3526c74ad251Schristos void 3527b3a00663Schristos ieee802_11_radio_avs_if_print(netdissect_options *ndo, 3528b3a00663Schristos const struct pcap_pkthdr *h, const u_char *p) 35290f74e101Schristos { 3530c74ad251Schristos ndo->ndo_protocol = "802.11_radio_avs"; 3531c74ad251Schristos ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen); 35320f74e101Schristos } 3533