1193326Sed/* 2193326Sed * Copyright (c) 2001 3193326Sed * Fortress Technologies, Inc. All rights reserved. 4193326Sed * Charlie Lenahan (clenahan@fortresstech.com) 5193326Sed * 6193326Sed * Redistribution and use in source and binary forms, with or without 7193326Sed * modification, are permitted provided that: (1) source code distributions 8193326Sed * retain the above copyright notice and this paragraph in its entirety, (2) 9193326Sed * distributions including binary code include the above copyright notice and 10193326Sed * this paragraph in its entirety in the documentation or other materials 11193326Sed * provided with the distribution, and (3) all advertising materials mentioning 12193326Sed * features or use of this software display the following acknowledgement: 13193326Sed * ``This product includes software developed by the University of California, 14193326Sed * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 15193326Sed * the University nor the names of its contributors may be used to endorse 16193326Sed * or promote products derived from this software without specific prior 17193326Sed * written permission. 18193326Sed * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 19193326Sed * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 20193326Sed * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21193326Sed */ 22193326Sed 23193326Sed/* \summary: IEEE 802.11 printer */ 24193326Sed 25193326Sed#ifdef HAVE_CONFIG_H 26193326Sed#include "config.h" 27193326Sed#endif 28193326Sed 29193326Sed#include <netdissect-stdinc.h> 30193326Sed 31193326Sed#include <string.h> 32193326Sed 33193326Sed#include "netdissect.h" 34193326Sed#include "addrtoname.h" 35193326Sed 36193326Sed#include "extract.h" 37193326Sed 38193326Sed#include "cpack.h" 39193326Sed 40193326Sed 41193326Sed/* Lengths of 802.11 header components. */ 42193326Sed#define IEEE802_11_FC_LEN 2 43193326Sed#define IEEE802_11_DUR_LEN 2 44193326Sed#define IEEE802_11_DA_LEN 6 45193326Sed#define IEEE802_11_SA_LEN 6 46193326Sed#define IEEE802_11_BSSID_LEN 6 47193326Sed#define IEEE802_11_RA_LEN 6 48193326Sed#define IEEE802_11_TA_LEN 6 49193326Sed#define IEEE802_11_ADDR1_LEN 6 50193326Sed#define IEEE802_11_SEQ_LEN 2 51193326Sed#define IEEE802_11_CTL_LEN 2 52193326Sed#define IEEE802_11_CARRIED_FC_LEN 2 53193326Sed#define IEEE802_11_HT_CONTROL_LEN 4 54193326Sed#define IEEE802_11_IV_LEN 3 55193326Sed#define IEEE802_11_KID_LEN 1 56193326Sed 57193326Sed/* Frame check sequence length. */ 58193326Sed#define IEEE802_11_FCS_LEN 4 59193326Sed 60193326Sed/* Lengths of beacon components. */ 61193326Sed#define IEEE802_11_TSTAMP_LEN 8 62193326Sed#define IEEE802_11_BCNINT_LEN 2 63193326Sed#define IEEE802_11_CAPINFO_LEN 2 64193326Sed#define IEEE802_11_LISTENINT_LEN 2 65193326Sed 66193326Sed#define IEEE802_11_AID_LEN 2 67193326Sed#define IEEE802_11_STATUS_LEN 2 68193326Sed#define IEEE802_11_REASON_LEN 2 69193326Sed 70193326Sed/* Length of previous AP in reassocation frame */ 71193326Sed#define IEEE802_11_AP_LEN 6 72193326Sed 73193326Sed#define T_MGMT 0x0 /* management */ 74193326Sed#define T_CTRL 0x1 /* control */ 75193326Sed#define T_DATA 0x2 /* data */ 76193326Sed#define T_RESV 0x3 /* reserved */ 77193326Sed 78193326Sed#define ST_ASSOC_REQUEST 0x0 79193326Sed#define ST_ASSOC_RESPONSE 0x1 80193326Sed#define ST_REASSOC_REQUEST 0x2 81193326Sed#define ST_REASSOC_RESPONSE 0x3 82193326Sed#define ST_PROBE_REQUEST 0x4 83193326Sed#define ST_PROBE_RESPONSE 0x5 84193326Sed/* RESERVED 0x6 */ 85193326Sed/* RESERVED 0x7 */ 86193326Sed#define ST_BEACON 0x8 87193326Sed#define ST_ATIM 0x9 88193326Sed#define ST_DISASSOC 0xA 89193326Sed#define ST_AUTH 0xB 90193326Sed#define ST_DEAUTH 0xC 91193326Sed#define ST_ACTION 0xD 92193326Sed/* RESERVED 0xE */ 93193326Sed/* RESERVED 0xF */ 94193326Sed 95193326Sedstatic const struct tok st_str[] = { 96193326Sed { ST_ASSOC_REQUEST, "Assoc Request" }, 97193326Sed { ST_ASSOC_RESPONSE, "Assoc Response" }, 98193326Sed { ST_REASSOC_REQUEST, "ReAssoc Request" }, 99193326Sed { ST_REASSOC_RESPONSE, "ReAssoc Response" }, 100193326Sed { ST_PROBE_REQUEST, "Probe Request" }, 101193326Sed { ST_PROBE_RESPONSE, "Probe Response" }, 102193326Sed { ST_BEACON, "Beacon" }, 103193326Sed { ST_ATIM, "ATIM" }, 104193326Sed { ST_DISASSOC, "Disassociation" }, 105193326Sed { ST_AUTH, "Authentication" }, 106193326Sed { ST_DEAUTH, "DeAuthentication" }, 107193326Sed { ST_ACTION, "Action" }, 108193326Sed { 0, NULL } 109193326Sed}; 110193326Sed 111193326Sed#define CTRL_CONTROL_WRAPPER 0x7 112193326Sed#define CTRL_BAR 0x8 113193326Sed#define CTRL_BA 0x9 114193326Sed#define CTRL_PS_POLL 0xA 115193326Sed#define CTRL_RTS 0xB 116193326Sed#define CTRL_CTS 0xC 117193326Sed#define CTRL_ACK 0xD 118193326Sed#define CTRL_CF_END 0xE 119193326Sed#define CTRL_END_ACK 0xF 120193326Sed 121193326Sedstatic const struct tok ctrl_str[] = { 122193326Sed { CTRL_CONTROL_WRAPPER, "Control Wrapper" }, 123193326Sed { CTRL_BAR, "BAR" }, 124193326Sed { CTRL_BA, "BA" }, 125193326Sed { CTRL_PS_POLL, "Power Save-Poll" }, 126193326Sed { CTRL_RTS, "Request-To-Send" }, 127193326Sed { CTRL_CTS, "Clear-To-Send" }, 128193326Sed { CTRL_ACK, "Acknowledgment" }, 129193326Sed { CTRL_CF_END, "CF-End" }, 130193326Sed { CTRL_END_ACK, "CF-End+CF-Ack" }, 131193326Sed { 0, NULL } 132193326Sed}; 133193326Sed 134193326Sed#define DATA_DATA 0x0 135193326Sed#define DATA_DATA_CF_ACK 0x1 136193326Sed#define DATA_DATA_CF_POLL 0x2 137193326Sed#define DATA_DATA_CF_ACK_POLL 0x3 138193326Sed#define DATA_NODATA 0x4 139193326Sed#define DATA_NODATA_CF_ACK 0x5 140193326Sed#define DATA_NODATA_CF_POLL 0x6 141193326Sed#define DATA_NODATA_CF_ACK_POLL 0x7 142193326Sed 143194179Sed#define DATA_QOS_DATA 0x8 144194179Sed#define DATA_QOS_DATA_CF_ACK 0x9 145193326Sed#define DATA_QOS_DATA_CF_POLL 0xA 146193326Sed#define DATA_QOS_DATA_CF_ACK_POLL 0xB 147193326Sed#define DATA_QOS_NODATA 0xC 148193326Sed#define DATA_QOS_CF_POLL_NODATA 0xE 149193326Sed#define DATA_QOS_CF_ACK_POLL_NODATA 0xF 150193326Sed 151193326Sed/* 152193326Sed * The subtype field of a data frame is, in effect, composed of 4 flag 153193326Sed * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have 154193326Sed * any data), and QoS. 155193326Sed */ 156193326Sed#define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01) 157193326Sed#define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02) 158193326Sed#define DATA_FRAME_IS_NULL(x) ((x) & 0x04) 159193326Sed#define DATA_FRAME_IS_QOS(x) ((x) & 0x08) 160193326Sed 161193326Sed/* 162193326Sed * Bits in the frame control field. 163193326Sed */ 164193326Sed#define FC_VERSION(fc) ((fc) & 0x3) 165193326Sed#define FC_TYPE(fc) (((fc) >> 2) & 0x3) 166194179Sed#define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF) 167194179Sed#define FC_TO_DS(fc) ((fc) & 0x0100) 168193326Sed#define FC_FROM_DS(fc) ((fc) & 0x0200) 169193326Sed#define FC_MORE_FLAG(fc) ((fc) & 0x0400) 170193326Sed#define FC_RETRY(fc) ((fc) & 0x0800) 171193326Sed#define FC_POWER_MGMT(fc) ((fc) & 0x1000) 172193326Sed#define FC_MORE_DATA(fc) ((fc) & 0x2000) 173193326Sed#define FC_PROTECTED(fc) ((fc) & 0x4000) 174193326Sed#define FC_ORDER(fc) ((fc) & 0x8000) 175193326Sed 176193326Sedstruct mgmt_header_t { 177193326Sed uint16_t fc; 178193326Sed uint16_t duration; 179193326Sed uint8_t da[IEEE802_11_DA_LEN]; 180193326Sed uint8_t sa[IEEE802_11_SA_LEN]; 181193326Sed uint8_t bssid[IEEE802_11_BSSID_LEN]; 182193326Sed uint16_t seq_ctrl; 183193326Sed}; 184193326Sed 185193326Sed#define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 186193326Sed IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\ 187193326Sed IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN) 188193326Sed 189193326Sed#define CAPABILITY_ESS(cap) ((cap) & 0x0001) 190194179Sed#define CAPABILITY_IBSS(cap) ((cap) & 0x0002) 191194179Sed#define CAPABILITY_CFP(cap) ((cap) & 0x0004) 192194179Sed#define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008) 193194179Sed#define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010) 194194179Sed 195194179Sedstruct ssid_t { 196194179Sed uint8_t element_id; 197194179Sed uint8_t length; 198193326Sed u_char ssid[33]; /* 32 + 1 for null */ 199193326Sed}; 200193326Sed 201193326Sedstruct rates_t { 202193326Sed uint8_t element_id; 203193326Sed uint8_t length; 204193326Sed uint8_t rate[16]; 205193326Sed}; 206193326Sed 207193326Sedstruct challenge_t { 208193326Sed uint8_t element_id; 209193326Sed uint8_t length; 210193326Sed uint8_t text[254]; /* 1-253 + 1 for null */ 211193326Sed}; 212193326Sed 213193326Sedstruct fh_t { 214193326Sed uint8_t element_id; 215193326Sed uint8_t length; 216193326Sed uint16_t dwell_time; 217193326Sed uint8_t hop_set; 218193326Sed uint8_t hop_pattern; 219193326Sed uint8_t hop_index; 220193326Sed}; 221193326Sed 222193326Sedstruct ds_t { 223193326Sed uint8_t element_id; 224193326Sed uint8_t length; 225193326Sed uint8_t channel; 226193326Sed}; 227193326Sed 228193326Sedstruct cf_t { 229193326Sed uint8_t element_id; 230193326Sed uint8_t length; 231193326Sed uint8_t count; 232193326Sed uint8_t period; 233193326Sed uint16_t max_duration; 234193326Sed uint16_t dur_remaing; 235193326Sed}; 236193326Sed 237193326Sedstruct tim_t { 238193326Sed uint8_t element_id; 239193326Sed uint8_t length; 240193326Sed uint8_t count; 241193326Sed uint8_t period; 242193326Sed uint8_t bitmap_control; 243193326Sed uint8_t bitmap[251]; 244193326Sed}; 245193326Sed 246193326Sed#define E_SSID 0 247193326Sed#define E_RATES 1 248193326Sed#define E_FH 2 249193326Sed#define E_DS 3 250193326Sed#define E_CF 4 251193326Sed#define E_TIM 5 252193326Sed#define E_IBSS 6 253193326Sed/* reserved 7 */ 254193326Sed/* reserved 8 */ 255193326Sed/* reserved 9 */ 256193326Sed/* reserved 10 */ 257193326Sed/* reserved 11 */ 258193326Sed/* reserved 12 */ 259193326Sed/* reserved 13 */ 260193326Sed/* reserved 14 */ 261193326Sed/* reserved 15 */ 262193326Sed/* reserved 16 */ 263193326Sed 264193326Sed#define E_CHALLENGE 16 265193326Sed/* reserved 17 */ 266193326Sed/* reserved 18 */ 267193326Sed/* reserved 19 */ 268193326Sed/* reserved 16 */ 269193326Sed/* reserved 16 */ 270193326Sed 271193326Sed 272193326Sedstruct mgmt_body_t { 273193326Sed uint8_t timestamp[IEEE802_11_TSTAMP_LEN]; 274193326Sed uint16_t beacon_interval; 275193326Sed uint16_t listen_interval; 276193326Sed uint16_t status_code; 277193326Sed uint16_t aid; 278193326Sed u_char ap[IEEE802_11_AP_LEN]; 279193326Sed uint16_t reason_code; 280193326Sed uint16_t auth_alg; 281193326Sed uint16_t auth_trans_seq_num; 282193326Sed int challenge_present; 283193326Sed struct challenge_t challenge; 284193326Sed uint16_t capability_info; 285193326Sed int ssid_present; 286193326Sed struct ssid_t ssid; 287193326Sed int rates_present; 288193326Sed struct rates_t rates; 289193326Sed int ds_present; 290193326Sed struct ds_t ds; 291193326Sed int cf_present; 292193326Sed struct cf_t cf; 293193326Sed int fh_present; 294193326Sed struct fh_t fh; 295193326Sed int tim_present; 296193326Sed struct tim_t tim; 297193326Sed}; 298193326Sed 299193326Sedstruct ctrl_control_wrapper_hdr_t { 300193326Sed uint16_t fc; 301193326Sed uint16_t duration; 302193326Sed uint8_t addr1[IEEE802_11_ADDR1_LEN]; 303193326Sed uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN]; 304193326Sed uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN]; 305193326Sed}; 306193326Sed 307193326Sed#define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 308193326Sed IEEE802_11_ADDR1_LEN+\ 309193326Sed IEEE802_11_CARRIED_FC_LEN+\ 310194179Sed IEEE802_11_HT_CONTROL_LEN) 311194179Sed 312194179Sedstruct ctrl_rts_hdr_t { 313193326Sed uint16_t fc; 314193326Sed uint16_t duration; 315193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 316193326Sed uint8_t ta[IEEE802_11_TA_LEN]; 317193326Sed}; 318193326Sed 319193326Sed#define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 320193326Sed IEEE802_11_RA_LEN+IEEE802_11_TA_LEN) 321193326Sed 322193326Sedstruct ctrl_cts_hdr_t { 323193326Sed uint16_t fc; 324193326Sed uint16_t duration; 325193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 326193326Sed}; 327193326Sed 328193326Sed#define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 329193326Sed 330193326Sedstruct ctrl_ack_hdr_t { 331193326Sed uint16_t fc; 332193326Sed uint16_t duration; 333193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 334193326Sed}; 335193326Sed 336193326Sed#define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 337193326Sed 338193326Sedstruct ctrl_ps_poll_hdr_t { 339193326Sed uint16_t fc; 340193326Sed uint16_t aid; 341193326Sed uint8_t bssid[IEEE802_11_BSSID_LEN]; 342193326Sed uint8_t ta[IEEE802_11_TA_LEN]; 343193326Sed}; 344193326Sed 345193326Sed#define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\ 346193326Sed IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN) 347193326Sed 348193326Sedstruct ctrl_end_hdr_t { 349193326Sed uint16_t fc; 350193326Sed uint16_t duration; 351193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 352193326Sed uint8_t bssid[IEEE802_11_BSSID_LEN]; 353193326Sed}; 354193326Sed 355193326Sed#define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 356193326Sed IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) 357193326Sed 358193326Sedstruct ctrl_end_ack_hdr_t { 359193326Sed uint16_t fc; 360193326Sed uint16_t duration; 361193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 362193326Sed uint8_t bssid[IEEE802_11_BSSID_LEN]; 363193326Sed}; 364193326Sed 365193326Sed#define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 366193326Sed IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) 367193326Sed 368193326Sedstruct ctrl_ba_hdr_t { 369193326Sed uint16_t fc; 370193326Sed uint16_t duration; 371193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 372193326Sed}; 373193326Sed 374193326Sed#define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) 375193326Sed 376193326Sedstruct ctrl_bar_hdr_t { 377193326Sed uint16_t fc; 378193326Sed uint16_t dur; 379193326Sed uint8_t ra[IEEE802_11_RA_LEN]; 380193326Sed uint8_t ta[IEEE802_11_TA_LEN]; 381193326Sed uint16_t ctl; 382193326Sed uint16_t seq; 383193326Sed}; 384193326Sed 385193326Sed#define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ 386193326Sed IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\ 387193326Sed IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN) 388193326Sed 389193326Sedstruct meshcntl_t { 390193326Sed uint8_t flags; 391193326Sed uint8_t ttl; 392193326Sed uint8_t seq[4]; 393193326Sed uint8_t addr4[6]; 394193326Sed uint8_t addr5[6]; 395193326Sed uint8_t addr6[6]; 396193326Sed}; 397193326Sed 398193326Sed#define IV_IV(iv) ((iv) & 0xFFFFFF) 399193326Sed#define IV_PAD(iv) (((iv) >> 24) & 0x3F) 400193326Sed#define IV_KEYID(iv) (((iv) >> 30) & 0x03) 401193326Sed 402193326Sed#define PRINT_SSID(p) \ 403193326Sed if (p.ssid_present) { \ 404193326Sed ND_PRINT((ndo, " (")); \ 405193326Sed fn_print(ndo, p.ssid.ssid, NULL); \ 406193326Sed ND_PRINT((ndo, ")")); \ 407193326Sed } 408193326Sed 409193326Sed#define PRINT_RATE(_sep, _r, _suf) \ 410193326Sed ND_PRINT((ndo, "%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)) 411193326Sed#define PRINT_RATES(p) \ 412193326Sed if (p.rates_present) { \ 413193326Sed int z; \ 414193326Sed const char *sep = " ["; \ 415193326Sed for (z = 0; z < p.rates.length ; z++) { \ 416193326Sed PRINT_RATE(sep, p.rates.rate[z], \ 417193326Sed (p.rates.rate[z] & 0x80 ? "*" : "")); \ 418193326Sed sep = " "; \ 419193326Sed } \ 420193326Sed if (p.rates.length != 0) \ 421193326Sed ND_PRINT((ndo, " Mbit]")); \ 422193326Sed } 423193326Sed 424193326Sed#define PRINT_DS_CHANNEL(p) \ 425193326Sed if (p.ds_present) \ 426193326Sed ND_PRINT((ndo, " CH: %u", p.ds.channel)); \ 427193326Sed ND_PRINT((ndo, "%s", \ 428193326Sed CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "")); 429193326Sed 430193326Sed#define MAX_MCS_INDEX 76 431193326Sed 432193326Sed/* 433193326Sed * Indices are: 434193326Sed * 435193326Sed * the MCS index (0-76); 436193326Sed * 437193326Sed * 0 for 20 MHz, 1 for 40 MHz; 438193326Sed * 439193326Sed * 0 for a long guard interval, 1 for a short guard interval. 440193326Sed */ 441193326Sedstatic const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = { 442193326Sed /* MCS 0 */ 443193326Sed { /* 20 Mhz */ { 6.5, /* SGI */ 7.2, }, 444193326Sed /* 40 Mhz */ { 13.5, /* SGI */ 15.0, }, 445193326Sed }, 446193326Sed 447194613Sed /* MCS 1 */ 448194613Sed { /* 20 Mhz */ { 13.0, /* SGI */ 14.4, }, 449194613Sed /* 40 Mhz */ { 27.0, /* SGI */ 30.0, }, 450193326Sed }, 451193326Sed 452193326Sed /* MCS 2 */ 453193326Sed { /* 20 Mhz */ { 19.5, /* SGI */ 21.7, }, 454193326Sed /* 40 Mhz */ { 40.5, /* SGI */ 45.0, }, 455193326Sed }, 456193326Sed 457193326Sed /* MCS 3 */ 458193326Sed { /* 20 Mhz */ { 26.0, /* SGI */ 28.9, }, 459193326Sed /* 40 Mhz */ { 54.0, /* SGI */ 60.0, }, 460193326Sed }, 461193326Sed 462193326Sed /* MCS 4 */ 463193326Sed { /* 20 Mhz */ { 39.0, /* SGI */ 43.3, }, 464193326Sed /* 40 Mhz */ { 81.0, /* SGI */ 90.0, }, 465193326Sed }, 466193326Sed 467193326Sed /* MCS 5 */ 468193326Sed { /* 20 Mhz */ { 52.0, /* SGI */ 57.8, }, 469193326Sed /* 40 Mhz */ { 108.0, /* SGI */ 120.0, }, 470193326Sed }, 471193326Sed 472193326Sed /* MCS 6 */ 473193326Sed { /* 20 Mhz */ { 58.5, /* SGI */ 65.0, }, 474193326Sed /* 40 Mhz */ { 121.5, /* SGI */ 135.0, }, 475193326Sed }, 476193326Sed 477193326Sed /* MCS 7 */ 478193326Sed { /* 20 Mhz */ { 65.0, /* SGI */ 72.2, }, 479193326Sed /* 40 Mhz */ { 135.0, /* SGI */ 150.0, }, 480193326Sed }, 481193326Sed 482193326Sed /* MCS 8 */ 483193326Sed { /* 20 Mhz */ { 13.0, /* SGI */ 14.4, }, 484193326Sed /* 40 Mhz */ { 27.0, /* SGI */ 30.0, }, 485193326Sed }, 486193326Sed 487193326Sed /* MCS 9 */ 488193326Sed { /* 20 Mhz */ { 26.0, /* SGI */ 28.9, }, 489193326Sed /* 40 Mhz */ { 54.0, /* SGI */ 60.0, }, 490193326Sed }, 491193326Sed 492193326Sed /* MCS 10 */ 493193326Sed { /* 20 Mhz */ { 39.0, /* SGI */ 43.3, }, 494193326Sed /* 40 Mhz */ { 81.0, /* SGI */ 90.0, }, 495193326Sed }, 496193326Sed 497193326Sed /* MCS 11 */ 498193326Sed { /* 20 Mhz */ { 52.0, /* SGI */ 57.8, }, 499193326Sed /* 40 Mhz */ { 108.0, /* SGI */ 120.0, }, 500193326Sed }, 501193326Sed 502193326Sed /* MCS 12 */ 503193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 504193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 505193326Sed }, 506193326Sed 507193326Sed /* MCS 13 */ 508193326Sed { /* 20 Mhz */ { 104.0, /* SGI */ 115.6, }, 509193326Sed /* 40 Mhz */ { 216.0, /* SGI */ 240.0, }, 510193326Sed }, 511193326Sed 512193326Sed /* MCS 14 */ 513193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 514193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 515193326Sed }, 516193326Sed 517193326Sed /* MCS 15 */ 518193326Sed { /* 20 Mhz */ { 130.0, /* SGI */ 144.4, }, 519193326Sed /* 40 Mhz */ { 270.0, /* SGI */ 300.0, }, 520193326Sed }, 521193326Sed 522193326Sed /* MCS 16 */ 523193326Sed { /* 20 Mhz */ { 19.5, /* SGI */ 21.7, }, 524193326Sed /* 40 Mhz */ { 40.5, /* SGI */ 45.0, }, 525193326Sed }, 526193326Sed 527193326Sed /* MCS 17 */ 528193326Sed { /* 20 Mhz */ { 39.0, /* SGI */ 43.3, }, 529193326Sed /* 40 Mhz */ { 81.0, /* SGI */ 90.0, }, 530193326Sed }, 531193326Sed 532193326Sed /* MCS 18 */ 533193326Sed { /* 20 Mhz */ { 58.5, /* SGI */ 65.0, }, 534193326Sed /* 40 Mhz */ { 121.5, /* SGI */ 135.0, }, 535193326Sed }, 536193326Sed 537193326Sed /* MCS 19 */ 538193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 539193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 540193326Sed }, 541193326Sed 542193326Sed /* MCS 20 */ 543193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 544193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 545193326Sed }, 546193326Sed 547193326Sed /* MCS 21 */ 548193326Sed { /* 20 Mhz */ { 156.0, /* SGI */ 173.3, }, 549193326Sed /* 40 Mhz */ { 324.0, /* SGI */ 360.0, }, 550193326Sed }, 551193326Sed 552193326Sed /* MCS 22 */ 553193326Sed { /* 20 Mhz */ { 175.5, /* SGI */ 195.0, }, 554194613Sed /* 40 Mhz */ { 364.5, /* SGI */ 405.0, }, 555193326Sed }, 556193326Sed 557193326Sed /* MCS 23 */ 558193326Sed { /* 20 Mhz */ { 195.0, /* SGI */ 216.7, }, 559193326Sed /* 40 Mhz */ { 405.0, /* SGI */ 450.0, }, 560193326Sed }, 561193326Sed 562193326Sed /* MCS 24 */ 563193326Sed { /* 20 Mhz */ { 26.0, /* SGI */ 28.9, }, 564193326Sed /* 40 Mhz */ { 54.0, /* SGI */ 60.0, }, 565193326Sed }, 566193326Sed 567193326Sed /* MCS 25 */ 568193326Sed { /* 20 Mhz */ { 52.0, /* SGI */ 57.8, }, 569193326Sed /* 40 Mhz */ { 108.0, /* SGI */ 120.0, }, 570193326Sed }, 571193326Sed 572193326Sed /* MCS 26 */ 573193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 574193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 575193326Sed }, 576193326Sed 577193326Sed /* MCS 27 */ 578193326Sed { /* 20 Mhz */ { 104.0, /* SGI */ 115.6, }, 579193326Sed /* 40 Mhz */ { 216.0, /* SGI */ 240.0, }, 580193326Sed }, 581193326Sed 582193326Sed /* MCS 28 */ 583193326Sed { /* 20 Mhz */ { 156.0, /* SGI */ 173.3, }, 584193326Sed /* 40 Mhz */ { 324.0, /* SGI */ 360.0, }, 585193326Sed }, 586193326Sed 587193326Sed /* MCS 29 */ 588193326Sed { /* 20 Mhz */ { 208.0, /* SGI */ 231.1, }, 589193326Sed /* 40 Mhz */ { 432.0, /* SGI */ 480.0, }, 590193326Sed }, 591193326Sed 592193326Sed /* MCS 30 */ 593193326Sed { /* 20 Mhz */ { 234.0, /* SGI */ 260.0, }, 594193326Sed /* 40 Mhz */ { 486.0, /* SGI */ 540.0, }, 595193326Sed }, 596193326Sed 597194179Sed /* MCS 31 */ 598194179Sed { /* 20 Mhz */ { 260.0, /* SGI */ 288.9, }, 599194179Sed /* 40 Mhz */ { 540.0, /* SGI */ 600.0, }, 600193326Sed }, 601193326Sed 602193326Sed /* MCS 32 */ 603193326Sed { /* 20 Mhz */ { 0.0, /* SGI */ 0.0, }, /* not valid */ 604193326Sed /* 40 Mhz */ { 6.0, /* SGI */ 6.7, }, 605193326Sed }, 606193326Sed 607193326Sed /* MCS 33 */ 608193326Sed { /* 20 Mhz */ { 39.0, /* SGI */ 43.3, }, 609193326Sed /* 40 Mhz */ { 81.0, /* SGI */ 90.0, }, 610193326Sed }, 611193326Sed 612193326Sed /* MCS 34 */ 613193326Sed { /* 20 Mhz */ { 52.0, /* SGI */ 57.8, }, 614193326Sed /* 40 Mhz */ { 108.0, /* SGI */ 120.0, }, 615193326Sed }, 616194179Sed 617194179Sed /* MCS 35 */ 618194179Sed { /* 20 Mhz */ { 65.0, /* SGI */ 72.2, }, 619194179Sed /* 40 Mhz */ { 135.0, /* SGI */ 150.0, }, 620194179Sed }, 621194179Sed 622194179Sed /* MCS 36 */ 623194179Sed { /* 20 Mhz */ { 58.5, /* SGI */ 65.0, }, 624194179Sed /* 40 Mhz */ { 121.5, /* SGI */ 135.0, }, 625193326Sed }, 626193326Sed 627193326Sed /* MCS 37 */ 628193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 629193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 630193326Sed }, 631194179Sed 632194179Sed /* MCS 38 */ 633194179Sed { /* 20 Mhz */ { 97.5, /* SGI */ 108.3, }, 634194179Sed /* 40 Mhz */ { 202.5, /* SGI */ 225.0, }, 635194179Sed }, 636194179Sed 637193326Sed /* MCS 39 */ 638193326Sed { /* 20 Mhz */ { 52.0, /* SGI */ 57.8, }, 639193326Sed /* 40 Mhz */ { 108.0, /* SGI */ 120.0, }, 640193326Sed }, 641193326Sed 642193326Sed /* MCS 40 */ 643193326Sed { /* 20 Mhz */ { 65.0, /* SGI */ 72.2, }, 644193326Sed /* 40 Mhz */ { 135.0, /* SGI */ 150.0, }, 645193326Sed }, 646193326Sed 647193326Sed /* MCS 41 */ 648193326Sed { /* 20 Mhz */ { 65.0, /* SGI */ 72.2, }, 649193326Sed /* 40 Mhz */ { 135.0, /* SGI */ 150.0, }, 650193326Sed }, 651193326Sed 652193326Sed /* MCS 42 */ 653193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 654193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 655193326Sed }, 656193326Sed 657193326Sed /* MCS 43 */ 658193326Sed { /* 20 Mhz */ { 91.0, /* SGI */ 101.1, }, 659193326Sed /* 40 Mhz */ { 189.0, /* SGI */ 210.0, }, 660193326Sed }, 661193326Sed 662193326Sed /* MCS 44 */ 663193326Sed { /* 20 Mhz */ { 91.0, /* SGI */ 101.1, }, 664193326Sed /* 40 Mhz */ { 189.0, /* SGI */ 210.0, }, 665193326Sed }, 666193326Sed 667193326Sed /* MCS 45 */ 668193326Sed { /* 20 Mhz */ { 104.0, /* SGI */ 115.6, }, 669193326Sed /* 40 Mhz */ { 216.0, /* SGI */ 240.0, }, 670193326Sed }, 671193326Sed 672193326Sed /* MCS 46 */ 673193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 674193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 675193326Sed }, 676193326Sed 677193326Sed /* MCS 47 */ 678193326Sed { /* 20 Mhz */ { 97.5, /* SGI */ 108.3, }, 679193326Sed /* 40 Mhz */ { 202.5, /* SGI */ 225.0, }, 680193326Sed }, 681193326Sed 682193326Sed /* MCS 48 */ 683193326Sed { /* 20 Mhz */ { 97.5, /* SGI */ 108.3, }, 684193326Sed /* 40 Mhz */ { 202.5, /* SGI */ 225.0, }, 685193326Sed }, 686193326Sed 687193326Sed /* MCS 49 */ 688193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 689193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 690193326Sed }, 691193326Sed 692193326Sed /* MCS 50 */ 693193326Sed { /* 20 Mhz */ { 136.5, /* SGI */ 151.7, }, 694193326Sed /* 40 Mhz */ { 283.5, /* SGI */ 315.0, }, 695193326Sed }, 696193326Sed 697193326Sed /* MCS 51 */ 698193326Sed { /* 20 Mhz */ { 136.5, /* SGI */ 151.7, }, 699193326Sed /* 40 Mhz */ { 283.5, /* SGI */ 315.0, }, 700193326Sed }, 701193326Sed 702193326Sed /* MCS 52 */ 703193326Sed { /* 20 Mhz */ { 156.0, /* SGI */ 173.3, }, 704193326Sed /* 40 Mhz */ { 324.0, /* SGI */ 360.0, }, 705193326Sed }, 706193326Sed 707193326Sed /* MCS 53 */ 708193326Sed { /* 20 Mhz */ { 65.0, /* SGI */ 72.2, }, 709193326Sed /* 40 Mhz */ { 135.0, /* SGI */ 150.0, }, 710193326Sed }, 711193326Sed 712193326Sed /* MCS 54 */ 713193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 714193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 715193326Sed }, 716193326Sed 717193326Sed /* MCS 55 */ 718193326Sed { /* 20 Mhz */ { 91.0, /* SGI */ 101.1, }, 719193326Sed /* 40 Mhz */ { 189.0, /* SGI */ 210.0, }, 720193326Sed }, 721193326Sed 722193326Sed /* MCS 56 */ 723193326Sed { /* 20 Mhz */ { 78.0, /* SGI */ 86.7, }, 724193326Sed /* 40 Mhz */ { 162.0, /* SGI */ 180.0, }, 725193326Sed }, 726193326Sed 727193326Sed /* MCS 57 */ 728193326Sed { /* 20 Mhz */ { 91.0, /* SGI */ 101.1, }, 729193326Sed /* 40 Mhz */ { 189.0, /* SGI */ 210.0, }, 730193326Sed }, 731193326Sed 732193326Sed /* MCS 58 */ 733193326Sed { /* 20 Mhz */ { 104.0, /* SGI */ 115.6, }, 734193326Sed /* 40 Mhz */ { 216.0, /* SGI */ 240.0, }, 735193326Sed }, 736193326Sed 737193326Sed /* MCS 59 */ 738193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 739193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 740193326Sed }, 741193326Sed 742193326Sed /* MCS 60 */ 743193326Sed { /* 20 Mhz */ { 104.0, /* SGI */ 115.6, }, 744193326Sed /* 40 Mhz */ { 216.0, /* SGI */ 240.0, }, 745193326Sed }, 746193326Sed 747193326Sed /* MCS 61 */ 748193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 749193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 750193326Sed }, 751193326Sed 752193326Sed /* MCS 62 */ 753193326Sed { /* 20 Mhz */ { 130.0, /* SGI */ 144.4, }, 754193326Sed /* 40 Mhz */ { 270.0, /* SGI */ 300.0, }, 755193326Sed }, 756193326Sed 757193326Sed /* MCS 63 */ 758193326Sed { /* 20 Mhz */ { 130.0, /* SGI */ 144.4, }, 759193326Sed /* 40 Mhz */ { 270.0, /* SGI */ 300.0, }, 760193326Sed }, 761193326Sed 762193326Sed /* MCS 64 */ 763193326Sed { /* 20 Mhz */ { 143.0, /* SGI */ 158.9, }, 764193326Sed /* 40 Mhz */ { 297.0, /* SGI */ 330.0, }, 765193326Sed }, 766193326Sed 767193326Sed /* MCS 65 */ 768193326Sed { /* 20 Mhz */ { 97.5, /* SGI */ 108.3, }, 769193326Sed /* 40 Mhz */ { 202.5, /* SGI */ 225.0, }, 770193326Sed }, 771193326Sed 772193326Sed /* MCS 66 */ 773193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 774193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 775193326Sed }, 776193326Sed 777193326Sed /* MCS 67 */ 778193326Sed { /* 20 Mhz */ { 136.5, /* SGI */ 151.7, }, 779193326Sed /* 40 Mhz */ { 283.5, /* SGI */ 315.0, }, 780193326Sed }, 781193326Sed 782193326Sed /* MCS 68 */ 783193326Sed { /* 20 Mhz */ { 117.0, /* SGI */ 130.0, }, 784193326Sed /* 40 Mhz */ { 243.0, /* SGI */ 270.0, }, 785193576Sed }, 786193576Sed 787193576Sed /* MCS 69 */ 788193576Sed { /* 20 Mhz */ { 136.5, /* SGI */ 151.7, }, 789193326Sed /* 40 Mhz */ { 283.5, /* SGI */ 315.0, }, 790193326Sed }, 791193326Sed 792193326Sed /* MCS 70 */ 793193326Sed { /* 20 Mhz */ { 156.0, /* SGI */ 173.3, }, 794193326Sed /* 40 Mhz */ { 324.0, /* SGI */ 360.0, }, 795193326Sed }, 796193326Sed 797193326Sed /* MCS 71 */ 798193326Sed { /* 20 Mhz */ { 175.5, /* SGI */ 195.0, }, 799193326Sed /* 40 Mhz */ { 364.5, /* SGI */ 405.0, }, 800193326Sed }, 801193326Sed 802193326Sed /* MCS 72 */ 803193326Sed { /* 20 Mhz */ { 156.0, /* SGI */ 173.3, }, 804193576Sed /* 40 Mhz */ { 324.0, /* SGI */ 360.0, }, 805193326Sed }, 806193326Sed 807193326Sed /* MCS 73 */ 808193326Sed { /* 20 Mhz */ { 175.5, /* SGI */ 195.0, }, 809193326Sed /* 40 Mhz */ { 364.5, /* SGI */ 405.0, }, 810193576Sed }, 811193326Sed 812194613Sed /* MCS 74 */ 813194613Sed { /* 20 Mhz */ { 195.0, /* SGI */ 216.7, }, 814194613Sed /* 40 Mhz */ { 405.0, /* SGI */ 450.0, }, 815194613Sed }, 816193326Sed 817193326Sed /* MCS 75 */ 818193326Sed { /* 20 Mhz */ { 195.0, /* SGI */ 216.7, }, 819193326Sed /* 40 Mhz */ { 405.0, /* SGI */ 450.0, }, 820193326Sed }, 821193326Sed 822193326Sed /* MCS 76 */ 823193326Sed { /* 20 Mhz */ { 214.5, /* SGI */ 238.3, }, 824193326Sed /* 40 Mhz */ { 445.5, /* SGI */ 495.0, }, 825193326Sed }, 826193326Sed}; 827193326Sed 828193326Sedstatic const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; 829193326Sed#define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0]) 830193326Sed 831193326Sedstatic const char *status_text[] = { 832193326Sed "Successful", /* 0 */ 833193326Sed "Unspecified failure", /* 1 */ 834193326Sed "Reserved", /* 2 */ 835193326Sed "Reserved", /* 3 */ 836193326Sed "Reserved", /* 4 */ 837193326Sed "Reserved", /* 5 */ 838193326Sed "Reserved", /* 6 */ 839193326Sed "Reserved", /* 7 */ 840193326Sed "Reserved", /* 8 */ 841193326Sed "Reserved", /* 9 */ 842193326Sed "Cannot Support all requested capabilities in the Capability " 843193326Sed "Information field", /* 10 */ 844193326Sed "Reassociation denied due to inability to confirm that association " 845193326Sed "exists", /* 11 */ 846193326Sed "Association denied due to reason outside the scope of the " 847193326Sed "standard", /* 12 */ 848193326Sed "Responding station does not support the specified authentication " 849193326Sed "algorithm ", /* 13 */ 850193576Sed "Received an Authentication frame with authentication transaction " 851193326Sed "sequence number out of expected sequence", /* 14 */ 852193326Sed "Authentication rejected because of challenge failure", /* 15 */ 853193326Sed "Authentication rejected due to timeout waiting for next frame in " 854193326Sed "sequence", /* 16 */ 855193326Sed "Association denied because AP is unable to handle additional" 856194613Sed "associated stations", /* 17 */ 857193326Sed "Association denied due to requesting station not supporting all of " 858193326Sed "the data rates in BSSBasicRateSet parameter", /* 18 */ 859193326Sed "Association denied due to requesting station not supporting " 860193326Sed "short preamble operation", /* 19 */ 861193326Sed "Association denied due to requesting station not supporting " 862193326Sed "PBCC encoding", /* 20 */ 863193326Sed "Association denied due to requesting station not supporting " 864193326Sed "channel agility", /* 21 */ 865193326Sed "Association request rejected because Spectrum Management " 866193326Sed "capability is required", /* 22 */ 867193326Sed "Association request rejected because the information in the " 868193326Sed "Power Capability element is unacceptable", /* 23 */ 869193326Sed "Association request rejected because the information in the " 870193326Sed "Supported Channels element is unacceptable", /* 24 */ 871193326Sed "Association denied due to requesting station not supporting " 872193326Sed "short slot operation", /* 25 */ 873193326Sed "Association denied due to requesting station not supporting " 874193576Sed "DSSS-OFDM operation", /* 26 */ 875193576Sed "Association denied because the requested STA does not support HT " 876193326Sed "features", /* 27 */ 877193326Sed "Reserved", /* 28 */ 878193326Sed "Association denied because the requested STA does not support " 879193326Sed "the PCO transition time required by the AP", /* 29 */ 880193326Sed "Reserved", /* 30 */ 881193576Sed "Reserved", /* 31 */ 882193576Sed "Unspecified, QoS-related failure", /* 32 */ 883193576Sed "Association denied due to QAP having insufficient bandwidth " 884193326Sed "to handle another QSTA", /* 33 */ 885193326Sed "Association denied due to excessive frame loss rates and/or " 886193326Sed "poor conditions on current operating channel", /* 34 */ 887193326Sed "Association (with QBSS) denied due to requesting station not " 888193326Sed "supporting the QoS facility", /* 35 */ 889193326Sed "Association denied due to requesting station not supporting " 890193326Sed "Block Ack", /* 36 */ 891193326Sed "The request has been declined", /* 37 */ 892193576Sed "The request has not been successful as one or more parameters " 893193576Sed "have invalid values", /* 38 */ 894193576Sed "The TS has not been created because the request cannot be honored. " 895193576Sed "Try again with the suggested changes to the TSPEC", /* 39 */ 896193326Sed "Invalid Information Element", /* 40 */ 897193326Sed "Group Cipher is not valid", /* 41 */ 898193326Sed "Pairwise Cipher is not valid", /* 42 */ 899193326Sed "AKMP is not valid", /* 43 */ 900193326Sed "Unsupported RSN IE version", /* 44 */ 901193326Sed "Invalid RSN IE Capabilities", /* 45 */ 902193326Sed "Cipher suite is rejected per security policy", /* 46 */ 903193326Sed "The TS has not been created. However, the HC may be capable of " 904193326Sed "creating a TS, in response to a request, after the time indicated " 905193326Sed "in the TS Delay element", /* 47 */ 906193326Sed "Direct Link is not allowed in the BSS by policy", /* 48 */ 907193326Sed "Destination STA is not present within this QBSS.", /* 49 */ 908193326Sed "The Destination STA is not a QSTA.", /* 50 */ 909193326Sed 910193326Sed}; 911193326Sed#define NUM_STATUSES (sizeof status_text / sizeof status_text[0]) 912193326Sed 913193326Sedstatic const char *reason_text[] = { 914193326Sed "Reserved", /* 0 */ 915193326Sed "Unspecified reason", /* 1 */ 916193326Sed "Previous authentication no longer valid", /* 2 */ 917193326Sed "Deauthenticated because sending station is leaving (or has left) " 918193326Sed "IBSS or ESS", /* 3 */ 919193326Sed "Disassociated due to inactivity", /* 4 */ 920193326Sed "Disassociated because AP is unable to handle all currently " 921193326Sed " associated stations", /* 5 */ 922193326Sed "Class 2 frame received from nonauthenticated station", /* 6 */ 923193326Sed "Class 3 frame received from nonassociated station", /* 7 */ 924193326Sed "Disassociated because sending station is leaving " 925193326Sed "(or has left) BSS", /* 8 */ 926193326Sed "Station requesting (re)association is not authenticated with " 927193326Sed "responding station", /* 9 */ 928193326Sed "Disassociated because the information in the Power Capability " 929193326Sed "element is unacceptable", /* 10 */ 930193326Sed "Disassociated because the information in the SupportedChannels " 931193326Sed "element is unacceptable", /* 11 */ 932193326Sed "Invalid Information Element", /* 12 */ 933193326Sed "Reserved", /* 13 */ 934193326Sed "Michael MIC failure", /* 14 */ 935193326Sed "4-Way Handshake timeout", /* 15 */ 936193326Sed "Group key update timeout", /* 16 */ 937193326Sed "Information element in 4-Way Handshake different from (Re)Association" 938193326Sed "Request/Probe Response/Beacon", /* 17 */ 939193326Sed "Group Cipher is not valid", /* 18 */ 940193326Sed "AKMP is not valid", /* 20 */ 941193326Sed "Unsupported RSN IE version", /* 21 */ 942193326Sed "Invalid RSN IE Capabilities", /* 22 */ 943193326Sed "IEEE 802.1X Authentication failed", /* 23 */ 944193326Sed "Cipher suite is rejected per security policy", /* 24 */ 945193326Sed "Reserved", /* 25 */ 946193326Sed "Reserved", /* 26 */ 947193326Sed "Reserved", /* 27 */ 948193326Sed "Reserved", /* 28 */ 949193326Sed "Reserved", /* 29 */ 950193326Sed "Reserved", /* 30 */ 951193326Sed "TS deleted because QoS AP lacks sufficient bandwidth for this " 952193326Sed "QoS STA due to a change in BSS service characteristics or " 953193326Sed "operational mode (e.g. an HT BSS change from 40 MHz channel " 954193326Sed "to 20 MHz channel)", /* 31 */ 955193326Sed "Disassociated for unspecified, QoS-related reason", /* 32 */ 956193326Sed "Disassociated because QoS AP lacks sufficient bandwidth for this " 957193326Sed "QoS STA", /* 33 */ 958193326Sed "Disassociated because of excessive number of frames that need to be " 959193326Sed "acknowledged, but are not acknowledged for AP transmissions " 960193326Sed "and/or poor channel conditions", /* 34 */ 961193326Sed "Disassociated because STA is transmitting outside the limits " 962193326Sed "of its TXOPs", /* 35 */ 963193326Sed "Requested from peer STA as the STA is leaving the BSS " 964193326Sed "(or resetting)", /* 36 */ 965193326Sed "Requested from peer STA as it does not want to use the " 966193326Sed "mechanism", /* 37 */ 967193326Sed "Requested from peer STA as the STA received frames using the " 968193326Sed "mechanism for which a set up is required", /* 38 */ 969193326Sed "Requested from peer STA due to time out", /* 39 */ 970193326Sed "Reserved", /* 40 */ 971193326Sed "Reserved", /* 41 */ 972193326Sed "Reserved", /* 42 */ 973193326Sed "Reserved", /* 43 */ 974193326Sed "Reserved", /* 44 */ 975193326Sed "Peer STA does not support the requested cipher suite", /* 45 */ 976193326Sed "Association denied due to requesting STA not supporting HT " 977193326Sed "features", /* 46 */ 978193326Sed}; 979193326Sed#define NUM_REASONS (sizeof reason_text / sizeof reason_text[0]) 980193326Sed 981193326Sedstatic int 982193326Sedwep_print(netdissect_options *ndo, 983193326Sed const u_char *p) 984193326Sed{ 985194179Sed uint32_t iv; 986194179Sed 987194179Sed if (!ND_TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN)) 988194179Sed return 0; 989194179Sed iv = EXTRACT_LE_32BITS(p); 990194179Sed 991194179Sed ND_PRINT((ndo, " IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), 992194179Sed IV_KEYID(iv))); 993194179Sed 994194179Sed return 1; 995194179Sed} 996194179Sed 997194179Sedstatic int 998194179Sedparse_elements(netdissect_options *ndo, 999194179Sed struct mgmt_body_t *pbody, const u_char *p, int offset, 1000194179Sed u_int length) 1001194179Sed{ 1002194179Sed u_int elementlen; 1003194179Sed struct ssid_t ssid; 1004194179Sed struct challenge_t challenge; 1005194179Sed struct rates_t rates; 1006194179Sed struct ds_t ds; 1007194179Sed struct cf_t cf; 1008194179Sed struct tim_t tim; 1009194179Sed 1010194179Sed /* 1011194179Sed * We haven't seen any elements yet. 1012193326Sed */ 1013193326Sed pbody->challenge_present = 0; 1014193326Sed pbody->ssid_present = 0; 1015193326Sed pbody->rates_present = 0; 1016193326Sed pbody->ds_present = 0; 1017193326Sed pbody->cf_present = 0; 1018193326Sed pbody->tim_present = 0; 1019193326Sed 1020193576Sed while (length != 0) { 1021193326Sed /* Make sure we at least have the element ID and length. */ 1022193326Sed if (!ND_TTEST2(*(p + offset), 2)) 1023193326Sed return 0; 1024193326Sed if (length < 2) 1025193326Sed return 0; 1026194179Sed elementlen = *(p + offset + 1); 1027194179Sed 1028194179Sed /* Make sure we have the entire element. */ 1029194179Sed if (!ND_TTEST2(*(p + offset + 2), elementlen)) 1030193326Sed return 0; 1031193326Sed if (length < elementlen + 2) 1032193326Sed return 0; 1033193326Sed 1034193326Sed switch (*(p + offset)) { 1035193326Sed case E_SSID: 1036193326Sed memcpy(&ssid, p + offset, 2); 1037193326Sed offset += 2; 1038193326Sed length -= 2; 1039193326Sed if (ssid.length != 0) { 1040193326Sed if (ssid.length > sizeof(ssid.ssid) - 1) 1041193326Sed return 0; 1042193326Sed memcpy(&ssid.ssid, p + offset, ssid.length); 1043193326Sed offset += ssid.length; 1044193326Sed length -= ssid.length; 1045193326Sed } 1046193326Sed ssid.ssid[ssid.length] = '\0'; 1047193326Sed /* 1048193326Sed * Present and not truncated. 1049193326Sed * 1050193326Sed * If we haven't already seen an SSID IE, 1051193326Sed * copy this one, otherwise ignore this one, 1052193326Sed * so we later report the first one we saw. 1053193326Sed */ 1054193326Sed if (!pbody->ssid_present) { 1055193326Sed pbody->ssid = ssid; 1056193326Sed pbody->ssid_present = 1; 1057193326Sed } 1058193326Sed break; 1059193326Sed case E_CHALLENGE: 1060193326Sed memcpy(&challenge, p + offset, 2); 1061193326Sed offset += 2; 1062193326Sed length -= 2; 1063194179Sed if (challenge.length != 0) { 1064194179Sed if (challenge.length > 1065194179Sed sizeof(challenge.text) - 1) 1066194179Sed return 0; 1067194179Sed memcpy(&challenge.text, p + offset, 1068194179Sed challenge.length); 1069194179Sed offset += challenge.length; 1070193326Sed length -= challenge.length; 1071193326Sed } 1072193326Sed challenge.text[challenge.length] = '\0'; 1073193326Sed /* 1074193326Sed * Present and not truncated. 1075193326Sed * 1076193326Sed * If we haven't already seen a challenge IE, 1077193326Sed * copy this one, otherwise ignore this one, 1078193326Sed * so we later report the first one we saw. 1079193576Sed */ 1080193576Sed if (!pbody->challenge_present) { 1081193326Sed pbody->challenge = challenge; 1082193326Sed pbody->challenge_present = 1; 1083193576Sed } 1084193576Sed break; 1085193576Sed case E_RATES: 1086193326Sed memcpy(&rates, p + offset, 2); 1087193326Sed offset += 2; 1088193326Sed length -= 2; 1089193326Sed if (rates.length != 0) { 1090193326Sed if (rates.length > sizeof rates.rate) 1091193326Sed return 0; 1092193326Sed memcpy(&rates.rate, p + offset, rates.length); 1093193326Sed offset += rates.length; 1094193326Sed length -= rates.length; 1095193326Sed } 1096193326Sed /* 1097193326Sed * Present and not truncated. 1098193326Sed * 1099193326Sed * If we haven't already seen a rates IE, 1100194179Sed * copy this one if it's not zero-length, 1101194179Sed * otherwise ignore this one, so we later 1102194179Sed * report the first one we saw. 1103194179Sed * 1104194179Sed * We ignore zero-length rates IEs as some 1105194179Sed * devices seem to put a zero-length rates 1106194179Sed * IE, followed by an SSID IE, followed by 1107194179Sed * a non-zero-length rates IE into frames, 1108194179Sed * even though IEEE Std 802.11-2007 doesn't 1109194179Sed * seem to indicate that a zero-length rates 1110194179Sed * IE is valid. 1111194179Sed */ 1112194179Sed if (!pbody->rates_present && rates.length != 0) { 1113194179Sed pbody->rates = rates; 1114194179Sed pbody->rates_present = 1; 1115193326Sed } 1116193326Sed break; 1117193326Sed case E_DS: 1118193326Sed memcpy(&ds, p + offset, 2); 1119193326Sed offset += 2; 1120193326Sed length -= 2; 1121193326Sed if (ds.length != 1) { 1122193326Sed offset += ds.length; 1123193326Sed length -= ds.length; 1124193326Sed break; 1125193326Sed } 1126193326Sed ds.channel = *(p + offset); 1127193326Sed offset += 1; 1128193326Sed length -= 1; 1129193326Sed /* 1130193326Sed * Present and not truncated. 1131193326Sed * 1132194179Sed * If we haven't already seen a DS IE, 1133194179Sed * copy this one, otherwise ignore this one, 1134194179Sed * so we later report the first one we saw. 1135194179Sed */ 1136194179Sed if (!pbody->ds_present) { 1137194179Sed pbody->ds = ds; 1138194179Sed pbody->ds_present = 1; 1139194179Sed } 1140194179Sed break; 1141194179Sed case E_CF: 1142194179Sed memcpy(&cf, p + offset, 2); 1143193326Sed offset += 2; 1144193326Sed length -= 2; 1145193326Sed if (cf.length != 6) { 1146193326Sed offset += cf.length; 1147193326Sed length -= cf.length; 1148193326Sed break; 1149193326Sed } 1150193326Sed memcpy(&cf.count, p + offset, 6); 1151193326Sed offset += 6; 1152193326Sed length -= 6; 1153193326Sed /* 1154193326Sed * Present and not truncated. 1155193576Sed * 1156193576Sed * If we haven't already seen a CF IE, 1157193326Sed * copy this one, otherwise ignore this one, 1158193326Sed * so we later report the first one we saw. 1159193576Sed */ 1160193576Sed if (!pbody->cf_present) { 1161193576Sed pbody->cf = cf; 1162193326Sed pbody->cf_present = 1; 1163193326Sed } 1164193326Sed break; 1165193326Sed case E_TIM: 1166193326Sed memcpy(&tim, p + offset, 2); 1167193326Sed offset += 2; 1168193326Sed length -= 2; 1169193326Sed if (tim.length <= 3) { 1170193326Sed offset += tim.length; 1171193326Sed length -= tim.length; 1172193326Sed break; 1173193326Sed } 1174193326Sed if (tim.length - 3 > (int)sizeof tim.bitmap) 1175193326Sed return 0; 1176193326Sed memcpy(&tim.count, p + offset, 3); 1177193326Sed offset += 3; 1178193576Sed length -= 3; 1179193576Sed 1180193576Sed memcpy(tim.bitmap, p + offset, tim.length - 3); 1181193576Sed offset += tim.length - 3; 1182193326Sed length -= tim.length - 3; 1183193326Sed /* 1184194179Sed * Present and not truncated. 1185194179Sed * 1186193326Sed * If we haven't already seen a TIM IE, 1187194179Sed * copy this one, otherwise ignore this one, 1188194179Sed * so we later report the first one we saw. 1189193326Sed */ 1190193326Sed if (!pbody->tim_present) { 1191193326Sed pbody->tim = tim; 1192193326Sed pbody->tim_present = 1; 1193193326Sed } 1194193326Sed break; 1195193326Sed default: 1196193326Sed#if 0 1197193326Sed ND_PRINT((ndo, "(1) unhandled element_id (%d) ", 1198193326Sed *(p + offset))); 1199193326Sed#endif 1200193326Sed offset += 2 + elementlen; 1201193326Sed length -= 2 + elementlen; 1202193326Sed break; 1203193326Sed } 1204193326Sed } 1205193326Sed 1206193326Sed /* No problems found. */ 1207193326Sed return 1; 1208193326Sed} 1209193326Sed 1210193326Sed/********************************************************************************* 1211193326Sed * Print Handle functions for the management frame types 1212193326Sed *********************************************************************************/ 1213193326Sed 1214193326Sedstatic int 1215193326Sedhandle_beacon(netdissect_options *ndo, 1216193326Sed const u_char *p, u_int length) 1217194613Sed{ 1218194613Sed struct mgmt_body_t pbody; 1219194613Sed int offset = 0; 1220194613Sed int ret; 1221194613Sed 1222193326Sed memset(&pbody, 0, sizeof(pbody)); 1223193326Sed 1224193326Sed if (!ND_TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1225193326Sed IEEE802_11_CAPINFO_LEN)) 1226193326Sed return 0; 1227193326Sed if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1228193326Sed IEEE802_11_CAPINFO_LEN) 1229193576Sed return 0; 1230193576Sed memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); 1231193576Sed offset += IEEE802_11_TSTAMP_LEN; 1232193576Sed length -= IEEE802_11_TSTAMP_LEN; 1233193326Sed pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); 1234193326Sed offset += IEEE802_11_BCNINT_LEN; 1235193326Sed length -= IEEE802_11_BCNINT_LEN; 1236193326Sed pbody.capability_info = EXTRACT_LE_16BITS(p+offset); 1237193326Sed offset += IEEE802_11_CAPINFO_LEN; 1238193326Sed length -= IEEE802_11_CAPINFO_LEN; 1239193326Sed 1240193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1241193326Sed 1242193326Sed PRINT_SSID(pbody); 1243193326Sed PRINT_RATES(pbody); 1244193326Sed ND_PRINT((ndo, " %s", 1245193326Sed CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS")); 1246193326Sed PRINT_DS_CHANNEL(pbody); 1247193326Sed 1248193326Sed return ret; 1249193326Sed} 1250193326Sed 1251193326Sedstatic int 1252193326Sedhandle_assoc_request(netdissect_options *ndo, 1253193326Sed const u_char *p, u_int length) 1254193326Sed{ 1255193326Sed struct mgmt_body_t pbody; 1256193326Sed int offset = 0; 1257193326Sed int ret; 1258193326Sed 1259193326Sed memset(&pbody, 0, sizeof(pbody)); 1260193326Sed 1261193326Sed if (!ND_TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)) 1262193326Sed return 0; 1263193326Sed if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN) 1264193326Sed return 0; 1265193326Sed pbody.capability_info = EXTRACT_LE_16BITS(p); 1266194613Sed offset += IEEE802_11_CAPINFO_LEN; 1267194613Sed length -= IEEE802_11_CAPINFO_LEN; 1268194613Sed pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); 1269194613Sed offset += IEEE802_11_LISTENINT_LEN; 1270193326Sed length -= IEEE802_11_LISTENINT_LEN; 1271193326Sed 1272193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1273193326Sed 1274193326Sed PRINT_SSID(pbody); 1275193326Sed PRINT_RATES(pbody); 1276193326Sed return ret; 1277193326Sed} 1278193326Sed 1279193326Sedstatic int 1280193326Sedhandle_assoc_response(netdissect_options *ndo, 1281193326Sed const u_char *p, u_int length) 1282193326Sed{ 1283193326Sed struct mgmt_body_t pbody; 1284193326Sed int offset = 0; 1285193326Sed int ret; 1286193326Sed 1287193326Sed memset(&pbody, 0, sizeof(pbody)); 1288193326Sed 1289193326Sed if (!ND_TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + 1290193326Sed IEEE802_11_AID_LEN)) 1291193326Sed return 0; 1292193326Sed if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + 1293193326Sed IEEE802_11_AID_LEN) 1294193326Sed return 0; 1295193326Sed pbody.capability_info = EXTRACT_LE_16BITS(p); 1296193326Sed offset += IEEE802_11_CAPINFO_LEN; 1297193326Sed length -= IEEE802_11_CAPINFO_LEN; 1298193326Sed pbody.status_code = EXTRACT_LE_16BITS(p+offset); 1299193326Sed offset += IEEE802_11_STATUS_LEN; 1300193326Sed length -= IEEE802_11_STATUS_LEN; 1301193326Sed pbody.aid = EXTRACT_LE_16BITS(p+offset); 1302193326Sed offset += IEEE802_11_AID_LEN; 1303193326Sed length -= IEEE802_11_AID_LEN; 1304193326Sed 1305193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1306193326Sed 1307193326Sed ND_PRINT((ndo, " AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 , 1308193326Sed CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "", 1309193326Sed (pbody.status_code < NUM_STATUSES 1310193326Sed ? status_text[pbody.status_code] 1311193326Sed : "n/a"))); 1312193326Sed 1313193326Sed return ret; 1314193326Sed} 1315193326Sed 1316193326Sedstatic int 1317193326Sedhandle_reassoc_request(netdissect_options *ndo, 1318193326Sed const u_char *p, u_int length) 1319193326Sed{ 1320193326Sed struct mgmt_body_t pbody; 1321193326Sed int offset = 0; 1322193326Sed int ret; 1323193326Sed 1324193326Sed memset(&pbody, 0, sizeof(pbody)); 1325193326Sed 1326193326Sed if (!ND_TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + 1327193326Sed IEEE802_11_AP_LEN)) 1328193326Sed return 0; 1329193326Sed if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + 1330193326Sed IEEE802_11_AP_LEN) 1331193326Sed return 0; 1332193326Sed pbody.capability_info = EXTRACT_LE_16BITS(p); 1333193326Sed offset += IEEE802_11_CAPINFO_LEN; 1334193326Sed length -= IEEE802_11_CAPINFO_LEN; 1335193326Sed pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); 1336193326Sed offset += IEEE802_11_LISTENINT_LEN; 1337193326Sed length -= IEEE802_11_LISTENINT_LEN; 1338193326Sed memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN); 1339193326Sed offset += IEEE802_11_AP_LEN; 1340193326Sed length -= IEEE802_11_AP_LEN; 1341193326Sed 1342193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1343193326Sed 1344193326Sed PRINT_SSID(pbody); 1345193326Sed ND_PRINT((ndo, " AP : %s", etheraddr_string(ndo, pbody.ap ))); 1346193326Sed 1347193326Sed return ret; 1348193326Sed} 1349193326Sed 1350193326Sedstatic int 1351193326Sedhandle_reassoc_response(netdissect_options *ndo, 1352193326Sed const u_char *p, u_int length) 1353193326Sed{ 1354193326Sed /* Same as a Association Reponse */ 1355193326Sed return handle_assoc_response(ndo, p, length); 1356193326Sed} 1357193326Sed 1358193326Sedstatic int 1359193326Sedhandle_probe_request(netdissect_options *ndo, 1360193326Sed const u_char *p, u_int length) 1361193326Sed{ 1362193326Sed struct mgmt_body_t pbody; 1363193326Sed int offset = 0; 1364193326Sed int ret; 1365193326Sed 1366193326Sed memset(&pbody, 0, sizeof(pbody)); 1367193326Sed 1368193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1369193326Sed 1370193326Sed PRINT_SSID(pbody); 1371193326Sed PRINT_RATES(pbody); 1372193326Sed 1373193326Sed return ret; 1374193326Sed} 1375193326Sed 1376193326Sedstatic int 1377193326Sedhandle_probe_response(netdissect_options *ndo, 1378193326Sed const u_char *p, u_int length) 1379193326Sed{ 1380193326Sed struct mgmt_body_t pbody; 1381193326Sed int offset = 0; 1382193326Sed int ret; 1383193326Sed 1384193326Sed memset(&pbody, 0, sizeof(pbody)); 1385193326Sed 1386193326Sed if (!ND_TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1387193326Sed IEEE802_11_CAPINFO_LEN)) 1388193326Sed return 0; 1389193326Sed if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + 1390193326Sed IEEE802_11_CAPINFO_LEN) 1391193326Sed return 0; 1392193326Sed memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); 1393193326Sed offset += IEEE802_11_TSTAMP_LEN; 1394193326Sed length -= IEEE802_11_TSTAMP_LEN; 1395193326Sed pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); 1396193326Sed offset += IEEE802_11_BCNINT_LEN; 1397193326Sed length -= IEEE802_11_BCNINT_LEN; 1398193326Sed pbody.capability_info = EXTRACT_LE_16BITS(p+offset); 1399193326Sed offset += IEEE802_11_CAPINFO_LEN; 1400193326Sed length -= IEEE802_11_CAPINFO_LEN; 1401193326Sed 1402193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1403193326Sed 1404193326Sed PRINT_SSID(pbody); 1405193326Sed PRINT_RATES(pbody); 1406193326Sed PRINT_DS_CHANNEL(pbody); 1407193326Sed 1408193326Sed return ret; 1409193326Sed} 1410193326Sed 1411193326Sedstatic int 1412193326Sedhandle_atim(void) 1413193326Sed{ 1414193326Sed /* the frame body for ATIM is null. */ 1415193326Sed return 1; 1416193326Sed} 1417193326Sed 1418193326Sedstatic int 1419193326Sedhandle_disassoc(netdissect_options *ndo, 1420193326Sed const u_char *p, u_int length) 1421193326Sed{ 1422193326Sed struct mgmt_body_t pbody; 1423193326Sed 1424193326Sed memset(&pbody, 0, sizeof(pbody)); 1425193326Sed 1426193326Sed if (!ND_TTEST2(*p, IEEE802_11_REASON_LEN)) 1427193326Sed return 0; 1428193326Sed if (length < IEEE802_11_REASON_LEN) 1429193326Sed return 0; 1430193326Sed pbody.reason_code = EXTRACT_LE_16BITS(p); 1431193326Sed 1432193326Sed ND_PRINT((ndo, ": %s", 1433193326Sed (pbody.reason_code < NUM_REASONS) 1434193326Sed ? reason_text[pbody.reason_code] 1435193326Sed : "Reserved")); 1436193326Sed 1437193326Sed return 1; 1438193326Sed} 1439193326Sed 1440193326Sedstatic int 1441193326Sedhandle_auth(netdissect_options *ndo, 1442193326Sed const u_char *p, u_int length) 1443193326Sed{ 1444193326Sed struct mgmt_body_t pbody; 1445193326Sed int offset = 0; 1446193326Sed int ret; 1447193326Sed 1448193326Sed memset(&pbody, 0, sizeof(pbody)); 1449193326Sed 1450193326Sed if (!ND_TTEST2(*p, 6)) 1451193326Sed return 0; 1452193326Sed if (length < 6) 1453193326Sed return 0; 1454193326Sed pbody.auth_alg = EXTRACT_LE_16BITS(p); 1455193326Sed offset += 2; 1456193326Sed length -= 2; 1457193326Sed pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset); 1458193326Sed offset += 2; 1459193326Sed length -= 2; 1460193326Sed pbody.status_code = EXTRACT_LE_16BITS(p + offset); 1461193326Sed offset += 2; 1462193326Sed length -= 2; 1463193326Sed 1464193326Sed ret = parse_elements(ndo, &pbody, p, offset, length); 1465193326Sed 1466193326Sed if ((pbody.auth_alg == 1) && 1467193326Sed ((pbody.auth_trans_seq_num == 2) || 1468193326Sed (pbody.auth_trans_seq_num == 3))) { 1469193326Sed ND_PRINT((ndo, " (%s)-%x [Challenge Text] %s", 1470193326Sed (pbody.auth_alg < NUM_AUTH_ALGS) 1471193326Sed ? auth_alg_text[pbody.auth_alg] 1472193326Sed : "Reserved", 1473193326Sed pbody.auth_trans_seq_num, 1474193326Sed ((pbody.auth_trans_seq_num % 2) 1475193326Sed ? ((pbody.status_code < NUM_STATUSES) 1476193326Sed ? status_text[pbody.status_code] 1477193326Sed : "n/a") : ""))); 1478193326Sed return ret; 1479193326Sed } 1480193326Sed ND_PRINT((ndo, " (%s)-%x: %s", 1481194179Sed (pbody.auth_alg < NUM_AUTH_ALGS) 1482193326Sed ? auth_alg_text[pbody.auth_alg] 1483193326Sed : "Reserved", 1484194179Sed pbody.auth_trans_seq_num, 1485193326Sed (pbody.auth_trans_seq_num % 2) 1486193326Sed ? ((pbody.status_code < NUM_STATUSES) 1487193326Sed ? status_text[pbody.status_code] 1488193326Sed : "n/a") 1489193326Sed : "")); 1490193326Sed 1491193326Sed return ret; 1492194179Sed} 1493193326Sed 1494193326Sedstatic int 1495193326Sedhandle_deauth(netdissect_options *ndo, 1496193326Sed const uint8_t *src, const u_char *p, u_int length) 1497193326Sed{ 1498193326Sed struct mgmt_body_t pbody; 1499193326Sed const char *reason = NULL; 1500193326Sed 1501193326Sed memset(&pbody, 0, sizeof(pbody)); 1502193326Sed 1503193326Sed if (!ND_TTEST2(*p, IEEE802_11_REASON_LEN)) 1504193326Sed return 0; 1505193326Sed if (length < IEEE802_11_REASON_LEN) 1506193326Sed return 0; 1507193326Sed pbody.reason_code = EXTRACT_LE_16BITS(p); 1508193326Sed 1509193326Sed reason = (pbody.reason_code < NUM_REASONS) 1510193326Sed ? reason_text[pbody.reason_code] 1511193326Sed : "Reserved"; 1512193326Sed 1513193326Sed if (ndo->ndo_eflag) { 1514193326Sed ND_PRINT((ndo, ": %s", reason)); 1515193326Sed } else { 1516193326Sed ND_PRINT((ndo, " (%s): %s", etheraddr_string(ndo, src), reason)); 1517193326Sed } 1518193326Sed return 1; 1519193326Sed} 1520193326Sed 1521193326Sed#define PRINT_HT_ACTION(v) (\ 1522193326Sed (v) == 0 ? ND_PRINT((ndo, "TxChWidth")) : \ 1523193326Sed (v) == 1 ? ND_PRINT((ndo, "MIMOPwrSave")) : \ 1524193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1525193326Sed) 1526193326Sed#define PRINT_BA_ACTION(v) (\ 1527193326Sed (v) == 0 ? ND_PRINT((ndo, "ADDBA Request")) : \ 1528193326Sed (v) == 1 ? ND_PRINT((ndo, "ADDBA Response")) : \ 1529193326Sed (v) == 2 ? ND_PRINT((ndo, "DELBA")) : \ 1530193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1531193326Sed) 1532193326Sed#define PRINT_MESHLINK_ACTION(v) (\ 1533193326Sed (v) == 0 ? ND_PRINT((ndo, "Request")) : \ 1534193326Sed (v) == 1 ? ND_PRINT((ndo, "Report")) : \ 1535193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1536193326Sed) 1537193326Sed#define PRINT_MESHPEERING_ACTION(v) (\ 1538193326Sed (v) == 0 ? ND_PRINT((ndo, "Open")) : \ 1539193326Sed (v) == 1 ? ND_PRINT((ndo, "Confirm")) : \ 1540193326Sed (v) == 2 ? ND_PRINT((ndo, "Close")) : \ 1541193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1542193326Sed) 1543193326Sed#define PRINT_MESHPATH_ACTION(v) (\ 1544193326Sed (v) == 0 ? ND_PRINT((ndo, "Request")) : \ 1545193326Sed (v) == 1 ? ND_PRINT((ndo, "Report")) : \ 1546193326Sed (v) == 2 ? ND_PRINT((ndo, "Error")) : \ 1547193326Sed (v) == 3 ? ND_PRINT((ndo, "RootAnnouncement")) : \ 1548193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1549193326Sed) 1550193326Sed 1551193326Sed#define PRINT_MESH_ACTION(v) (\ 1552193326Sed (v) == 0 ? ND_PRINT((ndo, "MeshLink")) : \ 1553193326Sed (v) == 1 ? ND_PRINT((ndo, "HWMP")) : \ 1554193326Sed (v) == 2 ? ND_PRINT((ndo, "Gate Announcement")) : \ 1555193326Sed (v) == 3 ? ND_PRINT((ndo, "Congestion Control")) : \ 1556193326Sed (v) == 4 ? ND_PRINT((ndo, "MCCA Setup Request")) : \ 1557194179Sed (v) == 5 ? ND_PRINT((ndo, "MCCA Setup Reply")) : \ 1558193326Sed (v) == 6 ? ND_PRINT((ndo, "MCCA Advertisement Request")) : \ 1559193326Sed (v) == 7 ? ND_PRINT((ndo, "MCCA Advertisement")) : \ 1560193326Sed (v) == 8 ? ND_PRINT((ndo, "MCCA Teardown")) : \ 1561193326Sed (v) == 9 ? ND_PRINT((ndo, "TBTT Adjustment Request")) : \ 1562193326Sed (v) == 10 ? ND_PRINT((ndo, "TBTT Adjustment Response")) : \ 1563193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1564193326Sed) 1565193326Sed#define PRINT_MULTIHOP_ACTION(v) (\ 1566193326Sed (v) == 0 ? ND_PRINT((ndo, "Proxy Update")) : \ 1567193326Sed (v) == 1 ? ND_PRINT((ndo, "Proxy Update Confirmation")) : \ 1568193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1569193326Sed) 1570193326Sed#define PRINT_SELFPROT_ACTION(v) (\ 1571193326Sed (v) == 1 ? ND_PRINT((ndo, "Peering Open")) : \ 1572193326Sed (v) == 2 ? ND_PRINT((ndo, "Peering Confirm")) : \ 1573193326Sed (v) == 3 ? ND_PRINT((ndo, "Peering Close")) : \ 1574193326Sed (v) == 4 ? ND_PRINT((ndo, "Group Key Inform")) : \ 1575193326Sed (v) == 5 ? ND_PRINT((ndo, "Group Key Acknowledge")) : \ 1576193326Sed ND_PRINT((ndo, "Act#%d", (v))) \ 1577193326Sed) 1578193326Sed 1579193326Sedstatic int 1580193326Sedhandle_action(netdissect_options *ndo, 1581193326Sed const uint8_t *src, const u_char *p, u_int length) 1582193326Sed{ 1583193326Sed if (!ND_TTEST2(*p, 2)) 1584193326Sed return 0; 1585193326Sed if (length < 2) 1586193326Sed return 0; 1587194179Sed if (ndo->ndo_eflag) { 1588194179Sed ND_PRINT((ndo, ": ")); 1589194179Sed } else { 1590194179Sed ND_PRINT((ndo, " (%s): ", etheraddr_string(ndo, src))); 1591194179Sed } 1592194179Sed switch (p[0]) { 1593194179Sed case 0: ND_PRINT((ndo, "Spectrum Management Act#%d", p[1])); break; 1594194179Sed case 1: ND_PRINT((ndo, "QoS Act#%d", p[1])); break; 1595193326Sed case 2: ND_PRINT((ndo, "DLS Act#%d", p[1])); break; 1596193326Sed case 3: ND_PRINT((ndo, "BA ")); PRINT_BA_ACTION(p[1]); break; 1597194179Sed case 7: ND_PRINT((ndo, "HT ")); PRINT_HT_ACTION(p[1]); break; 1598194179Sed case 13: ND_PRINT((ndo, "MeshAction ")); PRINT_MESH_ACTION(p[1]); break; 1599194179Sed case 14: 1600193326Sed ND_PRINT((ndo, "MultiohopAction ")); 1601193326Sed PRINT_MULTIHOP_ACTION(p[1]); break; 1602193326Sed case 15: 1603193326Sed ND_PRINT((ndo, "SelfprotectAction ")); 1604193326Sed PRINT_SELFPROT_ACTION(p[1]); break; 1605193326Sed case 127: ND_PRINT((ndo, "Vendor Act#%d", p[1])); break; 1606193326Sed default: 1607193326Sed ND_PRINT((ndo, "Reserved(%d) Act#%d", p[0], p[1])); 1608193326Sed break; 1609193326Sed } 1610193326Sed return 1; 1611193326Sed} 1612193326Sed 1613193326Sed 1614193326Sed/********************************************************************************* 1615193326Sed * Print Body funcs 1616193326Sed *********************************************************************************/ 1617193326Sed 1618193326Sed 1619193326Sedstatic int 1620193326Sedmgmt_body_print(netdissect_options *ndo, 1621193326Sed uint16_t fc, const uint8_t *src, const u_char *p, u_int length) 1622193326Sed{ 1623193326Sed ND_PRINT((ndo, "%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)))); 1624193326Sed 1625193326Sed /* There may be a problem w/ AP not having this bit set */ 1626193326Sed if (FC_PROTECTED(fc)) 1627193326Sed return wep_print(ndo, p); 1628193326Sed switch (FC_SUBTYPE(fc)) { 1629193326Sed case ST_ASSOC_REQUEST: 1630193326Sed return handle_assoc_request(ndo, p, length); 1631193326Sed case ST_ASSOC_RESPONSE: 1632193326Sed return handle_assoc_response(ndo, p, length); 1633193326Sed case ST_REASSOC_REQUEST: 1634193326Sed return handle_reassoc_request(ndo, p, length); 1635193326Sed case ST_REASSOC_RESPONSE: 1636193326Sed return handle_reassoc_response(ndo, p, length); 1637193326Sed case ST_PROBE_REQUEST: 1638193326Sed return handle_probe_request(ndo, p, length); 1639193326Sed case ST_PROBE_RESPONSE: 1640193326Sed return handle_probe_response(ndo, p, length); 1641193326Sed case ST_BEACON: 1642193326Sed return handle_beacon(ndo, p, length); 1643193326Sed case ST_ATIM: 1644193326Sed return handle_atim(); 1645193326Sed case ST_DISASSOC: 1646193326Sed return handle_disassoc(ndo, p, length); 1647193326Sed case ST_AUTH: 1648193326Sed return handle_auth(ndo, p, length); 1649193326Sed case ST_DEAUTH: 1650193326Sed return handle_deauth(ndo, src, p, length); 1651193326Sed case ST_ACTION: 1652193326Sed return handle_action(ndo, src, p, length); 1653193326Sed default: 1654193326Sed return 1; 1655193326Sed } 1656193326Sed} 1657193326Sed 1658193326Sed 1659193326Sed/********************************************************************************* 1660193326Sed * Handles printing all the control frame types 1661193326Sed *********************************************************************************/ 1662193326Sed 1663193326Sedstatic int 1664193326Sedctrl_body_print(netdissect_options *ndo, 1665193326Sed uint16_t fc, const u_char *p) 1666194179Sed{ 1667194179Sed ND_PRINT((ndo, "%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)))); 1668193326Sed switch (FC_SUBTYPE(fc)) { 1669193326Sed case CTRL_CONTROL_WRAPPER: 1670193326Sed /* XXX - requires special handling */ 1671193326Sed break; 1672193326Sed case CTRL_BAR: 1673193326Sed if (!ND_TTEST2(*p, CTRL_BAR_HDRLEN)) 1674193326Sed return 0; 1675194179Sed if (!ndo->ndo_eflag) 1676194179Sed ND_PRINT((ndo, " RA:%s TA:%s CTL(%x) SEQ(%u) ", 1677193326Sed etheraddr_string(ndo, ((const struct ctrl_bar_hdr_t *)p)->ra), 1678193326Sed etheraddr_string(ndo, ((const struct ctrl_bar_hdr_t *)p)->ta), 1679193326Sed EXTRACT_LE_16BITS(&(((const struct ctrl_bar_hdr_t *)p)->ctl)), 1680193326Sed EXTRACT_LE_16BITS(&(((const struct ctrl_bar_hdr_t *)p)->seq)))); 1681193326Sed break; 1682193326Sed case CTRL_BA: 1683193326Sed if (!ND_TTEST2(*p, CTRL_BA_HDRLEN)) 1684193326Sed return 0; 1685193326Sed if (!ndo->ndo_eflag) 1686193326Sed ND_PRINT((ndo, " RA:%s ", 1687193326Sed etheraddr_string(ndo, ((const struct ctrl_ba_hdr_t *)p)->ra))); 1688193326Sed break; 1689193326Sed case CTRL_PS_POLL: 1690193326Sed if (!ND_TTEST2(*p, CTRL_PS_POLL_HDRLEN)) 1691193326Sed return 0; 1692193326Sed ND_PRINT((ndo, " AID(%x)", 1693193326Sed EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_hdr_t *)p)->aid)))); 1694193326Sed break; 1695193326Sed case CTRL_RTS: 1696193326Sed if (!ND_TTEST2(*p, CTRL_RTS_HDRLEN)) 1697193326Sed return 0; 1698193326Sed if (!ndo->ndo_eflag) 1699193326Sed ND_PRINT((ndo, " TA:%s ", 1700193326Sed etheraddr_string(ndo, ((const struct ctrl_rts_hdr_t *)p)->ta))); 1701193326Sed break; 1702193326Sed case CTRL_CTS: 1703193326Sed if (!ND_TTEST2(*p, CTRL_CTS_HDRLEN)) 1704193326Sed return 0; 1705193326Sed if (!ndo->ndo_eflag) 1706193326Sed ND_PRINT((ndo, " RA:%s ", 1707193326Sed etheraddr_string(ndo, ((const struct ctrl_cts_hdr_t *)p)->ra))); 1708193326Sed break; 1709193326Sed case CTRL_ACK: 1710193326Sed if (!ND_TTEST2(*p, CTRL_ACK_HDRLEN)) 1711193326Sed return 0; 1712193326Sed if (!ndo->ndo_eflag) 1713193326Sed ND_PRINT((ndo, " RA:%s ", 1714194179Sed etheraddr_string(ndo, ((const struct ctrl_ack_hdr_t *)p)->ra))); 1715194179Sed break; 1716193326Sed case CTRL_CF_END: 1717193326Sed if (!ND_TTEST2(*p, CTRL_END_HDRLEN)) 1718193326Sed return 0; 1719193326Sed if (!ndo->ndo_eflag) 1720193326Sed ND_PRINT((ndo, " RA:%s ", 1721193326Sed etheraddr_string(ndo, ((const struct ctrl_end_hdr_t *)p)->ra))); 1722193326Sed break; 1723193326Sed case CTRL_END_ACK: 1724193326Sed if (!ND_TTEST2(*p, CTRL_END_ACK_HDRLEN)) 1725193326Sed return 0; 1726193326Sed if (!ndo->ndo_eflag) 1727193326Sed ND_PRINT((ndo, " RA:%s ", 1728193326Sed etheraddr_string(ndo, ((const struct ctrl_end_ack_hdr_t *)p)->ra))); 1729193326Sed break; 1730193326Sed } 1731193326Sed return 1; 1732193326Sed} 1733193326Sed 1734193326Sed/* 1735193326Sed * Data Frame - Address field contents 1736193326Sed * 1737193326Sed * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4 1738193326Sed * 0 | 0 | DA | SA | BSSID | n/a 1739193326Sed * 0 | 1 | DA | BSSID | SA | n/a 1740193326Sed * 1 | 0 | BSSID | SA | DA | n/a 1741193326Sed * 1 | 1 | RA | TA | DA | SA 1742193326Sed */ 1743193326Sed 1744193326Sed/* 1745193326Sed * Function to get source and destination MAC addresses for a data frame. 1746193326Sed */ 1747193326Sedstatic void 1748193326Sedget_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp, 1749193326Sed const uint8_t **dstp) 1750193326Sed{ 1751193326Sed#define ADDR1 (p + 4) 1752193326Sed#define ADDR2 (p + 10) 1753193326Sed#define ADDR3 (p + 16) 1754193326Sed#define ADDR4 (p + 24) 1755194179Sed 1756194179Sed if (!FC_TO_DS(fc)) { 1757193326Sed if (!FC_FROM_DS(fc)) { 1758193326Sed /* not To DS and not From DS */ 1759193326Sed *srcp = ADDR2; 1760193326Sed *dstp = ADDR1; 1761193326Sed } else { 1762193326Sed /* not To DS and From DS */ 1763193326Sed *srcp = ADDR3; 1764193326Sed *dstp = ADDR1; 1765193326Sed } 1766193326Sed } else { 1767193326Sed if (!FC_FROM_DS(fc)) { 1768193326Sed /* From DS and not To DS */ 1769193326Sed *srcp = ADDR2; 1770193326Sed *dstp = ADDR3; 1771193326Sed } else { 1772193326Sed /* To DS and From DS */ 1773193326Sed *srcp = ADDR4; 1774193326Sed *dstp = ADDR3; 1775193326Sed } 1776193326Sed } 1777193326Sed 1778193326Sed#undef ADDR1 1779193326Sed#undef ADDR2 1780193326Sed#undef ADDR3 1781193326Sed#undef ADDR4 1782193326Sed} 1783193326Sed 1784194179Sedstatic void 1785194179Sedget_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp) 1786193326Sed{ 1787193326Sed const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 1788193326Sed 1789193326Sed if (srcp != NULL) 1790193326Sed *srcp = hp->sa; 1791193326Sed if (dstp != NULL) 1792193326Sed *dstp = hp->da; 1793193326Sed} 1794193326Sed 1795193326Sed/* 1796193326Sed * Print Header funcs 1797193326Sed */ 1798193326Sed 1799193326Sedstatic void 1800193326Seddata_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) 1801193326Sed{ 1802193326Sed u_int subtype = FC_SUBTYPE(fc); 1803193326Sed 1804193326Sed if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) || 1805193326Sed DATA_FRAME_IS_QOS(subtype)) { 1806194179Sed ND_PRINT((ndo, "CF ")); 1807194179Sed if (DATA_FRAME_IS_CF_ACK(subtype)) { 1808194179Sed if (DATA_FRAME_IS_CF_POLL(subtype)) 1809194179Sed ND_PRINT((ndo, "Ack/Poll")); 1810194179Sed else 1811194179Sed ND_PRINT((ndo, "Ack")); 1812193326Sed } else { 1813193326Sed if (DATA_FRAME_IS_CF_POLL(subtype)) 1814193326Sed ND_PRINT((ndo, "Poll")); 1815193326Sed } 1816193326Sed if (DATA_FRAME_IS_QOS(subtype)) 1817193326Sed ND_PRINT((ndo, "+QoS")); 1818193326Sed ND_PRINT((ndo, " ")); 1819193326Sed } 1820193326Sed 1821193326Sed#define ADDR1 (p + 4) 1822193326Sed#define ADDR2 (p + 10) 1823193326Sed#define ADDR3 (p + 16) 1824193326Sed#define ADDR4 (p + 24) 1825193326Sed 1826193326Sed if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) { 1827193326Sed ND_PRINT((ndo, "DA:%s SA:%s BSSID:%s ", 1828193326Sed etheraddr_string(ndo, ADDR1), etheraddr_string(ndo, ADDR2), 1829193326Sed etheraddr_string(ndo, ADDR3))); 1830193326Sed } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) { 1831193326Sed ND_PRINT((ndo, "DA:%s BSSID:%s SA:%s ", 1832193326Sed etheraddr_string(ndo, ADDR1), etheraddr_string(ndo, ADDR2), 1833193326Sed etheraddr_string(ndo, ADDR3))); 1834193326Sed } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) { 1835193326Sed ND_PRINT((ndo, "BSSID:%s SA:%s DA:%s ", 1836193326Sed etheraddr_string(ndo, ADDR1), etheraddr_string(ndo, ADDR2), 1837193326Sed etheraddr_string(ndo, ADDR3))); 1838193326Sed } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { 1839193326Sed ND_PRINT((ndo, "RA:%s TA:%s DA:%s SA:%s ", 1840193326Sed etheraddr_string(ndo, ADDR1), etheraddr_string(ndo, ADDR2), 1841193326Sed etheraddr_string(ndo, ADDR3), etheraddr_string(ndo, ADDR4))); 1842193326Sed } 1843193326Sed 1844193326Sed#undef ADDR1 1845193326Sed#undef ADDR2 1846193326Sed#undef ADDR3 1847193326Sed#undef ADDR4 1848193326Sed} 1849193326Sed 1850193326Sedstatic void 1851193326Sedmgmt_header_print(netdissect_options *ndo, const u_char *p) 1852193326Sed{ 1853193326Sed const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 1854193326Sed 1855193326Sed ND_PRINT((ndo, "BSSID:%s DA:%s SA:%s ", 1856193326Sed etheraddr_string(ndo, (hp)->bssid), etheraddr_string(ndo, (hp)->da), 1857193326Sed etheraddr_string(ndo, (hp)->sa))); 1858193326Sed} 1859193326Sed 1860193326Sedstatic void 1861193326Sedctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) 1862193326Sed{ 1863193326Sed switch (FC_SUBTYPE(fc)) { 1864193326Sed case CTRL_BAR: 1865193326Sed ND_PRINT((ndo, " RA:%s TA:%s CTL(%x) SEQ(%u) ", 1866193326Sed etheraddr_string(ndo, ((const struct ctrl_bar_hdr_t *)p)->ra), 1867193326Sed etheraddr_string(ndo, ((const struct ctrl_bar_hdr_t *)p)->ta), 1868193326Sed EXTRACT_LE_16BITS(&(((const struct ctrl_bar_hdr_t *)p)->ctl)), 1869193326Sed EXTRACT_LE_16BITS(&(((const struct ctrl_bar_hdr_t *)p)->seq)))); 1870193326Sed break; 1871193326Sed case CTRL_BA: 1872193326Sed ND_PRINT((ndo, "RA:%s ", 1873193326Sed etheraddr_string(ndo, ((const struct ctrl_ba_hdr_t *)p)->ra))); 1874193326Sed break; 1875193326Sed case CTRL_PS_POLL: 1876193326Sed ND_PRINT((ndo, "BSSID:%s TA:%s ", 1877193326Sed etheraddr_string(ndo, ((const struct ctrl_ps_poll_hdr_t *)p)->bssid), 1878193326Sed etheraddr_string(ndo, ((const struct ctrl_ps_poll_hdr_t *)p)->ta))); 1879193326Sed break; 1880193326Sed case CTRL_RTS: 1881193326Sed ND_PRINT((ndo, "RA:%s TA:%s ", 1882193326Sed etheraddr_string(ndo, ((const struct ctrl_rts_hdr_t *)p)->ra), 1883193326Sed etheraddr_string(ndo, ((const struct ctrl_rts_hdr_t *)p)->ta))); 1884193326Sed break; 1885193326Sed case CTRL_CTS: 1886193326Sed ND_PRINT((ndo, "RA:%s ", 1887193326Sed etheraddr_string(ndo, ((const struct ctrl_cts_hdr_t *)p)->ra))); 1888193326Sed break; 1889193326Sed case CTRL_ACK: 1890193326Sed ND_PRINT((ndo, "RA:%s ", 1891193326Sed etheraddr_string(ndo, ((const struct ctrl_ack_hdr_t *)p)->ra))); 1892193326Sed break; 1893193326Sed case CTRL_CF_END: 1894193326Sed ND_PRINT((ndo, "RA:%s BSSID:%s ", 1895193326Sed etheraddr_string(ndo, ((const struct ctrl_end_hdr_t *)p)->ra), 1896193326Sed etheraddr_string(ndo, ((const struct ctrl_end_hdr_t *)p)->bssid))); 1897193326Sed break; 1898193326Sed case CTRL_END_ACK: 1899193326Sed ND_PRINT((ndo, "RA:%s BSSID:%s ", 1900193326Sed etheraddr_string(ndo, ((const struct ctrl_end_ack_hdr_t *)p)->ra), 1901193326Sed etheraddr_string(ndo, ((const struct ctrl_end_ack_hdr_t *)p)->bssid))); 1902193326Sed break; 1903193326Sed default: 1904193326Sed /* We shouldn't get here - we should already have quit */ 1905193326Sed break; 1906193326Sed } 1907193326Sed} 1908193326Sed 1909193326Sedstatic int 1910193326Sedextract_header_length(netdissect_options *ndo, 1911193326Sed uint16_t fc) 1912193326Sed{ 1913193326Sed int len; 1914193326Sed 1915193326Sed switch (FC_TYPE(fc)) { 1916193326Sed case T_MGMT: 1917193326Sed return MGMT_HDRLEN; 1918193326Sed case T_CTRL: 1919193326Sed switch (FC_SUBTYPE(fc)) { 1920193326Sed case CTRL_CONTROL_WRAPPER: 1921193326Sed return CTRL_CONTROL_WRAPPER_HDRLEN; 1922193326Sed case CTRL_BAR: 1923193326Sed return CTRL_BAR_HDRLEN; 1924193326Sed case CTRL_BA: 1925193326Sed return CTRL_BA_HDRLEN; 1926193326Sed case CTRL_PS_POLL: 1927193326Sed return CTRL_PS_POLL_HDRLEN; 1928193326Sed case CTRL_RTS: 1929193326Sed return CTRL_RTS_HDRLEN; 1930193326Sed case CTRL_CTS: 1931193326Sed return CTRL_CTS_HDRLEN; 1932193326Sed case CTRL_ACK: 1933193326Sed return CTRL_ACK_HDRLEN; 1934193326Sed case CTRL_CF_END: 1935193326Sed return CTRL_END_HDRLEN; 1936193326Sed case CTRL_END_ACK: 1937193326Sed return CTRL_END_ACK_HDRLEN; 1938193326Sed default: 1939193326Sed ND_PRINT((ndo, "unknown 802.11 ctrl frame subtype (%d)", FC_SUBTYPE(fc))); 1940193326Sed return 0; 1941193326Sed } 1942193326Sed case T_DATA: 1943193326Sed len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24; 1944193326Sed if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) 1945193326Sed len += 2; 1946193326Sed return len; 1947193326Sed default: 1948193326Sed ND_PRINT((ndo, "unknown 802.11 frame type (%d)", FC_TYPE(fc))); 1949193326Sed return 0; 1950193326Sed } 1951193326Sed} 1952193326Sed 1953193326Sedstatic int 1954193326Sedextract_mesh_header_length(const u_char *p) 1955193326Sed{ 1956193326Sed return (p[0] &~ 3) ? 0 : 6*(1 + (p[0] & 3)); 1957193326Sed} 1958193326Sed 1959193326Sed/* 1960193326Sed * Print the 802.11 MAC header. 1961193326Sed */ 1962193326Sedstatic void 1963193326Sedieee_802_11_hdr_print(netdissect_options *ndo, 1964193326Sed uint16_t fc, const u_char *p, u_int hdrlen, 1965193326Sed u_int meshdrlen) 1966193326Sed{ 1967193326Sed if (ndo->ndo_vflag) { 1968193326Sed if (FC_MORE_DATA(fc)) 1969193326Sed ND_PRINT((ndo, "More Data ")); 1970193326Sed if (FC_MORE_FLAG(fc)) 1971193326Sed ND_PRINT((ndo, "More Fragments ")); 1972193326Sed if (FC_POWER_MGMT(fc)) 1973193326Sed ND_PRINT((ndo, "Pwr Mgmt ")); 1974193326Sed if (FC_RETRY(fc)) 1975193326Sed ND_PRINT((ndo, "Retry ")); 1976193326Sed if (FC_ORDER(fc)) 1977193326Sed ND_PRINT((ndo, "Strictly Ordered ")); 1978193326Sed if (FC_PROTECTED(fc)) 1979193326Sed ND_PRINT((ndo, "Protected ")); 1980193326Sed if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL) 1981193326Sed ND_PRINT((ndo, "%dus ", 1982193326Sed EXTRACT_LE_16BITS( 1983193326Sed &((const struct mgmt_header_t *)p)->duration))); 1984193326Sed } 1985193326Sed if (meshdrlen != 0) { 1986193326Sed const struct meshcntl_t *mc = 1987193326Sed (const struct meshcntl_t *)&p[hdrlen - meshdrlen]; 1988193326Sed int ae = mc->flags & 3; 1989193326Sed 1990193326Sed ND_PRINT((ndo, "MeshData (AE %d TTL %u seq %u", ae, mc->ttl, 1991193326Sed EXTRACT_LE_32BITS(mc->seq))); 1992193326Sed if (ae > 0) 1993193326Sed ND_PRINT((ndo, " A4:%s", etheraddr_string(ndo, mc->addr4))); 1994193326Sed if (ae > 1) 1995193326Sed ND_PRINT((ndo, " A5:%s", etheraddr_string(ndo, mc->addr5))); 1996193326Sed if (ae > 2) 1997193326Sed ND_PRINT((ndo, " A6:%s", etheraddr_string(ndo, mc->addr6))); 1998193326Sed ND_PRINT((ndo, ") ")); 1999193326Sed } 2000193326Sed 2001193326Sed switch (FC_TYPE(fc)) { 2002193326Sed case T_MGMT: 2003193326Sed mgmt_header_print(ndo, p); 2004193326Sed break; 2005193326Sed case T_CTRL: 2006194179Sed ctrl_header_print(ndo, fc, p); 2007193326Sed break; 2008193326Sed case T_DATA: 2009193326Sed data_header_print(ndo, fc, p); 2010193326Sed break; 2011193326Sed default: 2012193326Sed break; 2013193326Sed } 2014193326Sed} 2015193326Sed 2016193326Sed#ifndef roundup2 2017193326Sed#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 2018193326Sed#endif 2019193326Sed 2020193326Sedstatic const char tstr[] = "[|802.11]"; 2021193326Sed 2022194179Sedstatic u_int 2023193326Sedieee802_11_print(netdissect_options *ndo, 2024194179Sed const u_char *p, u_int length, u_int orig_caplen, int pad, 2025193326Sed u_int fcslen) 2026193326Sed{ 2027193326Sed uint16_t fc; 2028193326Sed u_int caplen, hdrlen, meshdrlen; 2029193326Sed struct lladdr_info src, dst; 2030193326Sed int llc_hdrlen; 2031193326Sed 2032193326Sed caplen = orig_caplen; 2033193326Sed /* Remove FCS, if present */ 2034193326Sed if (length < fcslen) { 2035193326Sed ND_PRINT((ndo, "%s", tstr)); 2036193326Sed return caplen; 2037193326Sed } 2038193326Sed length -= fcslen; 2039194179Sed if (caplen > length) { 2040193326Sed /* Amount of FCS in actual packet data, if any */ 2041193326Sed fcslen = caplen - length; 2042193326Sed caplen -= fcslen; 2043194179Sed ndo->ndo_snapend -= fcslen; 2044194179Sed } 2045193326Sed 2046193326Sed if (caplen < IEEE802_11_FC_LEN) { 2047193326Sed ND_PRINT((ndo, "%s", tstr)); 2048193326Sed return orig_caplen; 2049193326Sed } 2050193326Sed 2051193326Sed fc = EXTRACT_LE_16BITS(p); 2052193326Sed hdrlen = extract_header_length(ndo, fc); 2053193326Sed if (hdrlen == 0) { 2054193326Sed /* Unknown frame type or control frame subtype; quit. */ 2055193326Sed return (0); 2056193326Sed } 2057193326Sed if (pad) 2058194179Sed hdrlen = roundup2(hdrlen, 4); 2059193326Sed if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA && 2060193326Sed DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) { 2061193326Sed if (caplen < hdrlen + 1) { 2062194179Sed ND_PRINT((ndo, "%s", tstr)); 2063193326Sed return hdrlen; 2064193326Sed } 2065193326Sed meshdrlen = extract_mesh_header_length(p+hdrlen); 2066193326Sed hdrlen += meshdrlen; 2067193326Sed } else 2068194179Sed meshdrlen = 0; 2069193326Sed 2070193326Sed if (caplen < hdrlen) { 2071193326Sed ND_PRINT((ndo, "%s", tstr)); 2072193326Sed return hdrlen; 2073193326Sed } 2074193326Sed 2075193326Sed if (ndo->ndo_eflag) 2076193326Sed ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen); 2077193326Sed 2078193326Sed /* 2079193326Sed * Go past the 802.11 header. 2080193326Sed */ 2081194179Sed length -= hdrlen; 2082194179Sed caplen -= hdrlen; 2083194179Sed p += hdrlen; 2084194179Sed 2085194179Sed src.addr_string = etheraddr_string; 2086194179Sed dst.addr_string = etheraddr_string; 2087194179Sed switch (FC_TYPE(fc)) { 2088194179Sed case T_MGMT: 2089194179Sed get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr); 2090194179Sed if (!mgmt_body_print(ndo, fc, src.addr, p, length)) { 2091194179Sed ND_PRINT((ndo, "%s", tstr)); 2092194179Sed return hdrlen; 2093194179Sed } 2094194179Sed break; 2095194179Sed case T_CTRL: 2096194179Sed if (!ctrl_body_print(ndo, fc, p - hdrlen)) { 2097194179Sed ND_PRINT((ndo, "%s", tstr)); 2098194179Sed return hdrlen; 2099194179Sed } 2100194179Sed break; 2101194179Sed case T_DATA: 2102194179Sed if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc))) 2103194179Sed return hdrlen; /* no-data frame */ 2104194179Sed /* There may be a problem w/ AP not having this bit set */ 2105194179Sed if (FC_PROTECTED(fc)) { 2106194179Sed ND_PRINT((ndo, "Data")); 2107194179Sed if (!wep_print(ndo, p)) { 2108194179Sed ND_PRINT((ndo, "%s", tstr)); 2109194179Sed return hdrlen; 2110194179Sed } 2111194179Sed } else { 2112194179Sed get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr); 2113194179Sed llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); 2114194179Sed if (llc_hdrlen < 0) { 2115194179Sed /* 2116194179Sed * Some kinds of LLC packet we cannot 2117194179Sed * handle intelligently 2118194179Sed */ 2119194179Sed if (!ndo->ndo_suppress_default_print) 2120194179Sed ND_DEFAULTPRINT(p, caplen); 2121194179Sed llc_hdrlen = -llc_hdrlen; 2122194179Sed } 2123194179Sed hdrlen += llc_hdrlen; 2124194179Sed } 2125194179Sed break; 2126194179Sed default: 2127194179Sed /* We shouldn't get here - we should already have quit */ 2128194179Sed break; 2129194179Sed } 2130194179Sed 2131194179Sed return hdrlen; 2132194179Sed} 2133194179Sed 2134194179Sed/* 2135194179Sed * This is the top level routine of the printer. 'p' points 2136194179Sed * to the 802.11 header of the packet, 'h->ts' is the timestamp, 2137194179Sed * 'h->len' is the length of the packet off the wire, and 'h->caplen' 2138194179Sed * is the number of bytes actually captured. 2139194179Sed */ 2140194179Sedu_int 2141194179Sedieee802_11_if_print(netdissect_options *ndo, 2142194179Sed const struct pcap_pkthdr *h, const u_char *p) 2143194179Sed{ 2144194179Sed return ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0); 2145194179Sed} 2146194179Sed 2147194179Sed 2148194179Sed/* $FreeBSD: stable/11/contrib/tcpdump/print-802_11.c 276788 2015-01-07 19:55:18Z delphij $ */ 2149194179Sed/* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */ 2150194179Sed 2151194179Sed/*- 2152194179Sed * Copyright (c) 2003, 2004 David Young. All rights reserved. 2153194179Sed * 2154194179Sed * Redistribution and use in source and binary forms, with or without 2155194179Sed * modification, are permitted provided that the following conditions 2156194179Sed * are met: 2157194179Sed * 1. Redistributions of source code must retain the above copyright 2158194179Sed * notice, this list of conditions and the following disclaimer. 2159194179Sed * 2. Redistributions in binary form must reproduce the above copyright 2160194179Sed * notice, this list of conditions and the following disclaimer in the 2161194179Sed * documentation and/or other materials provided with the distribution. 2162194179Sed * 3. The name of David Young may not be used to endorse or promote 2163194179Sed * products derived from this software without specific prior 2164194179Sed * written permission. 2165194179Sed * 2166194179Sed * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY 2167194179Sed * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2168194179Sed * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 2169194179Sed * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID 2170194179Sed * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2171194179Sed * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2172194179Sed * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2173194179Sed * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2174194179Sed * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2175194179Sed * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2176194179Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 2177194179Sed * OF SUCH DAMAGE. 2178194179Sed */ 2179194179Sed 2180194179Sed/* A generic radio capture format is desirable. It must be 2181194179Sed * rigidly defined (e.g., units for fields should be given), 2182194179Sed * and easily extensible. 2183194179Sed * 2184194179Sed * The following is an extensible radio capture format. It is 2185194179Sed * based on a bitmap indicating which fields are present. 2186194179Sed * 2187194179Sed * I am trying to describe precisely what the application programmer 2188194179Sed * should expect in the following, and for that reason I tell the 2189194179Sed * units and origin of each measurement (where it applies), or else I 2190194179Sed * use sufficiently weaselly language ("is a monotonically nondecreasing 2191194179Sed * function of...") that I cannot set false expectations for lawyerly 2192194179Sed * readers. 2193194179Sed */ 2194194179Sed 2195194179Sed/* 2196194179Sed * The radio capture header precedes the 802.11 header. 2197194179Sed * 2198194179Sed * Note well: all radiotap fields are little-endian. 2199194179Sed */ 2200194179Sedstruct ieee80211_radiotap_header { 2201193326Sed uint8_t it_version; /* Version 0. Only increases 2202193326Sed * for drastic changes, 2203193326Sed * introduction of compatible 2204193326Sed * new fields does not count. 2205193326Sed */ 2206193326Sed uint8_t it_pad; 2207193326Sed uint16_t it_len; /* length of the whole 2208193326Sed * header in bytes, including 2209193326Sed * it_version, it_pad, 2210193326Sed * it_len, and data fields. 2211193326Sed */ 2212193326Sed uint32_t it_present; /* A bitmap telling which 2213193326Sed * fields are present. Set bit 31 2214193326Sed * (0x80000000) to extend the 2215193326Sed * bitmap by another 32 bits. 2216193326Sed * Additional extensions are made 2217193326Sed * by setting bit 31. 2218193326Sed */ 2219193326Sed}; 2220193326Sed 2221193326Sed/* Name Data type Units 2222193326Sed * ---- --------- ----- 2223193326Sed * 2224193326Sed * IEEE80211_RADIOTAP_TSFT uint64_t microseconds 2225193326Sed * 2226193326Sed * Value in microseconds of the MAC's 64-bit 802.11 Time 2227193326Sed * Synchronization Function timer when the first bit of the 2228193326Sed * MPDU arrived at the MAC. For received frames, only. 2229193326Sed * 2230193326Sed * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap 2231193326Sed * 2232193326Sed * Tx/Rx frequency in MHz, followed by flags (see below). 2233193326Sed * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to 2234193326Sed * represent an HT channel as there is not enough room in 2235193326Sed * the flags word. 2236193326Sed * 2237194179Sed * IEEE80211_RADIOTAP_FHSS uint16_t see below 2238193326Sed * 2239194179Sed * For frequency-hopping radios, the hop set (first byte) 2240194179Sed * and pattern (second byte). 2241194179Sed * 2242194179Sed * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index 2243194179Sed * 2244194179Sed * Tx/Rx data rate. If bit 0x80 is set then it represents an 2245194179Sed * an MCS index and not an IEEE rate. 2246194179Sed * 2247194179Sed * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from 2248194179Sed * one milliwatt (dBm) 2249194179Sed * 2250194179Sed * RF signal power at the antenna, decibel difference from 2251194179Sed * one milliwatt. 2252194179Sed * 2253194179Sed * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from 2254194179Sed * one milliwatt (dBm) 2255194179Sed * 2256194179Sed * RF noise power at the antenna, decibel difference from one 2257194179Sed * milliwatt. 2258194179Sed * 2259194179Sed * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) 2260194179Sed * 2261194179Sed * RF signal power at the antenna, decibel difference from an 2262194179Sed * arbitrary, fixed reference. 2263194179Sed * 2264194179Sed * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) 2265194179Sed * 2266194179Sed * RF noise power at the antenna, decibel difference from an 2267194179Sed * arbitrary, fixed reference point. 2268194179Sed * 2269194179Sed * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless 2270194179Sed * 2271194179Sed * Quality of Barker code lock. Unitless. Monotonically 2272193326Sed * nondecreasing with "better" lock strength. Called "Signal 2273193326Sed * Quality" in datasheets. (Is there a standard way to measure 2274193326Sed * this?) 2275193326Sed * 2276193326Sed * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless 2277193326Sed * 2278193326Sed * Transmit power expressed as unitless distance from max 2279193326Sed * power set at factory calibration. 0 is max power. 2280193326Sed * Monotonically nondecreasing with lower power levels. 2281193326Sed * 2282193326Sed * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) 2283193326Sed * 2284193326Sed * Transmit power expressed as decibel distance from max power 2285193326Sed * set at factory calibration. 0 is max power. Monotonically 2286193326Sed * nondecreasing with lower power levels. 2287193326Sed * 2288193326Sed * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from 2289193326Sed * one milliwatt (dBm) 2290193326Sed * 2291193326Sed * Transmit power expressed as dBm (decibels from a 1 milliwatt 2292193326Sed * reference). This is the absolute power level measured at 2293193326Sed * the antenna port. 2294193326Sed * 2295193326Sed * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap 2296193326Sed * 2297193326Sed * Properties of transmitted and received frames. See flags 2298193326Sed * defined below. 2299193326Sed * 2300193326Sed * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index 2301193576Sed * 2302193326Sed * Unitless indication of the Rx/Tx antenna for this packet. 2303194179Sed * The first antenna is antenna 0. 2304193326Sed * 2305193326Sed * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap 2306193326Sed * 2307194613Sed * Properties of received frames. See flags defined below. 2308193326Sed * 2309193326Sed * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap 2310193326Sed * uint16_t MHz 2311193326Sed * uint8_t channel number 2312193326Sed * uint8_t .5 dBm 2313193326Sed * 2314194179Sed * Extended channel specification: flags (see below) followed by 2315194179Sed * frequency in MHz, the corresponding IEEE channel number, and 2316194179Sed * finally the maximum regulatory transmit power cap in .5 dBm 2317194179Sed * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL 2318194179Sed * and only one of the two should be present. 2319194179Sed * 2320194179Sed * IEEE80211_RADIOTAP_MCS uint8_t known 2321194179Sed * uint8_t flags 2322194179Sed * uint8_t mcs 2323194179Sed * 2324194179Sed * Bitset indicating which fields have known values, followed 2325194179Sed * by bitset of flag values, followed by the MCS rate index as 2326194179Sed * in IEEE 802.11n. 2327194179Sed * 2328194179Sed * 2329194179Sed * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless 2330194179Sed * 2331194179Sed * Contains the AMPDU information for the subframe. 2332194179Sed * 2333194179Sed * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 2334194179Sed * 2335194179Sed * Contains VHT information about this frame. 2336194179Sed * 2337194179Sed * IEEE80211_RADIOTAP_VENDOR_NAMESPACE 2338194179Sed * uint8_t OUI[3] 2339193326Sed * uint8_t subspace 2340193576Sed * uint16_t length 2341193576Sed * 2342193576Sed * The Vendor Namespace Field contains three sub-fields. The first 2343194179Sed * sub-field is 3 bytes long. It contains the vendor's IEEE 802 2344193326Sed * Organizationally Unique Identifier (OUI). The fourth byte is a 2345193576Sed * vendor-specific "namespace selector." 2346193576Sed * 2347193576Sed */ 2348193326Sedenum ieee80211_radiotap_type { 2349193326Sed IEEE80211_RADIOTAP_TSFT = 0, 2350193326Sed IEEE80211_RADIOTAP_FLAGS = 1, 2351193326Sed IEEE80211_RADIOTAP_RATE = 2, 2352193326Sed IEEE80211_RADIOTAP_CHANNEL = 3, 2353193326Sed IEEE80211_RADIOTAP_FHSS = 4, 2354193326Sed IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, 2355193326Sed IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, 2356193326Sed IEEE80211_RADIOTAP_LOCK_QUALITY = 7, 2357193326Sed IEEE80211_RADIOTAP_TX_ATTENUATION = 8, 2358193326Sed IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, 2359193326Sed IEEE80211_RADIOTAP_DBM_TX_POWER = 10, 2360193326Sed IEEE80211_RADIOTAP_ANTENNA = 11, 2361193326Sed IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, 2362193326Sed IEEE80211_RADIOTAP_DB_ANTNOISE = 13, 2363193326Sed IEEE80211_RADIOTAP_RX_FLAGS = 14, 2364193326Sed /* NB: gap for netbsd definitions */ 2365193326Sed IEEE80211_RADIOTAP_XCHANNEL = 18, 2366194179Sed IEEE80211_RADIOTAP_MCS = 19, 2367193326Sed IEEE80211_RADIOTAP_AMPDU_STATUS = 20, 2368193326Sed IEEE80211_RADIOTAP_VHT = 21, 2369193326Sed IEEE80211_RADIOTAP_NAMESPACE = 29, 2370193326Sed IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, 2371193326Sed IEEE80211_RADIOTAP_EXT = 31 2372193326Sed}; 2373193326Sed 2374193326Sed/* channel attributes */ 2375193326Sed#define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */ 2376193326Sed#define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */ 2377193326Sed#define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */ 2378193326Sed#define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */ 2379193326Sed#define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */ 2380193326Sed#define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */ 2381193326Sed#define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */ 2382193326Sed#define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */ 2383193326Sed#define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */ 2384193326Sed#define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */ 2385193326Sed#define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */ 2386193326Sed#define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */ 2387193576Sed#define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */ 2388193576Sed#define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */ 2389193576Sed#define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */ 2390193576Sed 2391193576Sed/* Useful combinations of channel characteristics, borrowed from Ethereal */ 2392193326Sed#define IEEE80211_CHAN_A \ 2393193326Sed (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 2394193326Sed#define IEEE80211_CHAN_B \ 2395193326Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 2396193326Sed#define IEEE80211_CHAN_G \ 2397193326Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 2398193326Sed#define IEEE80211_CHAN_TA \ 2399193326Sed (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) 2400194179Sed#define IEEE80211_CHAN_TG \ 2401194179Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO) 2402194179Sed 2403194179Sed 2404194179Sed/* For IEEE80211_RADIOTAP_FLAGS */ 2405194179Sed#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received 2406194179Sed * during CFP 2407194179Sed */ 2408194179Sed#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received 2409194179Sed * with short 2410194179Sed * preamble 2411194179Sed */ 2412194179Sed#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received 2413194179Sed * with WEP encryption 2414194179Sed */ 2415194179Sed#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received 2416194179Sed * with fragmentation 2417194179Sed */ 2418194179Sed#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ 2419194179Sed#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between 2420194179Sed * 802.11 header and payload 2421194179Sed * (to 32-bit boundary) 2422194179Sed */ 2423194179Sed#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */ 2424194179Sed 2425194179Sed/* For IEEE80211_RADIOTAP_RX_FLAGS */ 2426194179Sed#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ 2427194179Sed#define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */ 2428194179Sed 2429194179Sed/* For IEEE80211_RADIOTAP_MCS known */ 2430194179Sed#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01 2431194179Sed#define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */ 2432193326Sed#define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04 2433193326Sed#define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08 2434193326Sed#define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10 2435193326Sed#define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20 2436193326Sed#define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40 2437193326Sed#define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80 2438193326Sed 2439193576Sed/* For IEEE80211_RADIOTAP_MCS flags */ 2440193576Sed#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03 2441193326Sed#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0 2442193326Sed#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1 2443193326Sed#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2 2444193326Sed#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3 2445193326Sed#define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */ 2446193326Sed#define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08 2447193326Sed#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 2448193326Sed#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 2449193326Sed#define IEEE80211_RADIOTAP_MCS_STBC_1 1 2450193326Sed#define IEEE80211_RADIOTAP_MCS_STBC_2 2 2451193326Sed#define IEEE80211_RADIOTAP_MCS_STBC_3 3 2452193326Sed#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 2453193326Sed#define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80 2454193326Sed 2455193326Sed/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ 2456193326Sed#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 2457193326Sed#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 2458193326Sed#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 2459193326Sed#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 2460193326Sed#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 2461193326Sed#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 2462193326Sed 2463193326Sed/* For IEEE80211_RADIOTAP_VHT known */ 2464193326Sed#define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001 2465193326Sed#define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002 2466193326Sed#define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004 2467193326Sed#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008 2468193326Sed#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010 2469193326Sed#define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020 2470193326Sed#define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040 2471193326Sed#define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080 2472193326Sed#define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100 2473193326Sed 2474193326Sed/* For IEEE80211_RADIOTAP_VHT flags */ 2475193326Sed#define IEEE80211_RADIOTAP_VHT_STBC 0x01 2476193326Sed#define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02 2477193326Sed#define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04 2478194179Sed#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08 2479193326Sed#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10 2480193326Sed#define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20 2481193326Sed 2482193326Sed#define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f 2483193326Sed 2484193326Sed#define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f 2485193326Sed#define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0 2486193326Sed#define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4 2487193326Sed 2488193326Sed#define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01 2489193326Sed 2490193326Sed#define IEEE80211_CHAN_FHSS \ 2491193326Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) 2492193326Sed#define IEEE80211_CHAN_A \ 2493193326Sed (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 2494193326Sed#define IEEE80211_CHAN_B \ 2495193326Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) 2496193326Sed#define IEEE80211_CHAN_PUREG \ 2497193326Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) 2498193326Sed#define IEEE80211_CHAN_G \ 2499193326Sed (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) 2500193326Sed 2501193326Sed#define IS_CHAN_FHSS(flags) \ 2502193326Sed ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) 2503193326Sed#define IS_CHAN_A(flags) \ 2504193326Sed ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) 2505193326Sed#define IS_CHAN_B(flags) \ 2506193326Sed ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) 2507193326Sed#define IS_CHAN_PUREG(flags) \ 2508193326Sed ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) 2509193326Sed#define IS_CHAN_G(flags) \ 2510193326Sed ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) 2511193326Sed#define IS_CHAN_ANYG(flags) \ 2512193326Sed (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags)) 2513193326Sed 2514193326Sedstatic void 2515193326Sedprint_chaninfo(netdissect_options *ndo, 2516193326Sed uint16_t freq, int flags, int presentflags) 2517193326Sed{ 2518193326Sed ND_PRINT((ndo, "%u MHz", freq)); 2519193326Sed if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) { 2520193326Sed /* 2521193326Sed * We have the MCS field, so this is 11n, regardless 2522193326Sed * of what the channel flags say. 2523193326Sed */ 2524193326Sed ND_PRINT((ndo, " 11n")); 2525193326Sed } else { 2526193326Sed if (IS_CHAN_FHSS(flags)) 2527193326Sed ND_PRINT((ndo, " FHSS")); 2528193326Sed if (IS_CHAN_A(flags)) { 2529193326Sed if (flags & IEEE80211_CHAN_HALF) 2530193326Sed ND_PRINT((ndo, " 11a/10Mhz")); 2531193326Sed else if (flags & IEEE80211_CHAN_QUARTER) 2532193326Sed ND_PRINT((ndo, " 11a/5Mhz")); 2533193326Sed else 2534193326Sed ND_PRINT((ndo, " 11a")); 2535193326Sed } 2536193326Sed if (IS_CHAN_ANYG(flags)) { 2537193326Sed if (flags & IEEE80211_CHAN_HALF) 2538193326Sed ND_PRINT((ndo, " 11g/10Mhz")); 2539193326Sed else if (flags & IEEE80211_CHAN_QUARTER) 2540193326Sed ND_PRINT((ndo, " 11g/5Mhz")); 2541193326Sed else 2542193326Sed ND_PRINT((ndo, " 11g")); 2543193326Sed } else if (IS_CHAN_B(flags)) 2544193326Sed ND_PRINT((ndo, " 11b")); 2545193326Sed if (flags & IEEE80211_CHAN_TURBO) 2546193326Sed ND_PRINT((ndo, " Turbo")); 2547193326Sed } 2548193326Sed /* 2549193326Sed * These apply to 11n. 2550193326Sed */ 2551193326Sed if (flags & IEEE80211_CHAN_HT20) 2552194179Sed ND_PRINT((ndo, " ht/20")); 2553193326Sed else if (flags & IEEE80211_CHAN_HT40D) 2554193326Sed ND_PRINT((ndo, " ht/40-")); 2555193326Sed else if (flags & IEEE80211_CHAN_HT40U) 2556193326Sed ND_PRINT((ndo, " ht/40+")); 2557193326Sed ND_PRINT((ndo, " ")); 2558193326Sed} 2559193326Sed 2560193326Sedstatic int 2561193326Sedprint_radiotap_field(netdissect_options *ndo, 2562193576Sed struct cpack_state *s, uint32_t bit, uint8_t *flagsp, 2563193326Sed uint32_t presentflags) 2564193576Sed{ 2565193326Sed u_int i; 2566193326Sed int rc; 2567193326Sed 2568194613Sed switch (bit) { 2569193326Sed 2570193326Sed case IEEE80211_RADIOTAP_TSFT: { 2571193326Sed uint64_t tsft; 2572193326Sed 2573193326Sed rc = cpack_uint64(s, &tsft); 2574193326Sed if (rc != 0) 2575193576Sed goto trunc; 2576193576Sed ND_PRINT((ndo, "%" PRIu64 "us tsft ", tsft)); 2577193576Sed break; 2578193326Sed } 2579193326Sed 2580193326Sed case IEEE80211_RADIOTAP_FLAGS: { 2581193326Sed uint8_t flagsval; 2582193326Sed 2583193326Sed rc = cpack_uint8(s, &flagsval); 2584193326Sed if (rc != 0) 2585193326Sed goto trunc; 2586193326Sed *flagsp = flagsval; 2587193326Sed if (flagsval & IEEE80211_RADIOTAP_F_CFP) 2588193326Sed ND_PRINT((ndo, "cfp ")); 2589193326Sed if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE) 2590193326Sed ND_PRINT((ndo, "short preamble ")); 2591193326Sed if (flagsval & IEEE80211_RADIOTAP_F_WEP) 2592193326Sed ND_PRINT((ndo, "wep ")); 2593193326Sed if (flagsval & IEEE80211_RADIOTAP_F_FRAG) 2594193326Sed ND_PRINT((ndo, "fragmented ")); 2595193326Sed if (flagsval & IEEE80211_RADIOTAP_F_BADFCS) 2596193326Sed ND_PRINT((ndo, "bad-fcs ")); 2597193326Sed break; 2598193326Sed } 2599193326Sed 2600193326Sed case IEEE80211_RADIOTAP_RATE: { 2601193326Sed uint8_t rate; 2602193326Sed 2603193326Sed rc = cpack_uint8(s, &rate); 2604193326Sed if (rc != 0) 2605193326Sed goto trunc; 2606193326Sed /* 2607193326Sed * XXX On FreeBSD rate & 0x80 means we have an MCS. On 2608193326Sed * Linux and AirPcap it does not. (What about 2609193326Sed * Mac OS X, NetBSD, OpenBSD, and DragonFly BSD?) 2610193326Sed * 2611193326Sed * This is an issue either for proprietary extensions 2612193326Sed * to 11a or 11g, which do exist, or for 11n 2613193326Sed * implementations that stuff a rate value into 2614193326Sed * this field, which also appear to exist. 2615193326Sed * 2616193326Sed * We currently handle that by assuming that 2617193326Sed * if the 0x80 bit is set *and* the remaining 2618193326Sed * bits have a value between 0 and 15 it's 2619193326Sed * an MCS value, otherwise it's a rate. If 2620193576Sed * there are cases where systems that use 2621193326Sed * "0x80 + MCS index" for MCS indices > 15, 2622193326Sed * or stuff a rate value here between 64 and 2623193326Sed * 71.5 Mb/s in here, we'll need a preference 2624193326Sed * setting. Such rates do exist, e.g. 11n 2625193326Sed * MCS 7 at 20 MHz with a long guard interval. 2626193326Sed */ 2627193326Sed if (rate >= 0x80 && rate <= 0x8f) { 2628193326Sed /* 2629193326Sed * XXX - we don't know the channel width 2630193326Sed * or guard interval length, so we can't 2631193326Sed * convert this to a data rate. 2632193326Sed * 2633193326Sed * If you want us to show a data rate, 2634193326Sed * use the MCS field, not the Rate field; 2635193326Sed * the MCS field includes not only the 2636193326Sed * MCS index, it also includes bandwidth 2637193326Sed * and guard interval information. 2638193326Sed * 2639193326Sed * XXX - can we get the channel width 2640193326Sed * from XChannel and the guard interval 2641193326Sed * information from Flags, at least on 2642193326Sed * FreeBSD? 2643193326Sed */ 2644193326Sed ND_PRINT((ndo, "MCS %u ", rate & 0x7f)); 2645193326Sed } else 2646193576Sed ND_PRINT((ndo, "%2.1f Mb/s ", .5 * rate)); 2647193326Sed break; 2648193326Sed } 2649193326Sed 2650193326Sed case IEEE80211_RADIOTAP_CHANNEL: { 2651193326Sed uint16_t frequency; 2652193326Sed uint16_t flags; 2653193326Sed 2654193326Sed rc = cpack_uint16(s, &frequency); 2655193326Sed if (rc != 0) 2656193326Sed goto trunc; 2657193326Sed rc = cpack_uint16(s, &flags); 2658193326Sed if (rc != 0) 2659193326Sed goto trunc; 2660193326Sed /* 2661193576Sed * If CHANNEL and XCHANNEL are both present, skip 2662193326Sed * CHANNEL. 2663193326Sed */ 2664193326Sed if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL)) 2665193326Sed break; 2666193326Sed print_chaninfo(ndo, frequency, flags, presentflags); 2667193326Sed break; 2668193326Sed } 2669193326Sed 2670193326Sed case IEEE80211_RADIOTAP_FHSS: { 2671193326Sed uint8_t hopset; 2672193326Sed uint8_t hoppat; 2673193326Sed 2674193326Sed rc = cpack_uint8(s, &hopset); 2675193326Sed if (rc != 0) 2676193326Sed goto trunc; 2677193326Sed rc = cpack_uint8(s, &hoppat); 2678193326Sed if (rc != 0) 2679193326Sed goto trunc; 2680193326Sed ND_PRINT((ndo, "fhset %d fhpat %d ", hopset, hoppat)); 2681193326Sed break; 2682193326Sed } 2683193326Sed 2684193326Sed case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: { 2685193326Sed int8_t dbm_antsignal; 2686193326Sed 2687193326Sed rc = cpack_int8(s, &dbm_antsignal); 2688193326Sed if (rc != 0) 2689193326Sed goto trunc; 2690193326Sed ND_PRINT((ndo, "%ddBm signal ", dbm_antsignal)); 2691193326Sed break; 2692193326Sed } 2693193326Sed 2694193326Sed case IEEE80211_RADIOTAP_DBM_ANTNOISE: { 2695193326Sed int8_t dbm_antnoise; 2696193326Sed 2697193326Sed rc = cpack_int8(s, &dbm_antnoise); 2698193326Sed if (rc != 0) 2699193326Sed goto trunc; 2700193326Sed ND_PRINT((ndo, "%ddBm noise ", dbm_antnoise)); 2701193326Sed break; 2702193326Sed } 2703193326Sed 2704193326Sed case IEEE80211_RADIOTAP_LOCK_QUALITY: { 2705193326Sed uint16_t lock_quality; 2706193326Sed 2707193326Sed rc = cpack_uint16(s, &lock_quality); 2708193326Sed if (rc != 0) 2709193326Sed goto trunc; 2710193326Sed ND_PRINT((ndo, "%u sq ", lock_quality)); 2711193326Sed break; 2712193326Sed } 2713193326Sed 2714193326Sed case IEEE80211_RADIOTAP_TX_ATTENUATION: { 2715193326Sed uint16_t tx_attenuation; 2716193326Sed 2717193326Sed rc = cpack_uint16(s, &tx_attenuation); 2718193326Sed if (rc != 0) 2719193326Sed goto trunc; 2720193326Sed ND_PRINT((ndo, "%d tx power ", -(int)tx_attenuation)); 2721193326Sed break; 2722193326Sed } 2723193326Sed 2724193326Sed case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: { 2725193326Sed uint8_t db_tx_attenuation; 2726193326Sed 2727193326Sed rc = cpack_uint8(s, &db_tx_attenuation); 2728193326Sed if (rc != 0) 2729193326Sed goto trunc; 2730193326Sed ND_PRINT((ndo, "%ddB tx attenuation ", -(int)db_tx_attenuation)); 2731193326Sed break; 2732193326Sed } 2733193326Sed 2734193326Sed case IEEE80211_RADIOTAP_DBM_TX_POWER: { 2735193326Sed int8_t dbm_tx_power; 2736193326Sed 2737193326Sed rc = cpack_int8(s, &dbm_tx_power); 2738193326Sed if (rc != 0) 2739193326Sed goto trunc; 2740193326Sed ND_PRINT((ndo, "%ddBm tx power ", dbm_tx_power)); 2741193326Sed break; 2742193326Sed } 2743193326Sed 2744193326Sed case IEEE80211_RADIOTAP_ANTENNA: { 2745193326Sed uint8_t antenna; 2746193326Sed 2747193326Sed rc = cpack_uint8(s, &antenna); 2748193326Sed if (rc != 0) 2749193326Sed goto trunc; 2750193326Sed ND_PRINT((ndo, "antenna %u ", antenna)); 2751193326Sed break; 2752193326Sed } 2753193326Sed 2754193326Sed case IEEE80211_RADIOTAP_DB_ANTSIGNAL: { 2755193326Sed uint8_t db_antsignal; 2756193326Sed 2757193326Sed rc = cpack_uint8(s, &db_antsignal); 2758193326Sed if (rc != 0) 2759193326Sed goto trunc; 2760193326Sed ND_PRINT((ndo, "%ddB signal ", db_antsignal)); 2761193326Sed break; 2762193326Sed } 2763193326Sed 2764193326Sed case IEEE80211_RADIOTAP_DB_ANTNOISE: { 2765193326Sed uint8_t db_antnoise; 2766193326Sed 2767193326Sed rc = cpack_uint8(s, &db_antnoise); 2768193326Sed if (rc != 0) 2769193326Sed goto trunc; 2770193326Sed ND_PRINT((ndo, "%ddB noise ", db_antnoise)); 2771193326Sed break; 2772193326Sed } 2773193326Sed 2774193326Sed case IEEE80211_RADIOTAP_RX_FLAGS: { 2775193326Sed uint16_t rx_flags; 2776193326Sed 2777193326Sed rc = cpack_uint16(s, &rx_flags); 2778193326Sed if (rc != 0) 2779193326Sed goto trunc; 2780193326Sed /* Do nothing for now */ 2781193326Sed break; 2782193326Sed } 2783193326Sed 2784193326Sed case IEEE80211_RADIOTAP_XCHANNEL: { 2785193326Sed uint32_t flags; 2786193326Sed uint16_t frequency; 2787193326Sed uint8_t channel; 2788193326Sed uint8_t maxpower; 2789193326Sed 2790193326Sed rc = cpack_uint32(s, &flags); 2791193326Sed if (rc != 0) 2792193326Sed goto trunc; 2793193326Sed rc = cpack_uint16(s, &frequency); 2794193326Sed if (rc != 0) 2795193326Sed goto trunc; 2796193326Sed rc = cpack_uint8(s, &channel); 2797193326Sed if (rc != 0) 2798193326Sed goto trunc; 2799193326Sed rc = cpack_uint8(s, &maxpower); 2800193326Sed if (rc != 0) 2801193326Sed goto trunc; 2802193326Sed print_chaninfo(ndo, frequency, flags, presentflags); 2803193326Sed break; 2804193326Sed } 2805193326Sed 2806193326Sed case IEEE80211_RADIOTAP_MCS: { 2807193326Sed uint8_t known; 2808193326Sed uint8_t flags; 2809193326Sed uint8_t mcs_index; 2810193326Sed static const char *ht_bandwidth[4] = { 2811193326Sed "20 MHz", 2812193326Sed "40 MHz", 2813193326Sed "20 MHz (L)", 2814193326Sed "20 MHz (U)" 2815193326Sed }; 2816193326Sed float htrate; 2817193326Sed 2818193326Sed rc = cpack_uint8(s, &known); 2819193326Sed if (rc != 0) 2820193326Sed goto trunc; 2821193326Sed rc = cpack_uint8(s, &flags); 2822193326Sed if (rc != 0) 2823193326Sed goto trunc; 2824193326Sed rc = cpack_uint8(s, &mcs_index); 2825193326Sed if (rc != 0) 2826193326Sed goto trunc; 2827193326Sed if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) { 2828193326Sed /* 2829193326Sed * We know the MCS index. 2830193326Sed */ 2831193326Sed if (mcs_index <= MAX_MCS_INDEX) { 2832193326Sed /* 2833193326Sed * And it's in-range. 2834193326Sed */ 2835193326Sed if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) { 2836193326Sed /* 2837193326Sed * And we know both the bandwidth and 2838193326Sed * the guard interval, so we can look 2839193326Sed * up the rate. 2840193326Sed */ 2841193326Sed htrate = 2842193326Sed ieee80211_float_htrates \ 2843193326Sed [mcs_index] \ 2844193326Sed [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)] \ 2845193326Sed [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)]; 2846193326Sed } else { 2847193326Sed /* 2848193326Sed * We don't know both the bandwidth 2849193326Sed * and the guard interval, so we can 2850193326Sed * only report the MCS index. 2851193326Sed */ 2852193326Sed htrate = 0.0; 2853193326Sed } 2854193326Sed } else { 2855193326Sed /* 2856193326Sed * The MCS value is out of range. 2857193326Sed */ 2858193326Sed htrate = 0.0; 2859193326Sed } 2860193326Sed if (htrate != 0.0) { 2861193326Sed /* 2862193326Sed * We have the rate. 2863193326Sed * Print it. 2864193326Sed */ 2865193326Sed ND_PRINT((ndo, "%.1f Mb/s MCS %u ", htrate, mcs_index)); 2866193326Sed } else { 2867 /* 2868 * We at least have the MCS index. 2869 * Print it. 2870 */ 2871 ND_PRINT((ndo, "MCS %u ", mcs_index)); 2872 } 2873 } 2874 if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) { 2875 ND_PRINT((ndo, "%s ", 2876 ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK])); 2877 } 2878 if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) { 2879 ND_PRINT((ndo, "%s GI ", 2880 (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 2881 "short" : "long")); 2882 } 2883 if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) { 2884 ND_PRINT((ndo, "%s ", 2885 (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ? 2886 "greenfield" : "mixed")); 2887 } 2888 if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) { 2889 ND_PRINT((ndo, "%s FEC ", 2890 (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ? 2891 "LDPC" : "BCC")); 2892 } 2893 if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) { 2894 ND_PRINT((ndo, "RX-STBC%u ", 2895 (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT)); 2896 } 2897 break; 2898 } 2899 2900 case IEEE80211_RADIOTAP_AMPDU_STATUS: { 2901 uint32_t reference_num; 2902 uint16_t flags; 2903 uint8_t delim_crc; 2904 uint8_t reserved; 2905 2906 rc = cpack_uint32(s, &reference_num); 2907 if (rc != 0) 2908 goto trunc; 2909 rc = cpack_uint16(s, &flags); 2910 if (rc != 0) 2911 goto trunc; 2912 rc = cpack_uint8(s, &delim_crc); 2913 if (rc != 0) 2914 goto trunc; 2915 rc = cpack_uint8(s, &reserved); 2916 if (rc != 0) 2917 goto trunc; 2918 /* Do nothing for now */ 2919 break; 2920 } 2921 2922 case IEEE80211_RADIOTAP_VHT: { 2923 uint16_t known; 2924 uint8_t flags; 2925 uint8_t bandwidth; 2926 uint8_t mcs_nss[4]; 2927 uint8_t coding; 2928 uint8_t group_id; 2929 uint16_t partial_aid; 2930 static const char *vht_bandwidth[32] = { 2931 "20 MHz", 2932 "40 MHz", 2933 "20 MHz (L)", 2934 "20 MHz (U)", 2935 "80 MHz", 2936 "80 MHz (L)", 2937 "80 MHz (U)", 2938 "80 MHz (LL)", 2939 "80 MHz (LU)", 2940 "80 MHz (UL)", 2941 "80 MHz (UU)", 2942 "160 MHz", 2943 "160 MHz (L)", 2944 "160 MHz (U)", 2945 "160 MHz (LL)", 2946 "160 MHz (LU)", 2947 "160 MHz (UL)", 2948 "160 MHz (UU)", 2949 "160 MHz (LLL)", 2950 "160 MHz (LLU)", 2951 "160 MHz (LUL)", 2952 "160 MHz (UUU)", 2953 "160 MHz (ULL)", 2954 "160 MHz (ULU)", 2955 "160 MHz (UUL)", 2956 "160 MHz (UUU)", 2957 "unknown (26)", 2958 "unknown (27)", 2959 "unknown (28)", 2960 "unknown (29)", 2961 "unknown (30)", 2962 "unknown (31)" 2963 }; 2964 2965 rc = cpack_uint16(s, &known); 2966 if (rc != 0) 2967 goto trunc; 2968 rc = cpack_uint8(s, &flags); 2969 if (rc != 0) 2970 goto trunc; 2971 rc = cpack_uint8(s, &bandwidth); 2972 if (rc != 0) 2973 goto trunc; 2974 for (i = 0; i < 4; i++) { 2975 rc = cpack_uint8(s, &mcs_nss[i]); 2976 if (rc != 0) 2977 goto trunc; 2978 } 2979 rc = cpack_uint8(s, &coding); 2980 if (rc != 0) 2981 goto trunc; 2982 rc = cpack_uint8(s, &group_id); 2983 if (rc != 0) 2984 goto trunc; 2985 rc = cpack_uint16(s, &partial_aid); 2986 if (rc != 0) 2987 goto trunc; 2988 for (i = 0; i < 4; i++) { 2989 u_int nss, mcs; 2990 nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK; 2991 mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT; 2992 2993 if (nss == 0) 2994 continue; 2995 2996 ND_PRINT((ndo, "User %u MCS %u ", i, mcs)); 2997 ND_PRINT((ndo, "%s FEC ", 2998 (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ? 2999 "LDPC" : "BCC")); 3000 } 3001 if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) { 3002 ND_PRINT((ndo, "%s ", 3003 vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK])); 3004 } 3005 if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) { 3006 ND_PRINT((ndo, "%s GI ", 3007 (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ? 3008 "short" : "long")); 3009 } 3010 break; 3011 } 3012 3013 default: 3014 /* this bit indicates a field whose 3015 * size we do not know, so we cannot 3016 * proceed. Just print the bit number. 3017 */ 3018 ND_PRINT((ndo, "[bit %u] ", bit)); 3019 return -1; 3020 } 3021 3022 return 0; 3023 3024trunc: 3025 ND_PRINT((ndo, "%s", tstr)); 3026 return rc; 3027} 3028 3029 3030static int 3031print_in_radiotap_namespace(netdissect_options *ndo, 3032 struct cpack_state *s, uint8_t *flags, 3033 uint32_t presentflags, int bit0) 3034{ 3035#define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x))) 3036#define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x))) 3037#define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x))) 3038#define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x))) 3039#define BITNO_2(x) (((x) & 2) ? 1 : 0) 3040 uint32_t present, next_present; 3041 int bitno; 3042 enum ieee80211_radiotap_type bit; 3043 int rc; 3044 3045 for (present = presentflags; present; present = next_present) { 3046 /* 3047 * Clear the least significant bit that is set. 3048 */ 3049 next_present = present & (present - 1); 3050 3051 /* 3052 * Get the bit number, within this presence word, 3053 * of the remaining least significant bit that 3054 * is set. 3055 */ 3056 bitno = BITNO_32(present ^ next_present); 3057 3058 /* 3059 * Stop if this is one of the "same meaning 3060 * in all presence flags" bits. 3061 */ 3062 if (bitno >= IEEE80211_RADIOTAP_NAMESPACE) 3063 break; 3064 3065 /* 3066 * Get the radiotap bit number of that bit. 3067 */ 3068 bit = (enum ieee80211_radiotap_type)(bit0 + bitno); 3069 3070 rc = print_radiotap_field(ndo, s, bit, flags, presentflags); 3071 if (rc != 0) 3072 return rc; 3073 } 3074 3075 return 0; 3076} 3077 3078u_int 3079ieee802_11_radio_print(netdissect_options *ndo, 3080 const u_char *p, u_int length, u_int caplen) 3081{ 3082#define BIT(n) (1U << n) 3083#define IS_EXTENDED(__p) \ 3084 (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0 3085 3086 struct cpack_state cpacker; 3087 const struct ieee80211_radiotap_header *hdr; 3088 uint32_t presentflags; 3089 const uint32_t *presentp, *last_presentp; 3090 int vendor_namespace; 3091 uint8_t vendor_oui[3]; 3092 uint8_t vendor_subnamespace; 3093 uint16_t skip_length; 3094 int bit0; 3095 u_int len; 3096 uint8_t flags; 3097 int pad; 3098 u_int fcslen; 3099 3100 if (caplen < sizeof(*hdr)) { 3101 ND_PRINT((ndo, "%s", tstr)); 3102 return caplen; 3103 } 3104 3105 hdr = (const struct ieee80211_radiotap_header *)p; 3106 3107 len = EXTRACT_LE_16BITS(&hdr->it_len); 3108 if (len < sizeof(*hdr)) { 3109 /* 3110 * The length is the length of the entire header, so 3111 * it must be as large as the fixed-length part of 3112 * the header. 3113 */ 3114 ND_PRINT((ndo, "%s", tstr)); 3115 return caplen; 3116 } 3117 3118 /* 3119 * If we don't have the entire radiotap header, just give up. 3120 */ 3121 if (caplen < len) { 3122 ND_PRINT((ndo, "%s", tstr)); 3123 return caplen; 3124 } 3125 cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */ 3126 cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */ 3127 for (last_presentp = &hdr->it_present; 3128 (const u_char*)(last_presentp + 1) <= p + len && 3129 IS_EXTENDED(last_presentp); 3130 last_presentp++) 3131 cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */ 3132 3133 /* are there more bitmap extensions than bytes in header? */ 3134 if ((const u_char*)(last_presentp + 1) > p + len) { 3135 ND_PRINT((ndo, "%s", tstr)); 3136 return caplen; 3137 } 3138 3139 /* 3140 * Start out at the beginning of the default radiotap namespace. 3141 */ 3142 bit0 = 0; 3143 vendor_namespace = 0; 3144 memset(vendor_oui, 0, 3); 3145 vendor_subnamespace = 0; 3146 skip_length = 0; 3147 /* Assume no flags */ 3148 flags = 0; 3149 /* Assume no Atheros padding between 802.11 header and body */ 3150 pad = 0; 3151 /* Assume no FCS at end of frame */ 3152 fcslen = 0; 3153 for (presentp = &hdr->it_present; presentp <= last_presentp; 3154 presentp++) { 3155 presentflags = EXTRACT_LE_32BITS(presentp); 3156 3157 /* 3158 * If this is a vendor namespace, we don't handle it. 3159 */ 3160 if (vendor_namespace) { 3161 /* 3162 * Skip past the stuff we don't understand. 3163 * If we add support for any vendor namespaces, 3164 * it'd be added here; use vendor_oui and 3165 * vendor_subnamespace to interpret the fields. 3166 */ 3167 if (cpack_advance(&cpacker, skip_length) != 0) { 3168 /* 3169 * Ran out of space in the packet. 3170 */ 3171 break; 3172 } 3173 3174 /* 3175 * We've skipped it all; nothing more to 3176 * skip. 3177 */ 3178 skip_length = 0; 3179 } else { 3180 if (print_in_radiotap_namespace(ndo, &cpacker, 3181 &flags, presentflags, bit0) != 0) { 3182 /* 3183 * Fatal error - can't process anything 3184 * more in the radiotap header. 3185 */ 3186 break; 3187 } 3188 } 3189 3190 /* 3191 * Handle the namespace switch bits; we've already handled 3192 * the extension bit in all but the last word above. 3193 */ 3194 switch (presentflags & 3195 (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) { 3196 3197 case 0: 3198 /* 3199 * We're not changing namespaces. 3200 * advance to the next 32 bits in the current 3201 * namespace. 3202 */ 3203 bit0 += 32; 3204 break; 3205 3206 case BIT(IEEE80211_RADIOTAP_NAMESPACE): 3207 /* 3208 * We're switching to the radiotap namespace. 3209 * Reset the presence-bitmap index to 0, and 3210 * reset the namespace to the default radiotap 3211 * namespace. 3212 */ 3213 bit0 = 0; 3214 vendor_namespace = 0; 3215 memset(vendor_oui, 0, 3); 3216 vendor_subnamespace = 0; 3217 skip_length = 0; 3218 break; 3219 3220 case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE): 3221 /* 3222 * We're switching to a vendor namespace. 3223 * Reset the presence-bitmap index to 0, 3224 * note that we're in a vendor namespace, 3225 * and fetch the fields of the Vendor Namespace 3226 * item. 3227 */ 3228 bit0 = 0; 3229 vendor_namespace = 1; 3230 if ((cpack_align_and_reserve(&cpacker, 2)) == NULL) { 3231 ND_PRINT((ndo, "%s", tstr)); 3232 break; 3233 } 3234 if (cpack_uint8(&cpacker, &vendor_oui[0]) != 0) { 3235 ND_PRINT((ndo, "%s", tstr)); 3236 break; 3237 } 3238 if (cpack_uint8(&cpacker, &vendor_oui[1]) != 0) { 3239 ND_PRINT((ndo, "%s", tstr)); 3240 break; 3241 } 3242 if (cpack_uint8(&cpacker, &vendor_oui[2]) != 0) { 3243 ND_PRINT((ndo, "%s", tstr)); 3244 break; 3245 } 3246 if (cpack_uint8(&cpacker, &vendor_subnamespace) != 0) { 3247 ND_PRINT((ndo, "%s", tstr)); 3248 break; 3249 } 3250 if (cpack_uint16(&cpacker, &skip_length) != 0) { 3251 ND_PRINT((ndo, "%s", tstr)); 3252 break; 3253 } 3254 break; 3255 3256 default: 3257 /* 3258 * Illegal combination. The behavior in this 3259 * case is undefined by the radiotap spec; we 3260 * just ignore both bits. 3261 */ 3262 break; 3263 } 3264 } 3265 3266 if (flags & IEEE80211_RADIOTAP_F_DATAPAD) 3267 pad = 1; /* Atheros padding */ 3268 if (flags & IEEE80211_RADIOTAP_F_FCS) 3269 fcslen = 4; /* FCS at end of packet */ 3270 return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad, 3271 fcslen); 3272#undef BITNO_32 3273#undef BITNO_16 3274#undef BITNO_8 3275#undef BITNO_4 3276#undef BITNO_2 3277#undef BIT 3278} 3279 3280static u_int 3281ieee802_11_avs_radio_print(netdissect_options *ndo, 3282 const u_char *p, u_int length, u_int caplen) 3283{ 3284 uint32_t caphdr_len; 3285 3286 if (caplen < 8) { 3287 ND_PRINT((ndo, "%s", tstr)); 3288 return caplen; 3289 } 3290 3291 caphdr_len = EXTRACT_32BITS(p + 4); 3292 if (caphdr_len < 8) { 3293 /* 3294 * Yow! The capture header length is claimed not 3295 * to be large enough to include even the version 3296 * cookie or capture header length! 3297 */ 3298 ND_PRINT((ndo, "%s", tstr)); 3299 return caplen; 3300 } 3301 3302 if (caplen < caphdr_len) { 3303 ND_PRINT((ndo, "%s", tstr)); 3304 return caplen; 3305 } 3306 3307 return caphdr_len + ieee802_11_print(ndo, p + caphdr_len, 3308 length - caphdr_len, caplen - caphdr_len, 0, 0); 3309} 3310 3311#define PRISM_HDR_LEN 144 3312 3313#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 3314#define WLANCAP_MAGIC_COOKIE_V1 0x80211001 3315#define WLANCAP_MAGIC_COOKIE_V2 0x80211002 3316 3317/* 3318 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header, 3319 * containing information such as radio information, which we 3320 * currently ignore. 3321 * 3322 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or 3323 * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS 3324 * (currently, on Linux, there's no ARPHRD_ type for 3325 * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM 3326 * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for 3327 * the AVS header, and the first 4 bytes of the header are used to 3328 * indicate whether it's a Prism header or an AVS header). 3329 */ 3330u_int 3331prism_if_print(netdissect_options *ndo, 3332 const struct pcap_pkthdr *h, const u_char *p) 3333{ 3334 u_int caplen = h->caplen; 3335 u_int length = h->len; 3336 uint32_t msgcode; 3337 3338 if (caplen < 4) { 3339 ND_PRINT((ndo, "%s", tstr)); 3340 return caplen; 3341 } 3342 3343 msgcode = EXTRACT_32BITS(p); 3344 if (msgcode == WLANCAP_MAGIC_COOKIE_V1 || 3345 msgcode == WLANCAP_MAGIC_COOKIE_V2) 3346 return ieee802_11_avs_radio_print(ndo, p, length, caplen); 3347 3348 if (caplen < PRISM_HDR_LEN) { 3349 ND_PRINT((ndo, "%s", tstr)); 3350 return caplen; 3351 } 3352 3353 return PRISM_HDR_LEN + ieee802_11_print(ndo, p + PRISM_HDR_LEN, 3354 length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN, 0, 0); 3355} 3356 3357/* 3358 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra 3359 * header, containing information such as radio information. 3360 */ 3361u_int 3362ieee802_11_radio_if_print(netdissect_options *ndo, 3363 const struct pcap_pkthdr *h, const u_char *p) 3364{ 3365 return ieee802_11_radio_print(ndo, p, h->len, h->caplen); 3366} 3367 3368/* 3369 * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an 3370 * extra header, containing information such as radio information, 3371 * which we currently ignore. 3372 */ 3373u_int 3374ieee802_11_radio_avs_if_print(netdissect_options *ndo, 3375 const struct pcap_pkthdr *h, const u_char *p) 3376{ 3377 return ieee802_11_avs_radio_print(ndo, p, h->len, h->caplen); 3378} 3379