1a90e161bSBill Fenner /*
2a90e161bSBill Fenner * Copyright (c) 2001
3a90e161bSBill Fenner * Fortress Technologies, Inc. All rights reserved.
4a90e161bSBill Fenner * Charlie Lenahan (clenahan@fortresstech.com)
5a90e161bSBill Fenner *
6a90e161bSBill Fenner * Redistribution and use in source and binary forms, with or without
7a90e161bSBill Fenner * modification, are permitted provided that: (1) source code distributions
8a90e161bSBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2)
9a90e161bSBill Fenner * distributions including binary code include the above copyright notice and
10a90e161bSBill Fenner * this paragraph in its entirety in the documentation or other materials
11a90e161bSBill Fenner * provided with the distribution, and (3) all advertising materials mentioning
12a90e161bSBill Fenner * features or use of this software display the following acknowledgement:
13a90e161bSBill Fenner * ``This product includes software developed by the University of California,
14a90e161bSBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15a90e161bSBill Fenner * the University nor the names of its contributors may be used to endorse
16a90e161bSBill Fenner * or promote products derived from this software without specific prior
17a90e161bSBill Fenner * written permission.
18a90e161bSBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19a90e161bSBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20a90e161bSBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21a90e161bSBill Fenner */
22a90e161bSBill Fenner
233340d773SGleb Smirnoff /* \summary: IEEE 802.11 printer */
243340d773SGleb Smirnoff
25ee67461eSJoseph Mingrone #include <config.h>
26a90e161bSBill Fenner
27ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
28a90e161bSBill Fenner
29a90e161bSBill Fenner #include <string.h>
30a90e161bSBill Fenner
313340d773SGleb Smirnoff #include "netdissect.h"
32a90e161bSBill Fenner #include "addrtoname.h"
33a90e161bSBill Fenner
34a90e161bSBill Fenner #include "extract.h"
35a90e161bSBill Fenner
361de50e9fSSam Leffler #include "cpack.h"
37a90e161bSBill Fenner
383c602fabSXin LI
393c602fabSXin LI /* Lengths of 802.11 header components. */
403c602fabSXin LI #define IEEE802_11_FC_LEN 2
413c602fabSXin LI #define IEEE802_11_DUR_LEN 2
423c602fabSXin LI #define IEEE802_11_DA_LEN 6
433c602fabSXin LI #define IEEE802_11_SA_LEN 6
443c602fabSXin LI #define IEEE802_11_BSSID_LEN 6
453c602fabSXin LI #define IEEE802_11_RA_LEN 6
463c602fabSXin LI #define IEEE802_11_TA_LEN 6
473340d773SGleb Smirnoff #define IEEE802_11_ADDR1_LEN 6
483c602fabSXin LI #define IEEE802_11_SEQ_LEN 2
493c602fabSXin LI #define IEEE802_11_CTL_LEN 2
503340d773SGleb Smirnoff #define IEEE802_11_CARRIED_FC_LEN 2
513340d773SGleb Smirnoff #define IEEE802_11_HT_CONTROL_LEN 4
523c602fabSXin LI #define IEEE802_11_IV_LEN 3
533c602fabSXin LI #define IEEE802_11_KID_LEN 1
543c602fabSXin LI
553c602fabSXin LI /* Frame check sequence length. */
563c602fabSXin LI #define IEEE802_11_FCS_LEN 4
573c602fabSXin LI
583c602fabSXin LI /* Lengths of beacon components. */
593c602fabSXin LI #define IEEE802_11_TSTAMP_LEN 8
603c602fabSXin LI #define IEEE802_11_BCNINT_LEN 2
613c602fabSXin LI #define IEEE802_11_CAPINFO_LEN 2
623c602fabSXin LI #define IEEE802_11_LISTENINT_LEN 2
633c602fabSXin LI
643c602fabSXin LI #define IEEE802_11_AID_LEN 2
653c602fabSXin LI #define IEEE802_11_STATUS_LEN 2
663c602fabSXin LI #define IEEE802_11_REASON_LEN 2
673c602fabSXin LI
68*0a7e5f1fSJoseph Mingrone /* Length of previous AP in reassociation frame */
693c602fabSXin LI #define IEEE802_11_AP_LEN 6
703c602fabSXin LI
713c602fabSXin LI #define T_MGMT 0x0 /* management */
723c602fabSXin LI #define T_CTRL 0x1 /* control */
733c602fabSXin LI #define T_DATA 0x2 /* data */
743c602fabSXin LI #define T_RESV 0x3 /* reserved */
753c602fabSXin LI
763c602fabSXin LI #define ST_ASSOC_REQUEST 0x0
773c602fabSXin LI #define ST_ASSOC_RESPONSE 0x1
783c602fabSXin LI #define ST_REASSOC_REQUEST 0x2
793c602fabSXin LI #define ST_REASSOC_RESPONSE 0x3
803c602fabSXin LI #define ST_PROBE_REQUEST 0x4
813c602fabSXin LI #define ST_PROBE_RESPONSE 0x5
823c602fabSXin LI /* RESERVED 0x6 */
833c602fabSXin LI /* RESERVED 0x7 */
843c602fabSXin LI #define ST_BEACON 0x8
853c602fabSXin LI #define ST_ATIM 0x9
863c602fabSXin LI #define ST_DISASSOC 0xA
873c602fabSXin LI #define ST_AUTH 0xB
883c602fabSXin LI #define ST_DEAUTH 0xC
893c602fabSXin LI #define ST_ACTION 0xD
903c602fabSXin LI /* RESERVED 0xE */
913c602fabSXin LI /* RESERVED 0xF */
923c602fabSXin LI
933c602fabSXin LI static const struct tok st_str[] = {
943c602fabSXin LI { ST_ASSOC_REQUEST, "Assoc Request" },
953c602fabSXin LI { ST_ASSOC_RESPONSE, "Assoc Response" },
963c602fabSXin LI { ST_REASSOC_REQUEST, "ReAssoc Request" },
973c602fabSXin LI { ST_REASSOC_RESPONSE, "ReAssoc Response" },
983c602fabSXin LI { ST_PROBE_REQUEST, "Probe Request" },
993c602fabSXin LI { ST_PROBE_RESPONSE, "Probe Response" },
1003c602fabSXin LI { ST_BEACON, "Beacon" },
1013c602fabSXin LI { ST_ATIM, "ATIM" },
1023c602fabSXin LI { ST_DISASSOC, "Disassociation" },
1033c602fabSXin LI { ST_AUTH, "Authentication" },
1043c602fabSXin LI { ST_DEAUTH, "DeAuthentication" },
1053c602fabSXin LI { ST_ACTION, "Action" },
1063c602fabSXin LI { 0, NULL }
1073c602fabSXin LI };
1083c602fabSXin LI
1093c602fabSXin LI #define CTRL_CONTROL_WRAPPER 0x7
1103c602fabSXin LI #define CTRL_BAR 0x8
1113c602fabSXin LI #define CTRL_BA 0x9
1123c602fabSXin LI #define CTRL_PS_POLL 0xA
1133c602fabSXin LI #define CTRL_RTS 0xB
1143c602fabSXin LI #define CTRL_CTS 0xC
1153c602fabSXin LI #define CTRL_ACK 0xD
1163c602fabSXin LI #define CTRL_CF_END 0xE
1173c602fabSXin LI #define CTRL_END_ACK 0xF
1183c602fabSXin LI
1193c602fabSXin LI static const struct tok ctrl_str[] = {
1203c602fabSXin LI { CTRL_CONTROL_WRAPPER, "Control Wrapper" },
1213c602fabSXin LI { CTRL_BAR, "BAR" },
1223c602fabSXin LI { CTRL_BA, "BA" },
1233c602fabSXin LI { CTRL_PS_POLL, "Power Save-Poll" },
1243c602fabSXin LI { CTRL_RTS, "Request-To-Send" },
1253c602fabSXin LI { CTRL_CTS, "Clear-To-Send" },
1263c602fabSXin LI { CTRL_ACK, "Acknowledgment" },
1273c602fabSXin LI { CTRL_CF_END, "CF-End" },
1283c602fabSXin LI { CTRL_END_ACK, "CF-End+CF-Ack" },
1293c602fabSXin LI { 0, NULL }
1303c602fabSXin LI };
1313c602fabSXin LI
1323c602fabSXin LI #define DATA_DATA 0x0
1333c602fabSXin LI #define DATA_DATA_CF_ACK 0x1
1343c602fabSXin LI #define DATA_DATA_CF_POLL 0x2
1353c602fabSXin LI #define DATA_DATA_CF_ACK_POLL 0x3
1363c602fabSXin LI #define DATA_NODATA 0x4
1373c602fabSXin LI #define DATA_NODATA_CF_ACK 0x5
1383c602fabSXin LI #define DATA_NODATA_CF_POLL 0x6
1393c602fabSXin LI #define DATA_NODATA_CF_ACK_POLL 0x7
1403c602fabSXin LI
1413c602fabSXin LI #define DATA_QOS_DATA 0x8
1423c602fabSXin LI #define DATA_QOS_DATA_CF_ACK 0x9
1433c602fabSXin LI #define DATA_QOS_DATA_CF_POLL 0xA
1443c602fabSXin LI #define DATA_QOS_DATA_CF_ACK_POLL 0xB
1453c602fabSXin LI #define DATA_QOS_NODATA 0xC
1463c602fabSXin LI #define DATA_QOS_CF_POLL_NODATA 0xE
1473c602fabSXin LI #define DATA_QOS_CF_ACK_POLL_NODATA 0xF
1483c602fabSXin LI
1493c602fabSXin LI /*
1503c602fabSXin LI * The subtype field of a data frame is, in effect, composed of 4 flag
1513c602fabSXin LI * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
1523c602fabSXin LI * any data), and QoS.
1533c602fabSXin LI */
1543c602fabSXin LI #define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01)
1553c602fabSXin LI #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02)
1563c602fabSXin LI #define DATA_FRAME_IS_NULL(x) ((x) & 0x04)
1573c602fabSXin LI #define DATA_FRAME_IS_QOS(x) ((x) & 0x08)
1583c602fabSXin LI
1593c602fabSXin LI /*
1603c602fabSXin LI * Bits in the frame control field.
1613c602fabSXin LI */
1623c602fabSXin LI #define FC_VERSION(fc) ((fc) & 0x3)
1633c602fabSXin LI #define FC_TYPE(fc) (((fc) >> 2) & 0x3)
1643c602fabSXin LI #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF)
1653c602fabSXin LI #define FC_TO_DS(fc) ((fc) & 0x0100)
1663c602fabSXin LI #define FC_FROM_DS(fc) ((fc) & 0x0200)
1673c602fabSXin LI #define FC_MORE_FLAG(fc) ((fc) & 0x0400)
1683c602fabSXin LI #define FC_RETRY(fc) ((fc) & 0x0800)
1693c602fabSXin LI #define FC_POWER_MGMT(fc) ((fc) & 0x1000)
1703c602fabSXin LI #define FC_MORE_DATA(fc) ((fc) & 0x2000)
1713340d773SGleb Smirnoff #define FC_PROTECTED(fc) ((fc) & 0x4000)
1723c602fabSXin LI #define FC_ORDER(fc) ((fc) & 0x8000)
1733c602fabSXin LI
1743c602fabSXin LI struct mgmt_header_t {
175ee67461eSJoseph Mingrone nd_uint16_t fc;
176ee67461eSJoseph Mingrone nd_uint16_t duration;
177ee67461eSJoseph Mingrone nd_mac_addr da;
178ee67461eSJoseph Mingrone nd_mac_addr sa;
179ee67461eSJoseph Mingrone nd_mac_addr bssid;
180ee67461eSJoseph Mingrone nd_uint16_t seq_ctrl;
1813c602fabSXin LI };
1823c602fabSXin LI
1833c602fabSXin LI #define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
1843c602fabSXin LI IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\
1853c602fabSXin LI IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN)
1863c602fabSXin LI
1873c602fabSXin LI #define CAPABILITY_ESS(cap) ((cap) & 0x0001)
1883c602fabSXin LI #define CAPABILITY_IBSS(cap) ((cap) & 0x0002)
1893c602fabSXin LI #define CAPABILITY_CFP(cap) ((cap) & 0x0004)
1903c602fabSXin LI #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008)
1913c602fabSXin LI #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010)
1923c602fabSXin LI
1933c602fabSXin LI struct ssid_t {
194*0a7e5f1fSJoseph Mingrone u_int length;
1953c602fabSXin LI u_char ssid[33]; /* 32 + 1 for null */
1963c602fabSXin LI };
1973c602fabSXin LI
1983c602fabSXin LI struct rates_t {
199*0a7e5f1fSJoseph Mingrone u_int length;
2003c602fabSXin LI uint8_t rate[16];
2013c602fabSXin LI };
2023c602fabSXin LI
2033c602fabSXin LI struct challenge_t {
204*0a7e5f1fSJoseph Mingrone u_int length;
2053c602fabSXin LI uint8_t text[254]; /* 1-253 + 1 for null */
2063c602fabSXin LI };
2073c602fabSXin LI
2083c602fabSXin LI struct fh_t {
209*0a7e5f1fSJoseph Mingrone u_int length;
2103c602fabSXin LI uint16_t dwell_time;
2113c602fabSXin LI uint8_t hop_set;
2123c602fabSXin LI uint8_t hop_pattern;
2133c602fabSXin LI uint8_t hop_index;
2143c602fabSXin LI };
2153c602fabSXin LI
2163c602fabSXin LI struct ds_t {
217*0a7e5f1fSJoseph Mingrone u_int length;
2183c602fabSXin LI uint8_t channel;
2193c602fabSXin LI };
2203c602fabSXin LI
2213c602fabSXin LI struct cf_t {
222*0a7e5f1fSJoseph Mingrone u_int length;
2233c602fabSXin LI uint8_t count;
2243c602fabSXin LI uint8_t period;
2253c602fabSXin LI uint16_t max_duration;
226ee67461eSJoseph Mingrone uint16_t dur_remaining;
2273c602fabSXin LI };
2283c602fabSXin LI
2293c602fabSXin LI struct tim_t {
230*0a7e5f1fSJoseph Mingrone u_int length;
2313c602fabSXin LI uint8_t count;
2323c602fabSXin LI uint8_t period;
2333c602fabSXin LI uint8_t bitmap_control;
2343c602fabSXin LI uint8_t bitmap[251];
2353c602fabSXin LI };
2363c602fabSXin LI
2373c602fabSXin LI #define E_SSID 0
2383c602fabSXin LI #define E_RATES 1
2393c602fabSXin LI #define E_FH 2
2403c602fabSXin LI #define E_DS 3
2413c602fabSXin LI #define E_CF 4
2423c602fabSXin LI #define E_TIM 5
2433c602fabSXin LI #define E_IBSS 6
2443c602fabSXin LI /* reserved 7 */
2453c602fabSXin LI /* reserved 8 */
2463c602fabSXin LI /* reserved 9 */
2473c602fabSXin LI /* reserved 10 */
2483c602fabSXin LI /* reserved 11 */
2493c602fabSXin LI /* reserved 12 */
2503c602fabSXin LI /* reserved 13 */
2513c602fabSXin LI /* reserved 14 */
2523c602fabSXin LI /* reserved 15 */
2533c602fabSXin LI /* reserved 16 */
2543c602fabSXin LI
2553c602fabSXin LI #define E_CHALLENGE 16
2563c602fabSXin LI /* reserved 17 */
2573c602fabSXin LI /* reserved 18 */
2583c602fabSXin LI /* reserved 19 */
2593c602fabSXin LI /* reserved 16 */
2603c602fabSXin LI /* reserved 16 */
2613c602fabSXin LI
2623c602fabSXin LI
2633c602fabSXin LI struct mgmt_body_t {
2643c602fabSXin LI uint8_t timestamp[IEEE802_11_TSTAMP_LEN];
2653c602fabSXin LI uint16_t beacon_interval;
2663c602fabSXin LI uint16_t listen_interval;
2673c602fabSXin LI uint16_t status_code;
2683c602fabSXin LI uint16_t aid;
2693c602fabSXin LI u_char ap[IEEE802_11_AP_LEN];
2703c602fabSXin LI uint16_t reason_code;
2713c602fabSXin LI uint16_t auth_alg;
2723c602fabSXin LI uint16_t auth_trans_seq_num;
2733c602fabSXin LI int challenge_present;
2743c602fabSXin LI struct challenge_t challenge;
2753c602fabSXin LI uint16_t capability_info;
2763c602fabSXin LI int ssid_present;
2773c602fabSXin LI struct ssid_t ssid;
2783c602fabSXin LI int rates_present;
2793c602fabSXin LI struct rates_t rates;
2803c602fabSXin LI int ds_present;
2813c602fabSXin LI struct ds_t ds;
2823c602fabSXin LI int cf_present;
2833c602fabSXin LI struct cf_t cf;
2843c602fabSXin LI int fh_present;
2853c602fabSXin LI struct fh_t fh;
2863c602fabSXin LI int tim_present;
2873c602fabSXin LI struct tim_t tim;
2883c602fabSXin LI };
2893c602fabSXin LI
2903340d773SGleb Smirnoff struct ctrl_control_wrapper_hdr_t {
291ee67461eSJoseph Mingrone nd_uint16_t fc;
292ee67461eSJoseph Mingrone nd_uint16_t duration;
293ee67461eSJoseph Mingrone nd_mac_addr addr1;
294ee67461eSJoseph Mingrone nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN];
295ee67461eSJoseph Mingrone nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN];
2963340d773SGleb Smirnoff };
2973340d773SGleb Smirnoff
2983340d773SGleb Smirnoff #define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
2993340d773SGleb Smirnoff IEEE802_11_ADDR1_LEN+\
3003340d773SGleb Smirnoff IEEE802_11_CARRIED_FC_LEN+\
3013340d773SGleb Smirnoff IEEE802_11_HT_CONTROL_LEN)
3023340d773SGleb Smirnoff
3033340d773SGleb Smirnoff struct ctrl_rts_hdr_t {
304ee67461eSJoseph Mingrone nd_uint16_t fc;
305ee67461eSJoseph Mingrone nd_uint16_t duration;
306ee67461eSJoseph Mingrone nd_mac_addr ra;
307ee67461eSJoseph Mingrone nd_mac_addr ta;
3083c602fabSXin LI };
3093c602fabSXin LI
3103c602fabSXin LI #define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
3113c602fabSXin LI IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
3123c602fabSXin LI
3133340d773SGleb Smirnoff struct ctrl_cts_hdr_t {
314ee67461eSJoseph Mingrone nd_uint16_t fc;
315ee67461eSJoseph Mingrone nd_uint16_t duration;
316ee67461eSJoseph Mingrone nd_mac_addr ra;
3173c602fabSXin LI };
3183c602fabSXin LI
3193c602fabSXin LI #define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
3203c602fabSXin LI
3213340d773SGleb Smirnoff struct ctrl_ack_hdr_t {
322ee67461eSJoseph Mingrone nd_uint16_t fc;
323ee67461eSJoseph Mingrone nd_uint16_t duration;
324ee67461eSJoseph Mingrone nd_mac_addr ra;
3253c602fabSXin LI };
3263c602fabSXin LI
3273c602fabSXin LI #define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
3283c602fabSXin LI
3293340d773SGleb Smirnoff struct ctrl_ps_poll_hdr_t {
330ee67461eSJoseph Mingrone nd_uint16_t fc;
331ee67461eSJoseph Mingrone nd_uint16_t aid;
332ee67461eSJoseph Mingrone nd_mac_addr bssid;
333ee67461eSJoseph Mingrone nd_mac_addr ta;
3343c602fabSXin LI };
3353c602fabSXin LI
3363c602fabSXin LI #define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
3373c602fabSXin LI IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN)
3383c602fabSXin LI
3393340d773SGleb Smirnoff struct ctrl_end_hdr_t {
340ee67461eSJoseph Mingrone nd_uint16_t fc;
341ee67461eSJoseph Mingrone nd_uint16_t duration;
342ee67461eSJoseph Mingrone nd_mac_addr ra;
343ee67461eSJoseph Mingrone nd_mac_addr bssid;
3443c602fabSXin LI };
3453c602fabSXin LI
3463c602fabSXin LI #define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
3473c602fabSXin LI IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
3483c602fabSXin LI
3493340d773SGleb Smirnoff struct ctrl_end_ack_hdr_t {
350ee67461eSJoseph Mingrone nd_uint16_t fc;
351ee67461eSJoseph Mingrone nd_uint16_t duration;
352ee67461eSJoseph Mingrone nd_mac_addr ra;
353ee67461eSJoseph Mingrone nd_mac_addr bssid;
3543c602fabSXin LI };
3553c602fabSXin LI
3563c602fabSXin LI #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
3573c602fabSXin LI IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
3583c602fabSXin LI
3593340d773SGleb Smirnoff struct ctrl_ba_hdr_t {
360ee67461eSJoseph Mingrone nd_uint16_t fc;
361ee67461eSJoseph Mingrone nd_uint16_t duration;
362ee67461eSJoseph Mingrone nd_mac_addr ra;
363*0a7e5f1fSJoseph Mingrone nd_mac_addr ta;
3643c602fabSXin LI };
3653c602fabSXin LI
366*0a7e5f1fSJoseph Mingrone #define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
367*0a7e5f1fSJoseph Mingrone IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
3683c602fabSXin LI
3693340d773SGleb Smirnoff struct ctrl_bar_hdr_t {
370ee67461eSJoseph Mingrone nd_uint16_t fc;
371ee67461eSJoseph Mingrone nd_uint16_t dur;
372ee67461eSJoseph Mingrone nd_mac_addr ra;
373ee67461eSJoseph Mingrone nd_mac_addr ta;
374ee67461eSJoseph Mingrone nd_uint16_t ctl;
375ee67461eSJoseph Mingrone nd_uint16_t seq;
3763c602fabSXin LI };
3773c602fabSXin LI
3783c602fabSXin LI #define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
3793c602fabSXin LI IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\
3803c602fabSXin LI IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN)
3813c602fabSXin LI
3823c602fabSXin LI struct meshcntl_t {
383ee67461eSJoseph Mingrone nd_uint8_t flags;
384ee67461eSJoseph Mingrone nd_uint8_t ttl;
385ee67461eSJoseph Mingrone nd_uint32_t seq;
386ee67461eSJoseph Mingrone nd_mac_addr addr4;
387ee67461eSJoseph Mingrone nd_mac_addr addr5;
388ee67461eSJoseph Mingrone nd_mac_addr addr6;
3893c602fabSXin LI };
3903c602fabSXin LI
3913c602fabSXin LI #define IV_IV(iv) ((iv) & 0xFFFFFF)
3923c602fabSXin LI #define IV_PAD(iv) (((iv) >> 24) & 0x3F)
3933c602fabSXin LI #define IV_KEYID(iv) (((iv) >> 30) & 0x03)
3943c602fabSXin LI
395abf25193SMax Laier #define PRINT_SSID(p) \
39627df3f5dSRui Paulo if (p.ssid_present) { \
397ee67461eSJoseph Mingrone ND_PRINT(" ("); \
398ee67461eSJoseph Mingrone fn_print_str(ndo, p.ssid.ssid); \
399ee67461eSJoseph Mingrone ND_PRINT(")"); \
400abf25193SMax Laier }
401abf25193SMax Laier
4021de50e9fSSam Leffler #define PRINT_RATE(_sep, _r, _suf) \
403ee67461eSJoseph Mingrone ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
4049afd0c29SBill Fenner #define PRINT_RATES(p) \
40527df3f5dSRui Paulo if (p.rates_present) { \
4065b0fe478SBruce M Simpson const char *sep = " ["; \
407*0a7e5f1fSJoseph Mingrone if (p.rates.length != 0) { \
408*0a7e5f1fSJoseph Mingrone for (u_int z = 0; z < p.rates.length ; z++) { \
4091de50e9fSSam Leffler PRINT_RATE(sep, p.rates.rate[z], \
4101de50e9fSSam Leffler (p.rates.rate[z] & 0x80 ? "*" : "")); \
4119afd0c29SBill Fenner sep = " "; \
4129afd0c29SBill Fenner } \
413ee67461eSJoseph Mingrone ND_PRINT(" Mbit]"); \
414*0a7e5f1fSJoseph Mingrone } \
415abf25193SMax Laier }
416abf25193SMax Laier
417abf25193SMax Laier #define PRINT_DS_CHANNEL(p) \
41827df3f5dSRui Paulo if (p.ds_present) \
419ee67461eSJoseph Mingrone ND_PRINT(" CH: %u", p.ds.channel); \
420ee67461eSJoseph Mingrone ND_PRINT("%s", \
421ee67461eSJoseph Mingrone CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
422a90e161bSBill Fenner
423cac3dcd5SXin LI #define MAX_MCS_INDEX 76
424cac3dcd5SXin LI
425cac3dcd5SXin LI /*
426cac3dcd5SXin LI * Indices are:
427cac3dcd5SXin LI *
428cac3dcd5SXin LI * the MCS index (0-76);
429cac3dcd5SXin LI *
430cac3dcd5SXin LI * 0 for 20 MHz, 1 for 40 MHz;
431cac3dcd5SXin LI *
432cac3dcd5SXin LI * 0 for a long guard interval, 1 for a short guard interval.
433cac3dcd5SXin LI */
434cac3dcd5SXin LI static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
435cac3dcd5SXin LI /* MCS 0 */
436ee67461eSJoseph Mingrone { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, },
437ee67461eSJoseph Mingrone /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, },
438cac3dcd5SXin LI },
439cac3dcd5SXin LI
440cac3dcd5SXin LI /* MCS 1 */
441ee67461eSJoseph Mingrone { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
442ee67461eSJoseph Mingrone /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
443cac3dcd5SXin LI },
444cac3dcd5SXin LI
445cac3dcd5SXin LI /* MCS 2 */
446ee67461eSJoseph Mingrone { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
447ee67461eSJoseph Mingrone /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
448cac3dcd5SXin LI },
449cac3dcd5SXin LI
450cac3dcd5SXin LI /* MCS 3 */
451ee67461eSJoseph Mingrone { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
452ee67461eSJoseph Mingrone /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
453cac3dcd5SXin LI },
454cac3dcd5SXin LI
455cac3dcd5SXin LI /* MCS 4 */
456ee67461eSJoseph Mingrone { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
457ee67461eSJoseph Mingrone /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
458cac3dcd5SXin LI },
459cac3dcd5SXin LI
460cac3dcd5SXin LI /* MCS 5 */
461ee67461eSJoseph Mingrone { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
462ee67461eSJoseph Mingrone /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
463cac3dcd5SXin LI },
464cac3dcd5SXin LI
465cac3dcd5SXin LI /* MCS 6 */
466ee67461eSJoseph Mingrone { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
467ee67461eSJoseph Mingrone /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
468cac3dcd5SXin LI },
469cac3dcd5SXin LI
470cac3dcd5SXin LI /* MCS 7 */
471ee67461eSJoseph Mingrone { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
472ee67461eSJoseph Mingrone /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
473cac3dcd5SXin LI },
474cac3dcd5SXin LI
475cac3dcd5SXin LI /* MCS 8 */
476ee67461eSJoseph Mingrone { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
477ee67461eSJoseph Mingrone /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
478cac3dcd5SXin LI },
479cac3dcd5SXin LI
480cac3dcd5SXin LI /* MCS 9 */
481ee67461eSJoseph Mingrone { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
482ee67461eSJoseph Mingrone /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
483cac3dcd5SXin LI },
484cac3dcd5SXin LI
485cac3dcd5SXin LI /* MCS 10 */
486ee67461eSJoseph Mingrone { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
487ee67461eSJoseph Mingrone /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
488cac3dcd5SXin LI },
489cac3dcd5SXin LI
490cac3dcd5SXin LI /* MCS 11 */
491ee67461eSJoseph Mingrone { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
492ee67461eSJoseph Mingrone /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
493cac3dcd5SXin LI },
494cac3dcd5SXin LI
495cac3dcd5SXin LI /* MCS 12 */
496ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
497ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
498cac3dcd5SXin LI },
499cac3dcd5SXin LI
500cac3dcd5SXin LI /* MCS 13 */
501ee67461eSJoseph Mingrone { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
502ee67461eSJoseph Mingrone /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
503cac3dcd5SXin LI },
504cac3dcd5SXin LI
505cac3dcd5SXin LI /* MCS 14 */
506ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
507ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
508cac3dcd5SXin LI },
509cac3dcd5SXin LI
510cac3dcd5SXin LI /* MCS 15 */
511ee67461eSJoseph Mingrone { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
512ee67461eSJoseph Mingrone /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
513cac3dcd5SXin LI },
514cac3dcd5SXin LI
515cac3dcd5SXin LI /* MCS 16 */
516ee67461eSJoseph Mingrone { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
517ee67461eSJoseph Mingrone /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
518cac3dcd5SXin LI },
519cac3dcd5SXin LI
520cac3dcd5SXin LI /* MCS 17 */
521ee67461eSJoseph Mingrone { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
522ee67461eSJoseph Mingrone /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
523cac3dcd5SXin LI },
524cac3dcd5SXin LI
525cac3dcd5SXin LI /* MCS 18 */
526ee67461eSJoseph Mingrone { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
527ee67461eSJoseph Mingrone /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
528cac3dcd5SXin LI },
529cac3dcd5SXin LI
530cac3dcd5SXin LI /* MCS 19 */
531ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
532ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
533cac3dcd5SXin LI },
534cac3dcd5SXin LI
535cac3dcd5SXin LI /* MCS 20 */
536ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
537ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
538cac3dcd5SXin LI },
539cac3dcd5SXin LI
540cac3dcd5SXin LI /* MCS 21 */
541ee67461eSJoseph Mingrone { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
542ee67461eSJoseph Mingrone /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
543cac3dcd5SXin LI },
544cac3dcd5SXin LI
545cac3dcd5SXin LI /* MCS 22 */
546ee67461eSJoseph Mingrone { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
547ee67461eSJoseph Mingrone /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
548cac3dcd5SXin LI },
549cac3dcd5SXin LI
550cac3dcd5SXin LI /* MCS 23 */
551ee67461eSJoseph Mingrone { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
552ee67461eSJoseph Mingrone /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
553cac3dcd5SXin LI },
554cac3dcd5SXin LI
555cac3dcd5SXin LI /* MCS 24 */
556ee67461eSJoseph Mingrone { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
557ee67461eSJoseph Mingrone /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
558cac3dcd5SXin LI },
559cac3dcd5SXin LI
560cac3dcd5SXin LI /* MCS 25 */
561ee67461eSJoseph Mingrone { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
562ee67461eSJoseph Mingrone /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
563cac3dcd5SXin LI },
564cac3dcd5SXin LI
565cac3dcd5SXin LI /* MCS 26 */
566ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
567ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
568cac3dcd5SXin LI },
569cac3dcd5SXin LI
570cac3dcd5SXin LI /* MCS 27 */
571ee67461eSJoseph Mingrone { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
572ee67461eSJoseph Mingrone /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
573cac3dcd5SXin LI },
574cac3dcd5SXin LI
575cac3dcd5SXin LI /* MCS 28 */
576ee67461eSJoseph Mingrone { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
577ee67461eSJoseph Mingrone /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
578cac3dcd5SXin LI },
579cac3dcd5SXin LI
580cac3dcd5SXin LI /* MCS 29 */
581ee67461eSJoseph Mingrone { /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, },
582ee67461eSJoseph Mingrone /* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, },
583cac3dcd5SXin LI },
584cac3dcd5SXin LI
585cac3dcd5SXin LI /* MCS 30 */
586ee67461eSJoseph Mingrone { /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, },
587ee67461eSJoseph Mingrone /* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, },
588cac3dcd5SXin LI },
589cac3dcd5SXin LI
590cac3dcd5SXin LI /* MCS 31 */
591ee67461eSJoseph Mingrone { /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, },
592ee67461eSJoseph Mingrone /* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, },
593cac3dcd5SXin LI },
594cac3dcd5SXin LI
595cac3dcd5SXin LI /* MCS 32 */
596ee67461eSJoseph Mingrone { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */
597ee67461eSJoseph Mingrone /* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, },
598cac3dcd5SXin LI },
599cac3dcd5SXin LI
600cac3dcd5SXin LI /* MCS 33 */
601ee67461eSJoseph Mingrone { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
602ee67461eSJoseph Mingrone /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
603cac3dcd5SXin LI },
604cac3dcd5SXin LI
605cac3dcd5SXin LI /* MCS 34 */
606ee67461eSJoseph Mingrone { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
607ee67461eSJoseph Mingrone /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
608cac3dcd5SXin LI },
609cac3dcd5SXin LI
610cac3dcd5SXin LI /* MCS 35 */
611ee67461eSJoseph Mingrone { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
612ee67461eSJoseph Mingrone /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
613cac3dcd5SXin LI },
614cac3dcd5SXin LI
615cac3dcd5SXin LI /* MCS 36 */
616ee67461eSJoseph Mingrone { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
617ee67461eSJoseph Mingrone /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
618cac3dcd5SXin LI },
619cac3dcd5SXin LI
620cac3dcd5SXin LI /* MCS 37 */
621ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
622ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
623cac3dcd5SXin LI },
624cac3dcd5SXin LI
625cac3dcd5SXin LI /* MCS 38 */
626ee67461eSJoseph Mingrone { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
627ee67461eSJoseph Mingrone /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
628cac3dcd5SXin LI },
629cac3dcd5SXin LI
630cac3dcd5SXin LI /* MCS 39 */
631ee67461eSJoseph Mingrone { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
632ee67461eSJoseph Mingrone /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
633cac3dcd5SXin LI },
634cac3dcd5SXin LI
635cac3dcd5SXin LI /* MCS 40 */
636ee67461eSJoseph Mingrone { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
637ee67461eSJoseph Mingrone /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
638cac3dcd5SXin LI },
639cac3dcd5SXin LI
640cac3dcd5SXin LI /* MCS 41 */
641ee67461eSJoseph Mingrone { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
642ee67461eSJoseph Mingrone /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
643cac3dcd5SXin LI },
644cac3dcd5SXin LI
645cac3dcd5SXin LI /* MCS 42 */
646ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
647ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
648cac3dcd5SXin LI },
649cac3dcd5SXin LI
650cac3dcd5SXin LI /* MCS 43 */
651ee67461eSJoseph Mingrone { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
652ee67461eSJoseph Mingrone /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
653cac3dcd5SXin LI },
654cac3dcd5SXin LI
655cac3dcd5SXin LI /* MCS 44 */
656ee67461eSJoseph Mingrone { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
657ee67461eSJoseph Mingrone /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
658cac3dcd5SXin LI },
659cac3dcd5SXin LI
660cac3dcd5SXin LI /* MCS 45 */
661ee67461eSJoseph Mingrone { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
662ee67461eSJoseph Mingrone /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
663cac3dcd5SXin LI },
664cac3dcd5SXin LI
665cac3dcd5SXin LI /* MCS 46 */
666ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
667ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
668cac3dcd5SXin LI },
669cac3dcd5SXin LI
670cac3dcd5SXin LI /* MCS 47 */
671ee67461eSJoseph Mingrone { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
672ee67461eSJoseph Mingrone /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
673cac3dcd5SXin LI },
674cac3dcd5SXin LI
675cac3dcd5SXin LI /* MCS 48 */
676ee67461eSJoseph Mingrone { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
677ee67461eSJoseph Mingrone /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
678cac3dcd5SXin LI },
679cac3dcd5SXin LI
680cac3dcd5SXin LI /* MCS 49 */
681ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
682ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
683cac3dcd5SXin LI },
684cac3dcd5SXin LI
685cac3dcd5SXin LI /* MCS 50 */
686ee67461eSJoseph Mingrone { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
687ee67461eSJoseph Mingrone /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
688cac3dcd5SXin LI },
689cac3dcd5SXin LI
690cac3dcd5SXin LI /* MCS 51 */
691ee67461eSJoseph Mingrone { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
692ee67461eSJoseph Mingrone /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
693cac3dcd5SXin LI },
694cac3dcd5SXin LI
695cac3dcd5SXin LI /* MCS 52 */
696ee67461eSJoseph Mingrone { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
697ee67461eSJoseph Mingrone /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
698cac3dcd5SXin LI },
699cac3dcd5SXin LI
700cac3dcd5SXin LI /* MCS 53 */
701ee67461eSJoseph Mingrone { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
702ee67461eSJoseph Mingrone /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
703cac3dcd5SXin LI },
704cac3dcd5SXin LI
705cac3dcd5SXin LI /* MCS 54 */
706ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
707ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
708cac3dcd5SXin LI },
709cac3dcd5SXin LI
710cac3dcd5SXin LI /* MCS 55 */
711ee67461eSJoseph Mingrone { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
712ee67461eSJoseph Mingrone /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
713cac3dcd5SXin LI },
714cac3dcd5SXin LI
715cac3dcd5SXin LI /* MCS 56 */
716ee67461eSJoseph Mingrone { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
717ee67461eSJoseph Mingrone /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
718cac3dcd5SXin LI },
719cac3dcd5SXin LI
720cac3dcd5SXin LI /* MCS 57 */
721ee67461eSJoseph Mingrone { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
722ee67461eSJoseph Mingrone /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
723cac3dcd5SXin LI },
724cac3dcd5SXin LI
725cac3dcd5SXin LI /* MCS 58 */
726ee67461eSJoseph Mingrone { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
727ee67461eSJoseph Mingrone /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
728cac3dcd5SXin LI },
729cac3dcd5SXin LI
730cac3dcd5SXin LI /* MCS 59 */
731ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
732ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
733cac3dcd5SXin LI },
734cac3dcd5SXin LI
735cac3dcd5SXin LI /* MCS 60 */
736ee67461eSJoseph Mingrone { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
737ee67461eSJoseph Mingrone /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
738cac3dcd5SXin LI },
739cac3dcd5SXin LI
740cac3dcd5SXin LI /* MCS 61 */
741ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
742ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
743cac3dcd5SXin LI },
744cac3dcd5SXin LI
745cac3dcd5SXin LI /* MCS 62 */
746ee67461eSJoseph Mingrone { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
747ee67461eSJoseph Mingrone /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
748cac3dcd5SXin LI },
749cac3dcd5SXin LI
750cac3dcd5SXin LI /* MCS 63 */
751ee67461eSJoseph Mingrone { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
752ee67461eSJoseph Mingrone /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
753cac3dcd5SXin LI },
754cac3dcd5SXin LI
755cac3dcd5SXin LI /* MCS 64 */
756ee67461eSJoseph Mingrone { /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, },
757ee67461eSJoseph Mingrone /* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, },
758cac3dcd5SXin LI },
759cac3dcd5SXin LI
760cac3dcd5SXin LI /* MCS 65 */
761ee67461eSJoseph Mingrone { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
762ee67461eSJoseph Mingrone /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
763cac3dcd5SXin LI },
764cac3dcd5SXin LI
765cac3dcd5SXin LI /* MCS 66 */
766ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
767ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
768cac3dcd5SXin LI },
769cac3dcd5SXin LI
770cac3dcd5SXin LI /* MCS 67 */
771ee67461eSJoseph Mingrone { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
772ee67461eSJoseph Mingrone /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
773cac3dcd5SXin LI },
774cac3dcd5SXin LI
775cac3dcd5SXin LI /* MCS 68 */
776ee67461eSJoseph Mingrone { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
777ee67461eSJoseph Mingrone /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
778cac3dcd5SXin LI },
779cac3dcd5SXin LI
780cac3dcd5SXin LI /* MCS 69 */
781ee67461eSJoseph Mingrone { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
782ee67461eSJoseph Mingrone /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
783cac3dcd5SXin LI },
784cac3dcd5SXin LI
785cac3dcd5SXin LI /* MCS 70 */
786ee67461eSJoseph Mingrone { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
787ee67461eSJoseph Mingrone /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
788cac3dcd5SXin LI },
789cac3dcd5SXin LI
790cac3dcd5SXin LI /* MCS 71 */
791ee67461eSJoseph Mingrone { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
792ee67461eSJoseph Mingrone /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
793cac3dcd5SXin LI },
794cac3dcd5SXin LI
795cac3dcd5SXin LI /* MCS 72 */
796ee67461eSJoseph Mingrone { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
797ee67461eSJoseph Mingrone /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
798cac3dcd5SXin LI },
799cac3dcd5SXin LI
800cac3dcd5SXin LI /* MCS 73 */
801ee67461eSJoseph Mingrone { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
802ee67461eSJoseph Mingrone /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
803cac3dcd5SXin LI },
804cac3dcd5SXin LI
805cac3dcd5SXin LI /* MCS 74 */
806ee67461eSJoseph Mingrone { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
807ee67461eSJoseph Mingrone /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
808cac3dcd5SXin LI },
809cac3dcd5SXin LI
810cac3dcd5SXin LI /* MCS 75 */
811ee67461eSJoseph Mingrone { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
812ee67461eSJoseph Mingrone /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
813cac3dcd5SXin LI },
814cac3dcd5SXin LI
815cac3dcd5SXin LI /* MCS 76 */
816ee67461eSJoseph Mingrone { /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, },
817ee67461eSJoseph Mingrone /* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, },
818cac3dcd5SXin LI },
8196efb4aa1SSam Leffler };
8206efb4aa1SSam Leffler
821a90e161bSBill Fenner static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
822ee67461eSJoseph Mingrone #define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0]))
823a90e161bSBill Fenner
824a90e161bSBill Fenner static const char *status_text[] = {
825d09a7e67SXin LI "Successful", /* 0 */
826a90e161bSBill Fenner "Unspecified failure", /* 1 */
827ee67461eSJoseph Mingrone "TDLS wakeup schedule rejected but alternative schedule "
828ee67461eSJoseph Mingrone "provided", /* 2 */
829ee67461eSJoseph Mingrone "TDLS wakeup schedule rejected",/* 3 */
830a90e161bSBill Fenner "Reserved", /* 4 */
831ee67461eSJoseph Mingrone "Security disabled", /* 5 */
832ee67461eSJoseph Mingrone "Unacceptable lifetime", /* 6 */
833ee67461eSJoseph Mingrone "Not in same BSS", /* 7 */
834a90e161bSBill Fenner "Reserved", /* 8 */
835a90e161bSBill Fenner "Reserved", /* 9 */
8360b73e403SSam Leffler "Cannot Support all requested capabilities in the Capability "
8370b73e403SSam Leffler "Information field", /* 10 */
8380b73e403SSam Leffler "Reassociation denied due to inability to confirm that association "
8390b73e403SSam Leffler "exists", /* 11 */
840ee67461eSJoseph Mingrone "Association denied due to reason outside the scope of this "
8410b73e403SSam Leffler "standard", /* 12 */
842ee67461eSJoseph Mingrone "Responding STA does not support the specified authentication "
8430b73e403SSam Leffler "algorithm", /* 13 */
8440b73e403SSam Leffler "Received an Authentication frame with authentication transaction "
845a90e161bSBill Fenner "sequence number out of expected sequence", /* 14 */
846a90e161bSBill Fenner "Authentication rejected because of challenge failure", /* 15 */
8470b73e403SSam Leffler "Authentication rejected due to timeout waiting for next frame in "
8480b73e403SSam Leffler "sequence", /* 16 */
849ee67461eSJoseph Mingrone "Association denied because AP is unable to handle "
850ee67461eSJoseph Mingrone "additional associated STAs", /* 17 */
851ee67461eSJoseph Mingrone "Association denied due to requesting STA not supporting "
852ee67461eSJoseph Mingrone "all of the data rates in the BSSBasicRateSet parameter, "
853ee67461eSJoseph Mingrone "the Basic HT-MCS Set field of the HT Operation "
854ee67461eSJoseph Mingrone "parameter, or the Basic VHT-MCS and NSS Set field in "
855ee67461eSJoseph Mingrone "the VHT Operation parameter", /* 18 */
856ee67461eSJoseph Mingrone "Association denied due to requesting STA not supporting "
857ee67461eSJoseph Mingrone "the short preamble option", /* 19 */
858ee67461eSJoseph Mingrone "Reserved", /* 20 */
859ee67461eSJoseph Mingrone "Reserved", /* 21 */
8600b73e403SSam Leffler "Association request rejected because Spectrum Management "
8610b73e403SSam Leffler "capability is required", /* 22 */
8620b73e403SSam Leffler "Association request rejected because the information in the "
8630b73e403SSam Leffler "Power Capability element is unacceptable", /* 23 */
8640b73e403SSam Leffler "Association request rejected because the information in the "
8650b73e403SSam Leffler "Supported Channels element is unacceptable", /* 24 */
866ee67461eSJoseph Mingrone "Association denied due to requesting STA not supporting "
867ee67461eSJoseph Mingrone "the Short Slot Time option", /* 25 */
868ee67461eSJoseph Mingrone "Reserved", /* 26 */
8690b73e403SSam Leffler "Association denied because the requested STA does not support HT "
8700b73e403SSam Leffler "features", /* 27 */
871ee67461eSJoseph Mingrone "R0KH unreachable", /* 28 */
872ee67461eSJoseph Mingrone "Association denied because the requesting STA does not "
873ee67461eSJoseph Mingrone "support the phased coexistence operation (PCO) "
874ee67461eSJoseph Mingrone "transition time required by the AP", /* 29 */
875ee67461eSJoseph Mingrone "Association request rejected temporarily; try again "
876ee67461eSJoseph Mingrone "later", /* 30 */
877ee67461eSJoseph Mingrone "Robust management frame policy violation", /* 31 */
8780b73e403SSam Leffler "Unspecified, QoS-related failure", /* 32 */
879ee67461eSJoseph Mingrone "Association denied because QoS AP or PCP has "
880ee67461eSJoseph Mingrone "insufficient bandwidth to handle another QoS "
881ee67461eSJoseph Mingrone "STA", /* 33 */
8820b73e403SSam Leffler "Association denied due to excessive frame loss rates and/or "
8830b73e403SSam Leffler "poor conditions on current operating channel", /* 34 */
884ee67461eSJoseph Mingrone "Association (with QoS BSS) denied because the requesting STA "
885ee67461eSJoseph Mingrone "does not support the QoS facility", /* 35 */
886ee67461eSJoseph Mingrone "Reserved", /* 36 */
8870b73e403SSam Leffler "The request has been declined", /* 37 */
8880b73e403SSam Leffler "The request has not been successful as one or more parameters "
8890b73e403SSam Leffler "have invalid values", /* 38 */
890ee67461eSJoseph Mingrone "The allocation or TS has not been created because the request "
891ee67461eSJoseph Mingrone "cannot be honored; however, a suggested TSPEC/DMG TSPEC is "
892ee67461eSJoseph Mingrone "provided so that the initiating STA can attempt to set "
893ee67461eSJoseph Mingrone "another allocation or TS with the suggested changes to the "
894ee67461eSJoseph Mingrone "TSPEC/DMG TSPEC", /* 39 */
895ee67461eSJoseph Mingrone "Invalid element, i.e., an element defined in this standard "
896ee67461eSJoseph Mingrone "for which the content does not meet the specifications in "
897ee67461eSJoseph Mingrone "Clause 9", /* 40 */
898ee67461eSJoseph Mingrone "Invalid group cipher", /* 41 */
899ee67461eSJoseph Mingrone "Invalid pairwise cipher", /* 42 */
900ee67461eSJoseph Mingrone "Invalid AKMP", /* 43 */
901ee67461eSJoseph Mingrone "Unsupported RSNE version", /* 44 */
902ee67461eSJoseph Mingrone "Invalid RSNE capabilities", /* 45 */
903ee67461eSJoseph Mingrone "Cipher suite rejected because of security policy", /* 46 */
904ee67461eSJoseph Mingrone "The TS or allocation has not been created; however, the "
905ee67461eSJoseph Mingrone "HC or PCP might be capable of creating a TS or "
906ee67461eSJoseph Mingrone "allocation, in response to a request, after the time "
907ee67461eSJoseph Mingrone "indicated in the TS Delay element", /* 47 */
9080b73e403SSam Leffler "Direct Link is not allowed in the BSS by policy", /* 48 */
909ee67461eSJoseph Mingrone "The Destination STA is not present within this BSS", /* 49 */
910ee67461eSJoseph Mingrone "The Destination STA is not a QoS STA", /* 50 */
9110b73e403SSam Leffler
912ee67461eSJoseph Mingrone "Association denied because the listen interval is "
913ee67461eSJoseph Mingrone "too large", /* 51 */
914ee67461eSJoseph Mingrone "Invalid FT Action frame count", /* 52 */
915ee67461eSJoseph Mingrone "Invalid pairwise master key identifier (PMKID)", /* 53 */
916ee67461eSJoseph Mingrone "Invalid MDE", /* 54 */
917ee67461eSJoseph Mingrone "Invalid FTE", /* 55 */
918ee67461eSJoseph Mingrone "Requested TCLAS processing is not supported by the AP "
919ee67461eSJoseph Mingrone "or PCP", /* 56 */
920ee67461eSJoseph Mingrone "The AP or PCP has insufficient TCLAS processing "
921ee67461eSJoseph Mingrone "resources to satisfy the request", /* 57 */
922ee67461eSJoseph Mingrone "The TS has not been created because the request "
923ee67461eSJoseph Mingrone "cannot be honored; however, the HC or PCP suggests "
924ee67461eSJoseph Mingrone "that the STA transition to a different BSS to set up "
925ee67461eSJoseph Mingrone "the TS", /* 58 */
926ee67461eSJoseph Mingrone "GAS Advertisement Protocol not supported", /* 59 */
927ee67461eSJoseph Mingrone "No outstanding GAS request", /* 60 */
928ee67461eSJoseph Mingrone "GAS Response not received from the Advertisement "
929ee67461eSJoseph Mingrone "Server", /* 61 */
930ee67461eSJoseph Mingrone "STA timed out waiting for GAS Query Response", /* 62 */
931ee67461eSJoseph Mingrone "LARGE GAS Response is larger than query response "
932ee67461eSJoseph Mingrone "length limit", /* 63 */
933ee67461eSJoseph Mingrone "Request refused because home network does not support "
934ee67461eSJoseph Mingrone "request", /* 64 */
935ee67461eSJoseph Mingrone "Advertisement Server in the network is not currently "
936ee67461eSJoseph Mingrone "reachable", /* 65 */
937ee67461eSJoseph Mingrone "Reserved", /* 66 */
938ee67461eSJoseph Mingrone "Request refused due to permissions received via SSPN "
939ee67461eSJoseph Mingrone "interface", /* 67 */
940ee67461eSJoseph Mingrone "Request refused because the AP or PCP does not "
941ee67461eSJoseph Mingrone "support unauthenticated access", /* 68 */
942ee67461eSJoseph Mingrone "Reserved", /* 69 */
943ee67461eSJoseph Mingrone "Reserved", /* 70 */
944ee67461eSJoseph Mingrone "Reserved", /* 71 */
945ee67461eSJoseph Mingrone "Invalid contents of RSNE", /* 72 */
946ee67461eSJoseph Mingrone "U-APSD coexistence is not supported", /* 73 */
947ee67461eSJoseph Mingrone "Requested U-APSD coexistence mode is not supported", /* 74 */
948ee67461eSJoseph Mingrone "Requested Interval/Duration value cannot be "
949ee67461eSJoseph Mingrone "supported with U-APSD coexistence", /* 75 */
950ee67461eSJoseph Mingrone "Authentication is rejected because an Anti-Clogging "
951ee67461eSJoseph Mingrone "Token is required", /* 76 */
952ee67461eSJoseph Mingrone "Authentication is rejected because the offered "
953ee67461eSJoseph Mingrone "finite cyclic group is not supported", /* 77 */
954ee67461eSJoseph Mingrone "The TBTT adjustment request has not been successful "
955ee67461eSJoseph Mingrone "because the STA could not find an alternative TBTT", /* 78 */
956ee67461eSJoseph Mingrone "Transmission failure", /* 79 */
957ee67461eSJoseph Mingrone "Requested TCLAS Not Supported", /* 80 */
958ee67461eSJoseph Mingrone "TCLAS Resources Exhausted", /* 81 */
959ee67461eSJoseph Mingrone "Rejected with Suggested BSS transition", /* 82 */
960ee67461eSJoseph Mingrone "Reject with recommended schedule", /* 83 */
961ee67461eSJoseph Mingrone "Reject because no wakeup schedule specified", /* 84 */
962ee67461eSJoseph Mingrone "Success, the destination STA is in power save mode", /* 85 */
963ee67461eSJoseph Mingrone "FST pending, in process of admitting FST session", /* 86 */
964ee67461eSJoseph Mingrone "Performing FST now", /* 87 */
965ee67461eSJoseph Mingrone "FST pending, gap(s) in block ack window", /* 88 */
966ee67461eSJoseph Mingrone "Reject because of U-PID setting", /* 89 */
967ee67461eSJoseph Mingrone "Reserved", /* 90 */
968ee67461eSJoseph Mingrone "Reserved", /* 91 */
969ee67461eSJoseph Mingrone "(Re)Association refused for some external reason", /* 92 */
970ee67461eSJoseph Mingrone "(Re)Association refused because of memory limits "
971ee67461eSJoseph Mingrone "at the AP", /* 93 */
972ee67461eSJoseph Mingrone "(Re)Association refused because emergency services "
973ee67461eSJoseph Mingrone "are not supported at the AP", /* 94 */
974ee67461eSJoseph Mingrone "GAS query response not yet received", /* 95 */
975ee67461eSJoseph Mingrone "Reject since the request is for transition to a "
976ee67461eSJoseph Mingrone "frequency band subject to DSE procedures and "
977ee67461eSJoseph Mingrone "FST Initiator is a dependent STA", /* 96 */
978ee67461eSJoseph Mingrone "Requested TCLAS processing has been terminated by "
979ee67461eSJoseph Mingrone "the AP", /* 97 */
980ee67461eSJoseph Mingrone "The TS schedule conflicts with an existing "
981ee67461eSJoseph Mingrone "schedule; an alternative schedule is provided", /* 98 */
982ee67461eSJoseph Mingrone "The association has been denied; however, one or "
983ee67461eSJoseph Mingrone "more Multi-band elements are included that can "
984ee67461eSJoseph Mingrone "be used by the receiving STA to join the BSS", /* 99 */
985ee67461eSJoseph Mingrone "The request failed due to a reservation conflict", /* 100 */
986ee67461eSJoseph Mingrone "The request failed due to exceeded MAF limit", /* 101 */
987ee67461eSJoseph Mingrone "The request failed due to exceeded MCCA track "
988ee67461eSJoseph Mingrone "limit", /* 102 */
989ee67461eSJoseph Mingrone "Association denied because the information in the"
990ee67461eSJoseph Mingrone "Spectrum Management field is unacceptable", /* 103 */
991ee67461eSJoseph Mingrone "Association denied because the requesting STA "
992ee67461eSJoseph Mingrone "does not support VHT features", /* 104 */
993ee67461eSJoseph Mingrone "Enablement denied", /* 105 */
994ee67461eSJoseph Mingrone "Enablement denied due to restriction from an "
995ee67461eSJoseph Mingrone "authorized GDB", /* 106 */
996ee67461eSJoseph Mingrone "Authorization deenabled", /* 107 */
997a90e161bSBill Fenner };
998ee67461eSJoseph Mingrone #define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0]))
999a90e161bSBill Fenner
1000a90e161bSBill Fenner static const char *reason_text[] = {
1001a90e161bSBill Fenner "Reserved", /* 0 */
1002a90e161bSBill Fenner "Unspecified reason", /* 1 */
1003a90e161bSBill Fenner "Previous authentication no longer valid", /* 2 */
1004ee67461eSJoseph Mingrone "Deauthenticated because sending STA is leaving (or has left) "
10050b73e403SSam Leffler "IBSS or ESS", /* 3 */
1006a90e161bSBill Fenner "Disassociated due to inactivity", /* 4 */
10070b73e403SSam Leffler "Disassociated because AP is unable to handle all currently "
1008ee67461eSJoseph Mingrone " associated STAs", /* 5 */
1009ee67461eSJoseph Mingrone "Class 2 frame received from nonauthenticated STA", /* 6 */
1010ee67461eSJoseph Mingrone "Class 3 frame received from nonassociated STA", /* 7 */
1011ee67461eSJoseph Mingrone "Disassociated because sending STA is leaving "
10120b73e403SSam Leffler "(or has left) BSS", /* 8 */
1013ee67461eSJoseph Mingrone "STA requesting (re)association is not authenticated with "
1014ee67461eSJoseph Mingrone "responding STA", /* 9 */
10150b73e403SSam Leffler "Disassociated because the information in the Power Capability "
10160b73e403SSam Leffler "element is unacceptable", /* 10 */
10170b73e403SSam Leffler "Disassociated because the information in the Supported Channels "
10180b73e403SSam Leffler "element is unacceptable", /* 11 */
1019ee67461eSJoseph Mingrone "Disassociated due to BSS transition management", /* 12 */
1020ee67461eSJoseph Mingrone "Invalid element, i.e., an element defined in this standard for "
1021ee67461eSJoseph Mingrone "which the content does not meet the specifications "
1022ee67461eSJoseph Mingrone "in Clause 9", /* 13 */
1023ee67461eSJoseph Mingrone "Message integrity code (MIC) failure", /* 14 */
10240b73e403SSam Leffler "4-Way Handshake timeout", /* 15 */
1025ee67461eSJoseph Mingrone "Group key handshake timeout", /* 16 */
10260b73e403SSam Leffler "Information element in 4-Way Handshake different from (Re)Association"
1027ee67461eSJoseph Mingrone "Request/Probe Response/Beacon frame", /* 17 */
1028ee67461eSJoseph Mingrone "Invalid group cipher", /* 18 */
1029ee67461eSJoseph Mingrone "Invalid pairwise cipher", /* 19 */
1030ee67461eSJoseph Mingrone "Invalid AKMP", /* 20 */
1031ee67461eSJoseph Mingrone "Unsupported RSNE version", /* 21 */
1032ee67461eSJoseph Mingrone "Invalid RSNE capabilities", /* 22 */
1033ee67461eSJoseph Mingrone "IEEE 802.1X authentication failed", /* 23 */
1034ee67461eSJoseph Mingrone "Cipher suite rejected because of the security policy", /* 24 */
1035ee67461eSJoseph Mingrone "TDLS direct-link teardown due to TDLS peer STA "
1036ee67461eSJoseph Mingrone "unreachable via the TDLS direct link", /* 25 */
1037ee67461eSJoseph Mingrone "TDLS direct-link teardown for unspecified reason", /* 26 */
1038ee67461eSJoseph Mingrone "Disassociated because session terminated by SSP request",/* 27 */
1039ee67461eSJoseph Mingrone "Disassociated because of lack of SSP roaming agreement",/* 28 */
1040ee67461eSJoseph Mingrone "Requested service rejected because of SSP cipher suite or "
1041ee67461eSJoseph Mingrone "AKM requirement", /* 29 */
1042ee67461eSJoseph Mingrone "Requested service not authorized in this location", /* 30 */
10430b73e403SSam Leffler "TS deleted because QoS AP lacks sufficient bandwidth for this "
10440b73e403SSam Leffler "QoS STA due to a change in BSS service characteristics or "
10450b73e403SSam Leffler "operational mode (e.g. an HT BSS change from 40 MHz channel "
10460b73e403SSam Leffler "to 20 MHz channel)", /* 31 */
10470b73e403SSam Leffler "Disassociated for unspecified, QoS-related reason", /* 32 */
10480b73e403SSam Leffler "Disassociated because QoS AP lacks sufficient bandwidth for this "
10490b73e403SSam Leffler "QoS STA", /* 33 */
10500b73e403SSam Leffler "Disassociated because of excessive number of frames that need to be "
1051ee67461eSJoseph Mingrone "acknowledged, but are not acknowledged due to AP transmissions "
10520b73e403SSam Leffler "and/or poor channel conditions", /* 34 */
10530b73e403SSam Leffler "Disassociated because STA is transmitting outside the limits "
10540b73e403SSam Leffler "of its TXOPs", /* 35 */
10550b73e403SSam Leffler "Requested from peer STA as the STA is leaving the BSS "
10560b73e403SSam Leffler "(or resetting)", /* 36 */
10570b73e403SSam Leffler "Requested from peer STA as it does not want to use the "
10580b73e403SSam Leffler "mechanism", /* 37 */
10590b73e403SSam Leffler "Requested from peer STA as the STA received frames using the "
10600b73e403SSam Leffler "mechanism for which a set up is required", /* 38 */
10610b73e403SSam Leffler "Requested from peer STA due to time out", /* 39 */
10620b73e403SSam Leffler "Reserved", /* 40 */
10630b73e403SSam Leffler "Reserved", /* 41 */
10640b73e403SSam Leffler "Reserved", /* 42 */
10650b73e403SSam Leffler "Reserved", /* 43 */
10660b73e403SSam Leffler "Reserved", /* 44 */
10670b73e403SSam Leffler "Peer STA does not support the requested cipher suite", /* 45 */
1068ee67461eSJoseph Mingrone "In a DLS Teardown frame: The teardown was initiated by the "
1069ee67461eSJoseph Mingrone "DLS peer. In a Disassociation frame: Disassociated because "
1070ee67461eSJoseph Mingrone "authorized access limit reached", /* 46 */
1071ee67461eSJoseph Mingrone "In a DLS Teardown frame: The teardown was initiated by the "
1072ee67461eSJoseph Mingrone "AP. In a Disassociation frame: Disassociated due to external "
1073ee67461eSJoseph Mingrone "service requirements", /* 47 */
1074ee67461eSJoseph Mingrone "Invalid FT Action frame count", /* 48 */
1075ee67461eSJoseph Mingrone "Invalid pairwise master key identifier (PMKID)", /* 49 */
1076ee67461eSJoseph Mingrone "Invalid MDE", /* 50 */
1077ee67461eSJoseph Mingrone "Invalid FTE", /* 51 */
1078ee67461eSJoseph Mingrone "Mesh peering canceled for unknown reasons", /* 52 */
1079ee67461eSJoseph Mingrone "The mesh STA has reached the supported maximum number of "
1080ee67461eSJoseph Mingrone "peer mesh STAs", /* 53 */
1081ee67461eSJoseph Mingrone "The received information violates the Mesh Configuration "
1082ee67461eSJoseph Mingrone "policy configured in the mesh STA profile", /* 54 */
1083ee67461eSJoseph Mingrone "The mesh STA has received a Mesh Peering Close frame "
1084ee67461eSJoseph Mingrone "requesting to close the mesh peering", /* 55 */
1085ee67461eSJoseph Mingrone "The mesh STA has resent dot11MeshMaxRetries Mesh "
1086ee67461eSJoseph Mingrone "Peering Open frames, without receiving a Mesh Peering "
1087ee67461eSJoseph Mingrone "Confirm frame", /* 56 */
1088ee67461eSJoseph Mingrone "The confirmTimer for the mesh peering instance times out", /* 57 */
1089ee67461eSJoseph Mingrone "The mesh STA fails to unwrap the GTK or the values in the "
1090ee67461eSJoseph Mingrone "wrapped contents do not match", /* 58 */
1091ee67461eSJoseph Mingrone "The mesh STA receives inconsistent information about the "
1092ee67461eSJoseph Mingrone "mesh parameters between mesh peering Management frames", /* 59 */
1093ee67461eSJoseph Mingrone "The mesh STA fails the authenticated mesh peering exchange "
1094ee67461eSJoseph Mingrone "because due to failure in selecting either the pairwise "
1095ee67461eSJoseph Mingrone "ciphersuite or group ciphersuite", /* 60 */
1096ee67461eSJoseph Mingrone "The mesh STA does not have proxy information for this "
1097ee67461eSJoseph Mingrone "external destination", /* 61 */
1098ee67461eSJoseph Mingrone "The mesh STA does not have forwarding information for this "
1099ee67461eSJoseph Mingrone "destination", /* 62 */
1100ee67461eSJoseph Mingrone "The mesh STA determines that the link to the next hop of an "
1101ee67461eSJoseph Mingrone "active path in its forwarding information is no longer "
1102ee67461eSJoseph Mingrone "usable", /* 63 */
1103ee67461eSJoseph Mingrone "The Deauthentication frame was sent because the MAC "
1104ee67461eSJoseph Mingrone "address of the STA already exists in the mesh BSS", /* 64 */
1105ee67461eSJoseph Mingrone "The mesh STA performs channel switch to meet regulatory "
1106ee67461eSJoseph Mingrone "requirements", /* 65 */
1107ee67461eSJoseph Mingrone "The mesh STA performs channel switching with unspecified "
1108ee67461eSJoseph Mingrone "reason", /* 66 */
1109a90e161bSBill Fenner };
1110ee67461eSJoseph Mingrone #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0]))
1111a90e161bSBill Fenner
11125b0fe478SBruce M Simpson static int
wep_print(netdissect_options * ndo,const u_char * p)11133c602fabSXin LI wep_print(netdissect_options *ndo,
11143c602fabSXin LI const u_char *p)
1115a90e161bSBill Fenner {
11163c602fabSXin LI uint32_t iv;
1117a90e161bSBill Fenner
1118ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN);
1119ee67461eSJoseph Mingrone iv = GET_LE_U_4(p);
1120a90e161bSBill Fenner
1121ee67461eSJoseph Mingrone ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
1122ee67461eSJoseph Mingrone IV_KEYID(iv));
1123a90e161bSBill Fenner
1124a90e161bSBill Fenner return 1;
1125ee67461eSJoseph Mingrone trunc:
1126ee67461eSJoseph Mingrone return 0;
1127a90e161bSBill Fenner }
1128a90e161bSBill Fenner
112927df3f5dSRui Paulo static int
parse_elements(netdissect_options * ndo,struct mgmt_body_t * pbody,const u_char * p,int offset,u_int length)11303c602fabSXin LI parse_elements(netdissect_options *ndo,
11313c602fabSXin LI struct mgmt_body_t *pbody, const u_char *p, int offset,
113227df3f5dSRui Paulo u_int length)
1133a90e161bSBill Fenner {
1134cac3dcd5SXin LI u_int elementlen;
113527df3f5dSRui Paulo struct ssid_t ssid;
113627df3f5dSRui Paulo struct challenge_t challenge;
113727df3f5dSRui Paulo struct rates_t rates;
113827df3f5dSRui Paulo struct ds_t ds;
113927df3f5dSRui Paulo struct cf_t cf;
114027df3f5dSRui Paulo struct tim_t tim;
114127df3f5dSRui Paulo
1142abf25193SMax Laier /*
1143abf25193SMax Laier * We haven't seen any elements yet.
1144abf25193SMax Laier */
114527df3f5dSRui Paulo pbody->challenge_present = 0;
114627df3f5dSRui Paulo pbody->ssid_present = 0;
114727df3f5dSRui Paulo pbody->rates_present = 0;
114827df3f5dSRui Paulo pbody->ds_present = 0;
114927df3f5dSRui Paulo pbody->cf_present = 0;
115027df3f5dSRui Paulo pbody->tim_present = 0;
1151abf25193SMax Laier
115227df3f5dSRui Paulo while (length != 0) {
11533c602fabSXin LI /* Make sure we at least have the element ID and length. */
1154ee67461eSJoseph Mingrone ND_TCHECK_2(p + offset);
115527df3f5dSRui Paulo if (length < 2)
1156ee67461eSJoseph Mingrone goto trunc;
1157ee67461eSJoseph Mingrone elementlen = GET_U_1(p + offset + 1);
11583c602fabSXin LI
11593c602fabSXin LI /* Make sure we have the entire element. */
1160ee67461eSJoseph Mingrone ND_TCHECK_LEN(p + offset + 2, elementlen);
11613c602fabSXin LI if (length < elementlen + 2)
1162ee67461eSJoseph Mingrone goto trunc;
11633c602fabSXin LI
1164ee67461eSJoseph Mingrone switch (GET_U_1(p + offset)) {
11653c602fabSXin LI case E_SSID:
1166*0a7e5f1fSJoseph Mingrone ssid.length = elementlen;
11675b0fe478SBruce M Simpson offset += 2;
116827df3f5dSRui Paulo length -= 2;
116927df3f5dSRui Paulo if (ssid.length != 0) {
117027df3f5dSRui Paulo if (ssid.length > sizeof(ssid.ssid) - 1)
117127df3f5dSRui Paulo return 0;
117227df3f5dSRui Paulo memcpy(&ssid.ssid, p + offset, ssid.length);
117327df3f5dSRui Paulo offset += ssid.length;
117427df3f5dSRui Paulo length -= ssid.length;
1175abf25193SMax Laier }
117627df3f5dSRui Paulo ssid.ssid[ssid.length] = '\0';
117727df3f5dSRui Paulo /*
117827df3f5dSRui Paulo * Present and not truncated.
117927df3f5dSRui Paulo *
118027df3f5dSRui Paulo * If we haven't already seen an SSID IE,
118127df3f5dSRui Paulo * copy this one, otherwise ignore this one,
118227df3f5dSRui Paulo * so we later report the first one we saw.
118327df3f5dSRui Paulo */
118427df3f5dSRui Paulo if (!pbody->ssid_present) {
118527df3f5dSRui Paulo pbody->ssid = ssid;
118627df3f5dSRui Paulo pbody->ssid_present = 1;
118727df3f5dSRui Paulo }
1188a90e161bSBill Fenner break;
1189a90e161bSBill Fenner case E_CHALLENGE:
1190*0a7e5f1fSJoseph Mingrone challenge.length = elementlen;
11915b0fe478SBruce M Simpson offset += 2;
119227df3f5dSRui Paulo length -= 2;
119327df3f5dSRui Paulo if (challenge.length != 0) {
119427df3f5dSRui Paulo if (challenge.length >
119527df3f5dSRui Paulo sizeof(challenge.text) - 1)
119627df3f5dSRui Paulo return 0;
119727df3f5dSRui Paulo memcpy(&challenge.text, p + offset,
119827df3f5dSRui Paulo challenge.length);
119927df3f5dSRui Paulo offset += challenge.length;
120027df3f5dSRui Paulo length -= challenge.length;
1201abf25193SMax Laier }
120227df3f5dSRui Paulo challenge.text[challenge.length] = '\0';
120327df3f5dSRui Paulo /*
120427df3f5dSRui Paulo * Present and not truncated.
120527df3f5dSRui Paulo *
120627df3f5dSRui Paulo * If we haven't already seen a challenge IE,
120727df3f5dSRui Paulo * copy this one, otherwise ignore this one,
120827df3f5dSRui Paulo * so we later report the first one we saw.
120927df3f5dSRui Paulo */
121027df3f5dSRui Paulo if (!pbody->challenge_present) {
121127df3f5dSRui Paulo pbody->challenge = challenge;
121227df3f5dSRui Paulo pbody->challenge_present = 1;
121327df3f5dSRui Paulo }
1214a90e161bSBill Fenner break;
1215a90e161bSBill Fenner case E_RATES:
1216*0a7e5f1fSJoseph Mingrone rates.length = elementlen;
12175b0fe478SBruce M Simpson offset += 2;
121827df3f5dSRui Paulo length -= 2;
121927df3f5dSRui Paulo if (rates.length != 0) {
1220ee67461eSJoseph Mingrone if (rates.length > sizeof(rates.rate))
122127df3f5dSRui Paulo return 0;
122227df3f5dSRui Paulo memcpy(&rates.rate, p + offset, rates.length);
122327df3f5dSRui Paulo offset += rates.length;
122427df3f5dSRui Paulo length -= rates.length;
1225abf25193SMax Laier }
122627df3f5dSRui Paulo /*
122727df3f5dSRui Paulo * Present and not truncated.
122827df3f5dSRui Paulo *
122927df3f5dSRui Paulo * If we haven't already seen a rates IE,
123027df3f5dSRui Paulo * copy this one if it's not zero-length,
123127df3f5dSRui Paulo * otherwise ignore this one, so we later
123227df3f5dSRui Paulo * report the first one we saw.
123327df3f5dSRui Paulo *
123427df3f5dSRui Paulo * We ignore zero-length rates IEs as some
123527df3f5dSRui Paulo * devices seem to put a zero-length rates
123627df3f5dSRui Paulo * IE, followed by an SSID IE, followed by
123727df3f5dSRui Paulo * a non-zero-length rates IE into frames,
123827df3f5dSRui Paulo * even though IEEE Std 802.11-2007 doesn't
123927df3f5dSRui Paulo * seem to indicate that a zero-length rates
124027df3f5dSRui Paulo * IE is valid.
124127df3f5dSRui Paulo */
124227df3f5dSRui Paulo if (!pbody->rates_present && rates.length != 0) {
124327df3f5dSRui Paulo pbody->rates = rates;
124427df3f5dSRui Paulo pbody->rates_present = 1;
124527df3f5dSRui Paulo }
1246a90e161bSBill Fenner break;
1247a90e161bSBill Fenner case E_DS:
1248*0a7e5f1fSJoseph Mingrone ds.length = elementlen;
12493c602fabSXin LI offset += 2;
12503c602fabSXin LI length -= 2;
12513c602fabSXin LI if (ds.length != 1) {
12523c602fabSXin LI offset += ds.length;
12533c602fabSXin LI length -= ds.length;
12543c602fabSXin LI break;
12553c602fabSXin LI }
1256ee67461eSJoseph Mingrone ds.channel = GET_U_1(p + offset);
12573c602fabSXin LI offset += 1;
12583c602fabSXin LI length -= 1;
125927df3f5dSRui Paulo /*
126027df3f5dSRui Paulo * Present and not truncated.
126127df3f5dSRui Paulo *
126227df3f5dSRui Paulo * If we haven't already seen a DS IE,
126327df3f5dSRui Paulo * copy this one, otherwise ignore this one,
126427df3f5dSRui Paulo * so we later report the first one we saw.
126527df3f5dSRui Paulo */
126627df3f5dSRui Paulo if (!pbody->ds_present) {
126727df3f5dSRui Paulo pbody->ds = ds;
126827df3f5dSRui Paulo pbody->ds_present = 1;
126927df3f5dSRui Paulo }
1270a90e161bSBill Fenner break;
1271a90e161bSBill Fenner case E_CF:
1272*0a7e5f1fSJoseph Mingrone cf.length = elementlen;
12733c602fabSXin LI offset += 2;
12743c602fabSXin LI length -= 2;
12753c602fabSXin LI if (cf.length != 6) {
12763c602fabSXin LI offset += cf.length;
12773c602fabSXin LI length -= cf.length;
12783c602fabSXin LI break;
12793c602fabSXin LI }
1280ee67461eSJoseph Mingrone cf.count = GET_U_1(p + offset);
1281ee67461eSJoseph Mingrone offset += 1;
1282ee67461eSJoseph Mingrone length -= 1;
1283ee67461eSJoseph Mingrone cf.period = GET_U_1(p + offset);
1284ee67461eSJoseph Mingrone offset += 1;
1285ee67461eSJoseph Mingrone length -= 1;
1286ee67461eSJoseph Mingrone cf.max_duration = GET_LE_U_2(p + offset);
1287ee67461eSJoseph Mingrone offset += 2;
1288ee67461eSJoseph Mingrone length -= 2;
1289ee67461eSJoseph Mingrone cf.dur_remaining = GET_LE_U_2(p + offset);
1290ee67461eSJoseph Mingrone offset += 2;
1291ee67461eSJoseph Mingrone length -= 2;
129227df3f5dSRui Paulo /*
129327df3f5dSRui Paulo * Present and not truncated.
129427df3f5dSRui Paulo *
129527df3f5dSRui Paulo * If we haven't already seen a CF IE,
129627df3f5dSRui Paulo * copy this one, otherwise ignore this one,
129727df3f5dSRui Paulo * so we later report the first one we saw.
129827df3f5dSRui Paulo */
129927df3f5dSRui Paulo if (!pbody->cf_present) {
130027df3f5dSRui Paulo pbody->cf = cf;
130127df3f5dSRui Paulo pbody->cf_present = 1;
130227df3f5dSRui Paulo }
1303a90e161bSBill Fenner break;
1304a90e161bSBill Fenner case E_TIM:
1305*0a7e5f1fSJoseph Mingrone tim.length = elementlen;
13065b0fe478SBruce M Simpson offset += 2;
130727df3f5dSRui Paulo length -= 2;
1308ee67461eSJoseph Mingrone if (tim.length <= 3U) {
13093c602fabSXin LI offset += tim.length;
13103c602fabSXin LI length -= tim.length;
13113c602fabSXin LI break;
13123c602fabSXin LI }
1313ee67461eSJoseph Mingrone if (tim.length - 3U > sizeof(tim.bitmap))
131427df3f5dSRui Paulo return 0;
1315ee67461eSJoseph Mingrone tim.count = GET_U_1(p + offset);
1316ee67461eSJoseph Mingrone offset += 1;
1317ee67461eSJoseph Mingrone length -= 1;
1318ee67461eSJoseph Mingrone tim.period = GET_U_1(p + offset);
1319ee67461eSJoseph Mingrone offset += 1;
1320ee67461eSJoseph Mingrone length -= 1;
1321ee67461eSJoseph Mingrone tim.bitmap_control = GET_U_1(p + offset);
1322ee67461eSJoseph Mingrone offset += 1;
1323ee67461eSJoseph Mingrone length -= 1;
13240bff6a5aSEd Maste memcpy(tim.bitmap, p + offset, tim.length - 3);
132527df3f5dSRui Paulo offset += tim.length - 3;
132627df3f5dSRui Paulo length -= tim.length - 3;
132727df3f5dSRui Paulo /*
132827df3f5dSRui Paulo * Present and not truncated.
132927df3f5dSRui Paulo *
133027df3f5dSRui Paulo * If we haven't already seen a TIM IE,
133127df3f5dSRui Paulo * copy this one, otherwise ignore this one,
133227df3f5dSRui Paulo * so we later report the first one we saw.
133327df3f5dSRui Paulo */
133427df3f5dSRui Paulo if (!pbody->tim_present) {
133527df3f5dSRui Paulo pbody->tim = tim;
133627df3f5dSRui Paulo pbody->tim_present = 1;
133727df3f5dSRui Paulo }
1338a90e161bSBill Fenner break;
1339a90e161bSBill Fenner default:
1340a90e161bSBill Fenner #if 0
1341ee67461eSJoseph Mingrone ND_PRINT("(1) unhandled element_id (%u) ",
1342ee67461eSJoseph Mingrone GET_U_1(p + offset));
1343a90e161bSBill Fenner #endif
13443c602fabSXin LI offset += 2 + elementlen;
13453c602fabSXin LI length -= 2 + elementlen;
1346a90e161bSBill Fenner break;
1347a90e161bSBill Fenner }
1348a90e161bSBill Fenner }
134927df3f5dSRui Paulo
135027df3f5dSRui Paulo /* No problems found. */
135127df3f5dSRui Paulo return 1;
1352ee67461eSJoseph Mingrone trunc:
1353ee67461eSJoseph Mingrone return 0;
1354a90e161bSBill Fenner }
1355a90e161bSBill Fenner
1356a90e161bSBill Fenner /*********************************************************************************
1357a90e161bSBill Fenner * Print Handle functions for the management frame types
1358a90e161bSBill Fenner *********************************************************************************/
1359a90e161bSBill Fenner
13605b0fe478SBruce M Simpson static int
handle_beacon(netdissect_options * ndo,const u_char * p,u_int length)13613c602fabSXin LI handle_beacon(netdissect_options *ndo,
13623c602fabSXin LI const u_char *p, u_int length)
1363a90e161bSBill Fenner {
1364a90e161bSBill Fenner struct mgmt_body_t pbody;
1365a90e161bSBill Fenner int offset = 0;
136627df3f5dSRui Paulo int ret;
1367a90e161bSBill Fenner
1368a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1369a90e161bSBill Fenner
1370ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1371ee67461eSJoseph Mingrone IEEE802_11_CAPINFO_LEN);
137227df3f5dSRui Paulo if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
137327df3f5dSRui Paulo IEEE802_11_CAPINFO_LEN)
1374ee67461eSJoseph Mingrone goto trunc;
1375abf25193SMax Laier memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
13765b0fe478SBruce M Simpson offset += IEEE802_11_TSTAMP_LEN;
137727df3f5dSRui Paulo length -= IEEE802_11_TSTAMP_LEN;
1378ee67461eSJoseph Mingrone pbody.beacon_interval = GET_LE_U_2(p + offset);
13795b0fe478SBruce M Simpson offset += IEEE802_11_BCNINT_LEN;
138027df3f5dSRui Paulo length -= IEEE802_11_BCNINT_LEN;
1381ee67461eSJoseph Mingrone pbody.capability_info = GET_LE_U_2(p + offset);
13825b0fe478SBruce M Simpson offset += IEEE802_11_CAPINFO_LEN;
138327df3f5dSRui Paulo length -= IEEE802_11_CAPINFO_LEN;
1384a90e161bSBill Fenner
13853c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1386a90e161bSBill Fenner
1387abf25193SMax Laier PRINT_SSID(pbody);
13889afd0c29SBill Fenner PRINT_RATES(pbody);
1389ee67461eSJoseph Mingrone ND_PRINT(" %s",
1390ee67461eSJoseph Mingrone CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
1391abf25193SMax Laier PRINT_DS_CHANNEL(pbody);
1392a90e161bSBill Fenner
139327df3f5dSRui Paulo return ret;
1394ee67461eSJoseph Mingrone trunc:
1395ee67461eSJoseph Mingrone return 0;
1396a90e161bSBill Fenner }
1397a90e161bSBill Fenner
13985b0fe478SBruce M Simpson static int
handle_assoc_request(netdissect_options * ndo,const u_char * p,u_int length)13993c602fabSXin LI handle_assoc_request(netdissect_options *ndo,
14003c602fabSXin LI const u_char *p, u_int length)
1401a90e161bSBill Fenner {
1402a90e161bSBill Fenner struct mgmt_body_t pbody;
1403a90e161bSBill Fenner int offset = 0;
140427df3f5dSRui Paulo int ret;
1405a90e161bSBill Fenner
1406a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1407a90e161bSBill Fenner
1408ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
140927df3f5dSRui Paulo if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
1410ee67461eSJoseph Mingrone goto trunc;
1411ee67461eSJoseph Mingrone pbody.capability_info = GET_LE_U_2(p);
14125b0fe478SBruce M Simpson offset += IEEE802_11_CAPINFO_LEN;
141327df3f5dSRui Paulo length -= IEEE802_11_CAPINFO_LEN;
1414ee67461eSJoseph Mingrone pbody.listen_interval = GET_LE_U_2(p + offset);
14155b0fe478SBruce M Simpson offset += IEEE802_11_LISTENINT_LEN;
141627df3f5dSRui Paulo length -= IEEE802_11_LISTENINT_LEN;
1417a90e161bSBill Fenner
14183c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1419a90e161bSBill Fenner
1420abf25193SMax Laier PRINT_SSID(pbody);
14219afd0c29SBill Fenner PRINT_RATES(pbody);
142227df3f5dSRui Paulo return ret;
1423ee67461eSJoseph Mingrone trunc:
1424ee67461eSJoseph Mingrone return 0;
1425a90e161bSBill Fenner }
1426a90e161bSBill Fenner
14275b0fe478SBruce M Simpson static int
handle_assoc_response(netdissect_options * ndo,const u_char * p,u_int length)14283c602fabSXin LI handle_assoc_response(netdissect_options *ndo,
14293c602fabSXin LI const u_char *p, u_int length)
1430a90e161bSBill Fenner {
1431a90e161bSBill Fenner struct mgmt_body_t pbody;
1432a90e161bSBill Fenner int offset = 0;
143327df3f5dSRui Paulo int ret;
1434a90e161bSBill Fenner
1435a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1436a90e161bSBill Fenner
1437ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1438ee67461eSJoseph Mingrone IEEE802_11_AID_LEN);
143927df3f5dSRui Paulo if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
144027df3f5dSRui Paulo IEEE802_11_AID_LEN)
1441ee67461eSJoseph Mingrone goto trunc;
1442ee67461eSJoseph Mingrone pbody.capability_info = GET_LE_U_2(p);
14435b0fe478SBruce M Simpson offset += IEEE802_11_CAPINFO_LEN;
144427df3f5dSRui Paulo length -= IEEE802_11_CAPINFO_LEN;
1445ee67461eSJoseph Mingrone pbody.status_code = GET_LE_U_2(p + offset);
14465b0fe478SBruce M Simpson offset += IEEE802_11_STATUS_LEN;
144727df3f5dSRui Paulo length -= IEEE802_11_STATUS_LEN;
1448ee67461eSJoseph Mingrone pbody.aid = GET_LE_U_2(p + offset);
14495b0fe478SBruce M Simpson offset += IEEE802_11_AID_LEN;
145027df3f5dSRui Paulo length -= IEEE802_11_AID_LEN;
1451a90e161bSBill Fenner
14523c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1453a90e161bSBill Fenner
1454ee67461eSJoseph Mingrone ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
1455a90e161bSBill Fenner CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
14562ebc47dbSSam Leffler (pbody.status_code < NUM_STATUSES
14572ebc47dbSSam Leffler ? status_text[pbody.status_code]
1458ee67461eSJoseph Mingrone : "n/a"));
1459a90e161bSBill Fenner
146027df3f5dSRui Paulo return ret;
1461ee67461eSJoseph Mingrone trunc:
1462ee67461eSJoseph Mingrone return 0;
1463a90e161bSBill Fenner }
1464a90e161bSBill Fenner
14655b0fe478SBruce M Simpson static int
handle_reassoc_request(netdissect_options * ndo,const u_char * p,u_int length)14663c602fabSXin LI handle_reassoc_request(netdissect_options *ndo,
14673c602fabSXin LI const u_char *p, u_int length)
1468a90e161bSBill Fenner {
1469a90e161bSBill Fenner struct mgmt_body_t pbody;
1470a90e161bSBill Fenner int offset = 0;
147127df3f5dSRui Paulo int ret;
1472a90e161bSBill Fenner
1473a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1474a90e161bSBill Fenner
1475ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1476ee67461eSJoseph Mingrone IEEE802_11_AP_LEN);
147727df3f5dSRui Paulo if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
147827df3f5dSRui Paulo IEEE802_11_AP_LEN)
1479ee67461eSJoseph Mingrone goto trunc;
1480ee67461eSJoseph Mingrone pbody.capability_info = GET_LE_U_2(p);
14815b0fe478SBruce M Simpson offset += IEEE802_11_CAPINFO_LEN;
148227df3f5dSRui Paulo length -= IEEE802_11_CAPINFO_LEN;
1483ee67461eSJoseph Mingrone pbody.listen_interval = GET_LE_U_2(p + offset);
14845b0fe478SBruce M Simpson offset += IEEE802_11_LISTENINT_LEN;
148527df3f5dSRui Paulo length -= IEEE802_11_LISTENINT_LEN;
14865b0fe478SBruce M Simpson memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
14875b0fe478SBruce M Simpson offset += IEEE802_11_AP_LEN;
148827df3f5dSRui Paulo length -= IEEE802_11_AP_LEN;
1489a90e161bSBill Fenner
14903c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1491a90e161bSBill Fenner
1492abf25193SMax Laier PRINT_SSID(pbody);
1493ee67461eSJoseph Mingrone ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap ));
1494a90e161bSBill Fenner
149527df3f5dSRui Paulo return ret;
1496ee67461eSJoseph Mingrone trunc:
1497ee67461eSJoseph Mingrone return 0;
1498a90e161bSBill Fenner }
1499a90e161bSBill Fenner
15005b0fe478SBruce M Simpson static int
handle_reassoc_response(netdissect_options * ndo,const u_char * p,u_int length)15013c602fabSXin LI handle_reassoc_response(netdissect_options *ndo,
15023c602fabSXin LI const u_char *p, u_int length)
1503a90e161bSBill Fenner {
1504ee67461eSJoseph Mingrone /* Same as a Association Response */
15053c602fabSXin LI return handle_assoc_response(ndo, p, length);
1506a90e161bSBill Fenner }
1507a90e161bSBill Fenner
15085b0fe478SBruce M Simpson static int
handle_probe_request(netdissect_options * ndo,const u_char * p,u_int length)15093c602fabSXin LI handle_probe_request(netdissect_options *ndo,
15103c602fabSXin LI const u_char *p, u_int length)
1511a90e161bSBill Fenner {
1512a90e161bSBill Fenner struct mgmt_body_t pbody;
1513a90e161bSBill Fenner int offset = 0;
151427df3f5dSRui Paulo int ret;
1515a90e161bSBill Fenner
1516a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1517a90e161bSBill Fenner
15183c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1519a90e161bSBill Fenner
1520abf25193SMax Laier PRINT_SSID(pbody);
15219afd0c29SBill Fenner PRINT_RATES(pbody);
1522a90e161bSBill Fenner
152327df3f5dSRui Paulo return ret;
1524a90e161bSBill Fenner }
1525a90e161bSBill Fenner
15265b0fe478SBruce M Simpson static int
handle_probe_response(netdissect_options * ndo,const u_char * p,u_int length)15273c602fabSXin LI handle_probe_response(netdissect_options *ndo,
15283c602fabSXin LI const u_char *p, u_int length)
1529a90e161bSBill Fenner {
1530a90e161bSBill Fenner struct mgmt_body_t pbody;
1531a90e161bSBill Fenner int offset = 0;
153227df3f5dSRui Paulo int ret;
1533a90e161bSBill Fenner
1534a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1535a90e161bSBill Fenner
1536ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1537ee67461eSJoseph Mingrone IEEE802_11_CAPINFO_LEN);
153827df3f5dSRui Paulo if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
153927df3f5dSRui Paulo IEEE802_11_CAPINFO_LEN)
1540ee67461eSJoseph Mingrone goto trunc;
15415b0fe478SBruce M Simpson memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
15425b0fe478SBruce M Simpson offset += IEEE802_11_TSTAMP_LEN;
154327df3f5dSRui Paulo length -= IEEE802_11_TSTAMP_LEN;
1544ee67461eSJoseph Mingrone pbody.beacon_interval = GET_LE_U_2(p + offset);
15455b0fe478SBruce M Simpson offset += IEEE802_11_BCNINT_LEN;
154627df3f5dSRui Paulo length -= IEEE802_11_BCNINT_LEN;
1547ee67461eSJoseph Mingrone pbody.capability_info = GET_LE_U_2(p + offset);
15485b0fe478SBruce M Simpson offset += IEEE802_11_CAPINFO_LEN;
154927df3f5dSRui Paulo length -= IEEE802_11_CAPINFO_LEN;
1550a90e161bSBill Fenner
15513c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1552a90e161bSBill Fenner
1553abf25193SMax Laier PRINT_SSID(pbody);
15549afd0c29SBill Fenner PRINT_RATES(pbody);
1555abf25193SMax Laier PRINT_DS_CHANNEL(pbody);
1556a90e161bSBill Fenner
155727df3f5dSRui Paulo return ret;
1558ee67461eSJoseph Mingrone trunc:
1559ee67461eSJoseph Mingrone return 0;
1560a90e161bSBill Fenner }
1561a90e161bSBill Fenner
15625b0fe478SBruce M Simpson static int
handle_atim(void)15635b0fe478SBruce M Simpson handle_atim(void)
1564a90e161bSBill Fenner {
1565a90e161bSBill Fenner /* the frame body for ATIM is null. */
1566a90e161bSBill Fenner return 1;
1567a90e161bSBill Fenner }
1568a90e161bSBill Fenner
15695b0fe478SBruce M Simpson static int
handle_disassoc(netdissect_options * ndo,const u_char * p,u_int length)15703c602fabSXin LI handle_disassoc(netdissect_options *ndo,
15713c602fabSXin LI const u_char *p, u_int length)
1572a90e161bSBill Fenner {
1573a90e161bSBill Fenner struct mgmt_body_t pbody;
1574a90e161bSBill Fenner
1575a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1576a90e161bSBill Fenner
1577ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
157827df3f5dSRui Paulo if (length < IEEE802_11_REASON_LEN)
1579ee67461eSJoseph Mingrone goto trunc;
1580ee67461eSJoseph Mingrone pbody.reason_code = GET_LE_U_2(p);
1581a90e161bSBill Fenner
1582ee67461eSJoseph Mingrone ND_PRINT(": %s",
15832ebc47dbSSam Leffler (pbody.reason_code < NUM_REASONS)
15842ebc47dbSSam Leffler ? reason_text[pbody.reason_code]
1585ee67461eSJoseph Mingrone : "Reserved");
1586a90e161bSBill Fenner
1587a90e161bSBill Fenner return 1;
1588ee67461eSJoseph Mingrone trunc:
1589ee67461eSJoseph Mingrone return 0;
1590a90e161bSBill Fenner }
1591a90e161bSBill Fenner
15925b0fe478SBruce M Simpson static int
handle_auth(netdissect_options * ndo,const u_char * p,u_int length)15933c602fabSXin LI handle_auth(netdissect_options *ndo,
15943c602fabSXin LI const u_char *p, u_int length)
1595a90e161bSBill Fenner {
1596a90e161bSBill Fenner struct mgmt_body_t pbody;
1597a90e161bSBill Fenner int offset = 0;
159827df3f5dSRui Paulo int ret;
1599a90e161bSBill Fenner
1600a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1601a90e161bSBill Fenner
1602ee67461eSJoseph Mingrone ND_TCHECK_6(p);
160327df3f5dSRui Paulo if (length < 6)
1604ee67461eSJoseph Mingrone goto trunc;
1605ee67461eSJoseph Mingrone pbody.auth_alg = GET_LE_U_2(p);
1606a90e161bSBill Fenner offset += 2;
160727df3f5dSRui Paulo length -= 2;
1608ee67461eSJoseph Mingrone pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
1609a90e161bSBill Fenner offset += 2;
161027df3f5dSRui Paulo length -= 2;
1611ee67461eSJoseph Mingrone pbody.status_code = GET_LE_U_2(p + offset);
1612a90e161bSBill Fenner offset += 2;
161327df3f5dSRui Paulo length -= 2;
1614a90e161bSBill Fenner
16153c602fabSXin LI ret = parse_elements(ndo, &pbody, p, offset, length);
1616a90e161bSBill Fenner
1617a90e161bSBill Fenner if ((pbody.auth_alg == 1) &&
16185b0fe478SBruce M Simpson ((pbody.auth_trans_seq_num == 2) ||
16195b0fe478SBruce M Simpson (pbody.auth_trans_seq_num == 3))) {
1620ee67461eSJoseph Mingrone ND_PRINT(" (%s)-%x [Challenge Text] %s",
16212ebc47dbSSam Leffler (pbody.auth_alg < NUM_AUTH_ALGS)
16222ebc47dbSSam Leffler ? auth_alg_text[pbody.auth_alg]
16235b0fe478SBruce M Simpson : "Reserved",
1624a90e161bSBill Fenner pbody.auth_trans_seq_num,
16255b0fe478SBruce M Simpson ((pbody.auth_trans_seq_num % 2)
16262ebc47dbSSam Leffler ? ((pbody.status_code < NUM_STATUSES)
16275b0fe478SBruce M Simpson ? status_text[pbody.status_code]
1628ee67461eSJoseph Mingrone : "n/a") : ""));
162927df3f5dSRui Paulo return ret;
1630a90e161bSBill Fenner }
1631ee67461eSJoseph Mingrone ND_PRINT(" (%s)-%x: %s",
16322ebc47dbSSam Leffler (pbody.auth_alg < NUM_AUTH_ALGS)
16332ebc47dbSSam Leffler ? auth_alg_text[pbody.auth_alg]
16342ebc47dbSSam Leffler : "Reserved",
16355b0fe478SBruce M Simpson pbody.auth_trans_seq_num,
16365b0fe478SBruce M Simpson (pbody.auth_trans_seq_num % 2)
16372ebc47dbSSam Leffler ? ((pbody.status_code < NUM_STATUSES)
16382ebc47dbSSam Leffler ? status_text[pbody.status_code]
16395b0fe478SBruce M Simpson : "n/a")
1640ee67461eSJoseph Mingrone : "");
1641a90e161bSBill Fenner
164227df3f5dSRui Paulo return ret;
1643ee67461eSJoseph Mingrone trunc:
1644ee67461eSJoseph Mingrone return 0;
1645a90e161bSBill Fenner }
1646a90e161bSBill Fenner
16475b0fe478SBruce M Simpson static int
handle_deauth(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)16483c602fabSXin LI handle_deauth(netdissect_options *ndo,
16493340d773SGleb Smirnoff const uint8_t *src, const u_char *p, u_int length)
1650a90e161bSBill Fenner {
1651a90e161bSBill Fenner struct mgmt_body_t pbody;
16525b0fe478SBruce M Simpson const char *reason = NULL;
1653a90e161bSBill Fenner
1654a90e161bSBill Fenner memset(&pbody, 0, sizeof(pbody));
1655a90e161bSBill Fenner
1656ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
165727df3f5dSRui Paulo if (length < IEEE802_11_REASON_LEN)
1658ee67461eSJoseph Mingrone goto trunc;
1659ee67461eSJoseph Mingrone pbody.reason_code = GET_LE_U_2(p);
16605b0fe478SBruce M Simpson
16612ebc47dbSSam Leffler reason = (pbody.reason_code < NUM_REASONS)
16622ebc47dbSSam Leffler ? reason_text[pbody.reason_code]
16635b0fe478SBruce M Simpson : "Reserved";
1664a90e161bSBill Fenner
16653c602fabSXin LI if (ndo->ndo_eflag) {
1666ee67461eSJoseph Mingrone ND_PRINT(": %s", reason);
1667a90e161bSBill Fenner } else {
1668ee67461eSJoseph Mingrone ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
1669a90e161bSBill Fenner }
1670a90e161bSBill Fenner return 1;
1671ee67461eSJoseph Mingrone trunc:
1672ee67461eSJoseph Mingrone return 0;
1673a90e161bSBill Fenner }
1674a90e161bSBill Fenner
16750b73e403SSam Leffler #define PRINT_HT_ACTION(v) (\
1676ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("TxChWidth"): \
1677ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("MIMOPwrSave"): \
1678ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
16790b73e403SSam Leffler #define PRINT_BA_ACTION(v) (\
1680ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("ADDBA Request"): \
1681ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("ADDBA Response"): \
1682ee67461eSJoseph Mingrone (v) == 2 ? ND_PRINT("DELBA"): \
1683ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
16840b73e403SSam Leffler #define PRINT_MESHLINK_ACTION(v) (\
1685ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("Request"): \
1686ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("Report"): \
1687ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
16880b73e403SSam Leffler #define PRINT_MESHPEERING_ACTION(v) (\
1689ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("Open"): \
1690ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("Confirm"): \
1691ee67461eSJoseph Mingrone (v) == 2 ? ND_PRINT("Close"): \
1692ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
16930b73e403SSam Leffler #define PRINT_MESHPATH_ACTION(v) (\
1694ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("Request"): \
1695ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("Report"): \
1696ee67461eSJoseph Mingrone (v) == 2 ? ND_PRINT("Error"): \
1697ee67461eSJoseph Mingrone (v) == 3 ? ND_PRINT("RootAnnouncement"): \
1698ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
16990b73e403SSam Leffler
1700d03c0883SXin LI #define PRINT_MESH_ACTION(v) (\
1701ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("MeshLink"): \
1702ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("HWMP"): \
1703ee67461eSJoseph Mingrone (v) == 2 ? ND_PRINT("Gate Announcement"): \
1704ee67461eSJoseph Mingrone (v) == 3 ? ND_PRINT("Congestion Control"): \
1705ee67461eSJoseph Mingrone (v) == 4 ? ND_PRINT("MCCA Setup Request"): \
1706ee67461eSJoseph Mingrone (v) == 5 ? ND_PRINT("MCCA Setup Reply"): \
1707ee67461eSJoseph Mingrone (v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \
1708ee67461eSJoseph Mingrone (v) == 7 ? ND_PRINT("MCCA Advertisement"): \
1709ee67461eSJoseph Mingrone (v) == 8 ? ND_PRINT("MCCA Teardown"): \
1710ee67461eSJoseph Mingrone (v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \
1711ee67461eSJoseph Mingrone (v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \
1712ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
1713d03c0883SXin LI #define PRINT_MULTIHOP_ACTION(v) (\
1714ee67461eSJoseph Mingrone (v) == 0 ? ND_PRINT("Proxy Update"): \
1715ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \
1716ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
1717d03c0883SXin LI #define PRINT_SELFPROT_ACTION(v) (\
1718ee67461eSJoseph Mingrone (v) == 1 ? ND_PRINT("Peering Open"): \
1719ee67461eSJoseph Mingrone (v) == 2 ? ND_PRINT("Peering Confirm"): \
1720ee67461eSJoseph Mingrone (v) == 3 ? ND_PRINT("Peering Close"): \
1721ee67461eSJoseph Mingrone (v) == 4 ? ND_PRINT("Group Key Inform"): \
1722ee67461eSJoseph Mingrone (v) == 5 ? ND_PRINT("Group Key Acknowledge"): \
1723ee67461eSJoseph Mingrone ND_PRINT("Act#%u", (v)))
1724d03c0883SXin LI
17250b73e403SSam Leffler static int
handle_action(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)17263c602fabSXin LI handle_action(netdissect_options *ndo,
17273340d773SGleb Smirnoff const uint8_t *src, const u_char *p, u_int length)
17280b73e403SSam Leffler {
1729ee67461eSJoseph Mingrone ND_TCHECK_2(p);
173027df3f5dSRui Paulo if (length < 2)
1731ee67461eSJoseph Mingrone goto trunc;
17323c602fabSXin LI if (ndo->ndo_eflag) {
1733ee67461eSJoseph Mingrone ND_PRINT(": ");
17340b73e403SSam Leffler } else {
1735ee67461eSJoseph Mingrone ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
17360b73e403SSam Leffler }
1737ee67461eSJoseph Mingrone switch (GET_U_1(p)) {
1738ee67461eSJoseph Mingrone case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break;
1739ee67461eSJoseph Mingrone case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break;
1740ee67461eSJoseph Mingrone case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break;
1741ee67461eSJoseph Mingrone case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break;
1742ee67461eSJoseph Mingrone case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break;
1743ee67461eSJoseph Mingrone case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break;
1744d03c0883SXin LI case 14:
1745*0a7e5f1fSJoseph Mingrone ND_PRINT("MultihopAction");
1746ee67461eSJoseph Mingrone PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break;
1747d03c0883SXin LI case 15:
1748ee67461eSJoseph Mingrone ND_PRINT("SelfprotectAction ");
1749ee67461eSJoseph Mingrone PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break;
1750ee67461eSJoseph Mingrone case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break;
17510b73e403SSam Leffler default:
1752ee67461eSJoseph Mingrone ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1));
17530b73e403SSam Leffler break;
17540b73e403SSam Leffler }
17550b73e403SSam Leffler return 1;
1756ee67461eSJoseph Mingrone trunc:
1757ee67461eSJoseph Mingrone return 0;
17580b73e403SSam Leffler }
17590b73e403SSam Leffler
1760a90e161bSBill Fenner
1761a90e161bSBill Fenner /*********************************************************************************
1762a90e161bSBill Fenner * Print Body funcs
1763a90e161bSBill Fenner *********************************************************************************/
1764a90e161bSBill Fenner
1765a90e161bSBill Fenner
17665b0fe478SBruce M Simpson static int
mgmt_body_print(netdissect_options * ndo,uint16_t fc,const uint8_t * src,const u_char * p,u_int length)17673c602fabSXin LI mgmt_body_print(netdissect_options *ndo,
17683340d773SGleb Smirnoff uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
1769a90e161bSBill Fenner {
1770ee67461eSJoseph Mingrone ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
17713340d773SGleb Smirnoff
17723340d773SGleb Smirnoff /* There may be a problem w/ AP not having this bit set */
17733340d773SGleb Smirnoff if (FC_PROTECTED(fc))
17743340d773SGleb Smirnoff return wep_print(ndo, p);
1775a90e161bSBill Fenner switch (FC_SUBTYPE(fc)) {
1776a90e161bSBill Fenner case ST_ASSOC_REQUEST:
17773c602fabSXin LI return handle_assoc_request(ndo, p, length);
1778a90e161bSBill Fenner case ST_ASSOC_RESPONSE:
17793c602fabSXin LI return handle_assoc_response(ndo, p, length);
1780a90e161bSBill Fenner case ST_REASSOC_REQUEST:
17813c602fabSXin LI return handle_reassoc_request(ndo, p, length);
1782a90e161bSBill Fenner case ST_REASSOC_RESPONSE:
17833c602fabSXin LI return handle_reassoc_response(ndo, p, length);
1784a90e161bSBill Fenner case ST_PROBE_REQUEST:
17853c602fabSXin LI return handle_probe_request(ndo, p, length);
1786a90e161bSBill Fenner case ST_PROBE_RESPONSE:
17873c602fabSXin LI return handle_probe_response(ndo, p, length);
1788a90e161bSBill Fenner case ST_BEACON:
17893c602fabSXin LI return handle_beacon(ndo, p, length);
1790a90e161bSBill Fenner case ST_ATIM:
17915b0fe478SBruce M Simpson return handle_atim();
1792a90e161bSBill Fenner case ST_DISASSOC:
17933c602fabSXin LI return handle_disassoc(ndo, p, length);
1794a90e161bSBill Fenner case ST_AUTH:
17953c602fabSXin LI return handle_auth(ndo, p, length);
1796a90e161bSBill Fenner case ST_DEAUTH:
17973340d773SGleb Smirnoff return handle_deauth(ndo, src, p, length);
17980b73e403SSam Leffler case ST_ACTION:
17993340d773SGleb Smirnoff return handle_action(ndo, src, p, length);
1800a90e161bSBill Fenner default:
1801a90e161bSBill Fenner return 1;
1802a90e161bSBill Fenner }
1803a90e161bSBill Fenner }
1804a90e161bSBill Fenner
1805a90e161bSBill Fenner
1806a90e161bSBill Fenner /*********************************************************************************
1807a90e161bSBill Fenner * Handles printing all the control frame types
1808a90e161bSBill Fenner *********************************************************************************/
1809a90e161bSBill Fenner
18105b0fe478SBruce M Simpson static int
ctrl_body_print(netdissect_options * ndo,uint16_t fc,const u_char * p)18113c602fabSXin LI ctrl_body_print(netdissect_options *ndo,
18123c602fabSXin LI uint16_t fc, const u_char *p)
1813a90e161bSBill Fenner {
1814ee67461eSJoseph Mingrone ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
1815a90e161bSBill Fenner switch (FC_SUBTYPE(fc)) {
181627df3f5dSRui Paulo case CTRL_CONTROL_WRAPPER:
181727df3f5dSRui Paulo /* XXX - requires special handling */
181827df3f5dSRui Paulo break;
18196efb4aa1SSam Leffler case CTRL_BAR:
1820ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
18213c602fabSXin LI if (!ndo->ndo_eflag)
1822ee67461eSJoseph Mingrone ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1823ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
1824ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
1825ee67461eSJoseph Mingrone GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
1826ee67461eSJoseph Mingrone GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
18276efb4aa1SSam Leffler break;
18280b73e403SSam Leffler case CTRL_BA:
1829ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
18303c602fabSXin LI if (!ndo->ndo_eflag)
1831ee67461eSJoseph Mingrone ND_PRINT(" RA:%s ",
1832ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
18330b73e403SSam Leffler break;
1834a90e161bSBill Fenner case CTRL_PS_POLL:
1835ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
1836ee67461eSJoseph Mingrone ND_PRINT(" AID(%x)",
1837ee67461eSJoseph Mingrone GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
1838a90e161bSBill Fenner break;
1839a90e161bSBill Fenner case CTRL_RTS:
1840ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
18413c602fabSXin LI if (!ndo->ndo_eflag)
1842ee67461eSJoseph Mingrone ND_PRINT(" TA:%s ",
1843ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
1844a90e161bSBill Fenner break;
1845a90e161bSBill Fenner case CTRL_CTS:
1846ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
18473c602fabSXin LI if (!ndo->ndo_eflag)
1848ee67461eSJoseph Mingrone ND_PRINT(" RA:%s ",
1849ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
1850a90e161bSBill Fenner break;
1851a90e161bSBill Fenner case CTRL_ACK:
1852ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
18533c602fabSXin LI if (!ndo->ndo_eflag)
1854ee67461eSJoseph Mingrone ND_PRINT(" RA:%s ",
1855ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
1856a90e161bSBill Fenner break;
1857a90e161bSBill Fenner case CTRL_CF_END:
1858ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
18593c602fabSXin LI if (!ndo->ndo_eflag)
1860ee67461eSJoseph Mingrone ND_PRINT(" RA:%s ",
1861ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
1862a90e161bSBill Fenner break;
1863a90e161bSBill Fenner case CTRL_END_ACK:
1864ee67461eSJoseph Mingrone ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
18653c602fabSXin LI if (!ndo->ndo_eflag)
1866ee67461eSJoseph Mingrone ND_PRINT(" RA:%s ",
1867ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
1868a90e161bSBill Fenner break;
1869a90e161bSBill Fenner }
1870a90e161bSBill Fenner return 1;
1871ee67461eSJoseph Mingrone trunc:
1872ee67461eSJoseph Mingrone return 0;
1873a90e161bSBill Fenner }
1874a90e161bSBill Fenner
1875a90e161bSBill Fenner /*
1876a90e161bSBill Fenner * Data Frame - Address field contents
1877a90e161bSBill Fenner *
1878a90e161bSBill Fenner * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
1879a90e161bSBill Fenner * 0 | 0 | DA | SA | BSSID | n/a
1880a90e161bSBill Fenner * 0 | 1 | DA | BSSID | SA | n/a
1881a90e161bSBill Fenner * 1 | 0 | BSSID | SA | DA | n/a
1882a90e161bSBill Fenner * 1 | 1 | RA | TA | DA | SA
1883a90e161bSBill Fenner */
1884a90e161bSBill Fenner
18853340d773SGleb Smirnoff /*
18863340d773SGleb Smirnoff * Function to get source and destination MAC addresses for a data frame.
18873340d773SGleb Smirnoff */
18885b0fe478SBruce M Simpson static void
get_data_src_dst_mac(uint16_t fc,const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)18893340d773SGleb Smirnoff get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
18903c602fabSXin LI const uint8_t **dstp)
1891a90e161bSBill Fenner {
18923340d773SGleb Smirnoff #define ADDR1 (p + 4)
18933340d773SGleb Smirnoff #define ADDR2 (p + 10)
18943340d773SGleb Smirnoff #define ADDR3 (p + 16)
18953340d773SGleb Smirnoff #define ADDR4 (p + 24)
18963340d773SGleb Smirnoff
18973340d773SGleb Smirnoff if (!FC_TO_DS(fc)) {
18983340d773SGleb Smirnoff if (!FC_FROM_DS(fc)) {
18993340d773SGleb Smirnoff /* not To DS and not From DS */
19003340d773SGleb Smirnoff *srcp = ADDR2;
19013340d773SGleb Smirnoff *dstp = ADDR1;
19023340d773SGleb Smirnoff } else {
19033340d773SGleb Smirnoff /* not To DS and From DS */
19043340d773SGleb Smirnoff *srcp = ADDR3;
19053340d773SGleb Smirnoff *dstp = ADDR1;
19063340d773SGleb Smirnoff }
19073340d773SGleb Smirnoff } else {
19083340d773SGleb Smirnoff if (!FC_FROM_DS(fc)) {
1909ee67461eSJoseph Mingrone /* To DS and not From DS */
19103340d773SGleb Smirnoff *srcp = ADDR2;
19113340d773SGleb Smirnoff *dstp = ADDR3;
19123340d773SGleb Smirnoff } else {
19133340d773SGleb Smirnoff /* To DS and From DS */
19143340d773SGleb Smirnoff *srcp = ADDR4;
19153340d773SGleb Smirnoff *dstp = ADDR3;
19163340d773SGleb Smirnoff }
19173340d773SGleb Smirnoff }
19183340d773SGleb Smirnoff
19193340d773SGleb Smirnoff #undef ADDR1
19203340d773SGleb Smirnoff #undef ADDR2
19213340d773SGleb Smirnoff #undef ADDR3
19223340d773SGleb Smirnoff #undef ADDR4
19233340d773SGleb Smirnoff }
19243340d773SGleb Smirnoff
19253340d773SGleb Smirnoff static void
get_mgmt_src_dst_mac(const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)19263340d773SGleb Smirnoff get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
19273340d773SGleb Smirnoff {
19283340d773SGleb Smirnoff const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
19293340d773SGleb Smirnoff
19303340d773SGleb Smirnoff if (srcp != NULL)
19313340d773SGleb Smirnoff *srcp = hp->sa;
19323340d773SGleb Smirnoff if (dstp != NULL)
19333340d773SGleb Smirnoff *dstp = hp->da;
19343340d773SGleb Smirnoff }
19353340d773SGleb Smirnoff
19363340d773SGleb Smirnoff /*
19373340d773SGleb Smirnoff * Print Header funcs
19383340d773SGleb Smirnoff */
19393340d773SGleb Smirnoff
19403340d773SGleb Smirnoff static void
data_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)19413340d773SGleb Smirnoff data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
19423340d773SGleb Smirnoff {
1943abf25193SMax Laier u_int subtype = FC_SUBTYPE(fc);
1944abf25193SMax Laier
1945abf25193SMax Laier if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
1946abf25193SMax Laier DATA_FRAME_IS_QOS(subtype)) {
1947ee67461eSJoseph Mingrone ND_PRINT("CF ");
1948abf25193SMax Laier if (DATA_FRAME_IS_CF_ACK(subtype)) {
1949abf25193SMax Laier if (DATA_FRAME_IS_CF_POLL(subtype))
1950ee67461eSJoseph Mingrone ND_PRINT("Ack/Poll");
1951abf25193SMax Laier else
1952ee67461eSJoseph Mingrone ND_PRINT("Ack");
1953abf25193SMax Laier } else {
1954abf25193SMax Laier if (DATA_FRAME_IS_CF_POLL(subtype))
1955ee67461eSJoseph Mingrone ND_PRINT("Poll");
1956abf25193SMax Laier }
1957abf25193SMax Laier if (DATA_FRAME_IS_QOS(subtype))
1958ee67461eSJoseph Mingrone ND_PRINT("+QoS");
1959ee67461eSJoseph Mingrone ND_PRINT(" ");
19605b0fe478SBruce M Simpson }
19615b0fe478SBruce M Simpson
1962a90e161bSBill Fenner #define ADDR1 (p + 4)
1963a90e161bSBill Fenner #define ADDR2 (p + 10)
1964a90e161bSBill Fenner #define ADDR3 (p + 16)
1965a90e161bSBill Fenner #define ADDR4 (p + 24)
1966a90e161bSBill Fenner
19675b0fe478SBruce M Simpson if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1968ee67461eSJoseph Mingrone ND_PRINT("DA:%s SA:%s BSSID:%s ",
1969ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1970ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR3));
19715b0fe478SBruce M Simpson } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1972ee67461eSJoseph Mingrone ND_PRINT("DA:%s BSSID:%s SA:%s ",
1973ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1974ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR3));
19755b0fe478SBruce M Simpson } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1976ee67461eSJoseph Mingrone ND_PRINT("BSSID:%s SA:%s DA:%s ",
1977ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1978ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR3));
19795b0fe478SBruce M Simpson } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1980ee67461eSJoseph Mingrone ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
1981ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1982ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
1983a90e161bSBill Fenner }
1984a90e161bSBill Fenner
1985a90e161bSBill Fenner #undef ADDR1
1986a90e161bSBill Fenner #undef ADDR2
1987a90e161bSBill Fenner #undef ADDR3
1988a90e161bSBill Fenner #undef ADDR4
1989a90e161bSBill Fenner }
1990a90e161bSBill Fenner
19915b0fe478SBruce M Simpson static void
mgmt_header_print(netdissect_options * ndo,const u_char * p)19923340d773SGleb Smirnoff mgmt_header_print(netdissect_options *ndo, const u_char *p)
1993a90e161bSBill Fenner {
1994a90e161bSBill Fenner const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
1995a90e161bSBill Fenner
1996ee67461eSJoseph Mingrone ND_PRINT("BSSID:%s DA:%s SA:%s ",
1997ee67461eSJoseph Mingrone GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
1998ee67461eSJoseph Mingrone GET_ETHERADDR_STRING((hp)->sa));
1999a90e161bSBill Fenner }
2000a90e161bSBill Fenner
20015b0fe478SBruce M Simpson static void
ctrl_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)20023340d773SGleb Smirnoff ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
2003a90e161bSBill Fenner {
2004a90e161bSBill Fenner switch (FC_SUBTYPE(fc)) {
20056efb4aa1SSam Leffler case CTRL_BAR:
2006ee67461eSJoseph Mingrone ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
2007ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
2008ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
2009ee67461eSJoseph Mingrone GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
2010ee67461eSJoseph Mingrone GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
20116efb4aa1SSam Leffler break;
20120b73e403SSam Leffler case CTRL_BA:
2013*0a7e5f1fSJoseph Mingrone ND_PRINT("RA:%s TA:%s ",
2014*0a7e5f1fSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra),
2015*0a7e5f1fSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ta));
20160b73e403SSam Leffler break;
2017a90e161bSBill Fenner case CTRL_PS_POLL:
2018ee67461eSJoseph Mingrone ND_PRINT("BSSID:%s TA:%s ",
2019ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
2020ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
2021a90e161bSBill Fenner break;
2022a90e161bSBill Fenner case CTRL_RTS:
2023ee67461eSJoseph Mingrone ND_PRINT("RA:%s TA:%s ",
2024ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
2025ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
2026a90e161bSBill Fenner break;
2027a90e161bSBill Fenner case CTRL_CTS:
2028ee67461eSJoseph Mingrone ND_PRINT("RA:%s ",
2029ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
2030a90e161bSBill Fenner break;
2031a90e161bSBill Fenner case CTRL_ACK:
2032ee67461eSJoseph Mingrone ND_PRINT("RA:%s ",
2033ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
2034a90e161bSBill Fenner break;
2035a90e161bSBill Fenner case CTRL_CF_END:
2036ee67461eSJoseph Mingrone ND_PRINT("RA:%s BSSID:%s ",
2037ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
2038ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
2039a90e161bSBill Fenner break;
2040a90e161bSBill Fenner case CTRL_END_ACK:
2041ee67461eSJoseph Mingrone ND_PRINT("RA:%s BSSID:%s ",
2042ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
2043ee67461eSJoseph Mingrone GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
2044a90e161bSBill Fenner break;
2045a90e161bSBill Fenner default:
20463340d773SGleb Smirnoff /* We shouldn't get here - we should already have quit */
20475b0fe478SBruce M Simpson break;
2048a90e161bSBill Fenner }
2049a90e161bSBill Fenner }
2050a90e161bSBill Fenner
20515b0fe478SBruce M Simpson static int
extract_header_length(netdissect_options * ndo,uint16_t fc)20523c602fabSXin LI extract_header_length(netdissect_options *ndo,
20533c602fabSXin LI uint16_t fc)
2054a90e161bSBill Fenner {
2055abf25193SMax Laier int len;
2056abf25193SMax Laier
2057a90e161bSBill Fenner switch (FC_TYPE(fc)) {
2058a90e161bSBill Fenner case T_MGMT:
20595b0fe478SBruce M Simpson return MGMT_HDRLEN;
2060a90e161bSBill Fenner case T_CTRL:
2061a90e161bSBill Fenner switch (FC_SUBTYPE(fc)) {
20623340d773SGleb Smirnoff case CTRL_CONTROL_WRAPPER:
20633340d773SGleb Smirnoff return CTRL_CONTROL_WRAPPER_HDRLEN;
20646efb4aa1SSam Leffler case CTRL_BAR:
20656efb4aa1SSam Leffler return CTRL_BAR_HDRLEN;
20663340d773SGleb Smirnoff case CTRL_BA:
20673340d773SGleb Smirnoff return CTRL_BA_HDRLEN;
2068a90e161bSBill Fenner case CTRL_PS_POLL:
20695b0fe478SBruce M Simpson return CTRL_PS_POLL_HDRLEN;
2070a90e161bSBill Fenner case CTRL_RTS:
20715b0fe478SBruce M Simpson return CTRL_RTS_HDRLEN;
2072a90e161bSBill Fenner case CTRL_CTS:
20735b0fe478SBruce M Simpson return CTRL_CTS_HDRLEN;
2074a90e161bSBill Fenner case CTRL_ACK:
20755b0fe478SBruce M Simpson return CTRL_ACK_HDRLEN;
2076a90e161bSBill Fenner case CTRL_CF_END:
20775b0fe478SBruce M Simpson return CTRL_END_HDRLEN;
2078a90e161bSBill Fenner case CTRL_END_ACK:
20795b0fe478SBruce M Simpson return CTRL_END_ACK_HDRLEN;
2080a90e161bSBill Fenner default:
2081ee67461eSJoseph Mingrone ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
20825b0fe478SBruce M Simpson return 0;
2083a90e161bSBill Fenner }
2084a90e161bSBill Fenner case T_DATA:
2085abf25193SMax Laier len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
2086abf25193SMax Laier if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
2087abf25193SMax Laier len += 2;
2088abf25193SMax Laier return len;
2089a90e161bSBill Fenner default:
2090ee67461eSJoseph Mingrone ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
20915b0fe478SBruce M Simpson return 0;
2092a90e161bSBill Fenner }
2093a90e161bSBill Fenner }
2094a90e161bSBill Fenner
20950b73e403SSam Leffler static int
extract_mesh_header_length(netdissect_options * ndo,const u_char * p)2096ee67461eSJoseph Mingrone extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
20970b73e403SSam Leffler {
2098ee67461eSJoseph Mingrone return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
20990b73e403SSam Leffler }
21000b73e403SSam Leffler
2101a90e161bSBill Fenner /*
21023340d773SGleb Smirnoff * Print the 802.11 MAC header.
2103a90e161bSBill Fenner */
21040b73e403SSam Leffler static void
ieee_802_11_hdr_print(netdissect_options * ndo,uint16_t fc,const u_char * p,u_int hdrlen,u_int meshdrlen)21053c602fabSXin LI ieee_802_11_hdr_print(netdissect_options *ndo,
21063c602fabSXin LI uint16_t fc, const u_char *p, u_int hdrlen,
21073340d773SGleb Smirnoff u_int meshdrlen)
2108a90e161bSBill Fenner {
21093c602fabSXin LI if (ndo->ndo_vflag) {
21105b0fe478SBruce M Simpson if (FC_MORE_DATA(fc))
2111ee67461eSJoseph Mingrone ND_PRINT("More Data ");
21125b0fe478SBruce M Simpson if (FC_MORE_FLAG(fc))
2113ee67461eSJoseph Mingrone ND_PRINT("More Fragments ");
21145b0fe478SBruce M Simpson if (FC_POWER_MGMT(fc))
2115ee67461eSJoseph Mingrone ND_PRINT("Pwr Mgmt ");
21165b0fe478SBruce M Simpson if (FC_RETRY(fc))
2117ee67461eSJoseph Mingrone ND_PRINT("Retry ");
21185b0fe478SBruce M Simpson if (FC_ORDER(fc))
2119ee67461eSJoseph Mingrone ND_PRINT("Strictly Ordered ");
21203340d773SGleb Smirnoff if (FC_PROTECTED(fc))
2121ee67461eSJoseph Mingrone ND_PRINT("Protected ");
21225b0fe478SBruce M Simpson if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
2123ee67461eSJoseph Mingrone ND_PRINT("%uus ",
2124ee67461eSJoseph Mingrone GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
21255b0fe478SBruce M Simpson }
21260b73e403SSam Leffler if (meshdrlen != 0) {
21270b73e403SSam Leffler const struct meshcntl_t *mc =
2128ee67461eSJoseph Mingrone (const struct meshcntl_t *)(p + hdrlen - meshdrlen);
2129ee67461eSJoseph Mingrone u_int ae = GET_U_1(mc->flags) & 3;
21300b73e403SSam Leffler
2131ee67461eSJoseph Mingrone ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
2132ee67461eSJoseph Mingrone GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
21330b73e403SSam Leffler if (ae > 0)
2134ee67461eSJoseph Mingrone ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
21350b73e403SSam Leffler if (ae > 1)
2136ee67461eSJoseph Mingrone ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
21370b73e403SSam Leffler if (ae > 2)
2138ee67461eSJoseph Mingrone ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
2139ee67461eSJoseph Mingrone ND_PRINT(") ");
21400b73e403SSam Leffler }
21415b0fe478SBruce M Simpson
2142a90e161bSBill Fenner switch (FC_TYPE(fc)) {
2143a90e161bSBill Fenner case T_MGMT:
21443340d773SGleb Smirnoff mgmt_header_print(ndo, p);
2145a90e161bSBill Fenner break;
2146a90e161bSBill Fenner case T_CTRL:
21473340d773SGleb Smirnoff ctrl_header_print(ndo, fc, p);
2148a90e161bSBill Fenner break;
2149a90e161bSBill Fenner case T_DATA:
21503340d773SGleb Smirnoff data_header_print(ndo, fc, p);
2151a90e161bSBill Fenner break;
2152a90e161bSBill Fenner default:
2153a90e161bSBill Fenner break;
2154a90e161bSBill Fenner }
2155a90e161bSBill Fenner }
2156a90e161bSBill Fenner
21575b0fe478SBruce M Simpson static u_int
ieee802_11_print(netdissect_options * ndo,const u_char * p,u_int length,u_int orig_caplen,int pad,u_int fcslen)21583c602fabSXin LI ieee802_11_print(netdissect_options *ndo,
21593c602fabSXin LI const u_char *p, u_int length, u_int orig_caplen, int pad,
216027df3f5dSRui Paulo u_int fcslen)
2161a90e161bSBill Fenner {
21623c602fabSXin LI uint16_t fc;
216327df3f5dSRui Paulo u_int caplen, hdrlen, meshdrlen;
21643340d773SGleb Smirnoff struct lladdr_info src, dst;
21653340d773SGleb Smirnoff int llc_hdrlen;
2166a90e161bSBill Fenner
2167ee67461eSJoseph Mingrone ndo->ndo_protocol = "802.11";
216827df3f5dSRui Paulo caplen = orig_caplen;
216927df3f5dSRui Paulo /* Remove FCS, if present */
217027df3f5dSRui Paulo if (length < fcslen) {
2171ee67461eSJoseph Mingrone nd_print_trunc(ndo);
21725b0fe478SBruce M Simpson return caplen;
2173a90e161bSBill Fenner }
217427df3f5dSRui Paulo length -= fcslen;
217527df3f5dSRui Paulo if (caplen > length) {
217627df3f5dSRui Paulo /* Amount of FCS in actual packet data, if any */
217727df3f5dSRui Paulo fcslen = caplen - length;
217827df3f5dSRui Paulo caplen -= fcslen;
21793c602fabSXin LI ndo->ndo_snapend -= fcslen;
218027df3f5dSRui Paulo }
218127df3f5dSRui Paulo
218227df3f5dSRui Paulo if (caplen < IEEE802_11_FC_LEN) {
2183ee67461eSJoseph Mingrone nd_print_trunc(ndo);
218427df3f5dSRui Paulo return orig_caplen;
218527df3f5dSRui Paulo }
2186a90e161bSBill Fenner
2187ee67461eSJoseph Mingrone fc = GET_LE_U_2(p);
21883c602fabSXin LI hdrlen = extract_header_length(ndo, fc);
21893340d773SGleb Smirnoff if (hdrlen == 0) {
21903340d773SGleb Smirnoff /* Unknown frame type or control frame subtype; quit. */
21913340d773SGleb Smirnoff return (0);
21923340d773SGleb Smirnoff }
2193abf25193SMax Laier if (pad)
2194abf25193SMax Laier hdrlen = roundup2(hdrlen, 4);
21953c602fabSXin LI if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
2196cac3dcd5SXin LI DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
2197ee67461eSJoseph Mingrone if(!ND_TTEST_1(p + hdrlen)) {
2198ee67461eSJoseph Mingrone nd_print_trunc(ndo);
219939e421e8SCy Schubert return hdrlen;
220039e421e8SCy Schubert }
2201ee67461eSJoseph Mingrone meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
22020b73e403SSam Leffler hdrlen += meshdrlen;
22030b73e403SSam Leffler } else
22040b73e403SSam Leffler meshdrlen = 0;
22050b73e403SSam Leffler
22065b0fe478SBruce M Simpson if (caplen < hdrlen) {
2207ee67461eSJoseph Mingrone nd_print_trunc(ndo);
22085b0fe478SBruce M Simpson return hdrlen;
22095b0fe478SBruce M Simpson }
22105b0fe478SBruce M Simpson
22113340d773SGleb Smirnoff if (ndo->ndo_eflag)
22123340d773SGleb Smirnoff ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
2213a90e161bSBill Fenner
2214a90e161bSBill Fenner /*
22155b0fe478SBruce M Simpson * Go past the 802.11 header.
2216a90e161bSBill Fenner */
22175b0fe478SBruce M Simpson length -= hdrlen;
22185b0fe478SBruce M Simpson caplen -= hdrlen;
22195b0fe478SBruce M Simpson p += hdrlen;
2220a90e161bSBill Fenner
22213340d773SGleb Smirnoff src.addr_string = etheraddr_string;
22223340d773SGleb Smirnoff dst.addr_string = etheraddr_string;
2223a90e161bSBill Fenner switch (FC_TYPE(fc)) {
2224a90e161bSBill Fenner case T_MGMT:
22253340d773SGleb Smirnoff get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
22263340d773SGleb Smirnoff if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
2227ee67461eSJoseph Mingrone nd_print_trunc(ndo);
22285b0fe478SBruce M Simpson return hdrlen;
2229a90e161bSBill Fenner }
2230a90e161bSBill Fenner break;
2231a90e161bSBill Fenner case T_CTRL:
22323c602fabSXin LI if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
2233ee67461eSJoseph Mingrone nd_print_trunc(ndo);
22345b0fe478SBruce M Simpson return hdrlen;
2235a90e161bSBill Fenner }
2236a90e161bSBill Fenner break;
2237a90e161bSBill Fenner case T_DATA:
2238abf25193SMax Laier if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
2239abf25193SMax Laier return hdrlen; /* no-data frame */
2240a90e161bSBill Fenner /* There may be a problem w/ AP not having this bit set */
22413340d773SGleb Smirnoff if (FC_PROTECTED(fc)) {
2242ee67461eSJoseph Mingrone ND_PRINT("Data");
22433c602fabSXin LI if (!wep_print(ndo, p)) {
2244ee67461eSJoseph Mingrone nd_print_trunc(ndo);
22455b0fe478SBruce M Simpson return hdrlen;
2246a90e161bSBill Fenner }
22473340d773SGleb Smirnoff } else {
22483340d773SGleb Smirnoff get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
22493340d773SGleb Smirnoff llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
22503340d773SGleb Smirnoff if (llc_hdrlen < 0) {
2251a90e161bSBill Fenner /*
2252a90e161bSBill Fenner * Some kinds of LLC packet we cannot
2253a90e161bSBill Fenner * handle intelligently
2254a90e161bSBill Fenner */
22553c602fabSXin LI if (!ndo->ndo_suppress_default_print)
22563c602fabSXin LI ND_DEFAULTPRINT(p, caplen);
22573340d773SGleb Smirnoff llc_hdrlen = -llc_hdrlen;
22583340d773SGleb Smirnoff }
22593340d773SGleb Smirnoff hdrlen += llc_hdrlen;
2260a90e161bSBill Fenner }
2261a90e161bSBill Fenner break;
2262a90e161bSBill Fenner default:
22633340d773SGleb Smirnoff /* We shouldn't get here - we should already have quit */
2264a90e161bSBill Fenner break;
2265a90e161bSBill Fenner }
2266a90e161bSBill Fenner
22675b0fe478SBruce M Simpson return hdrlen;
22685b0fe478SBruce M Simpson }
22695b0fe478SBruce M Simpson
22705b0fe478SBruce M Simpson /*
22715b0fe478SBruce M Simpson * This is the top level routine of the printer. 'p' points
22725b0fe478SBruce M Simpson * to the 802.11 header of the packet, 'h->ts' is the timestamp,
22731de50e9fSSam Leffler * 'h->len' is the length of the packet off the wire, and 'h->caplen'
22745b0fe478SBruce M Simpson * is the number of bytes actually captured.
22755b0fe478SBruce M Simpson */
2276ee67461eSJoseph Mingrone void
ieee802_11_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)22773c602fabSXin LI ieee802_11_if_print(netdissect_options *ndo,
22783c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p)
22795b0fe478SBruce M Simpson {
2280ee67461eSJoseph Mingrone ndo->ndo_protocol = "802.11";
2281ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
22825b0fe478SBruce M Simpson }
22835b0fe478SBruce M Simpson
22843340d773SGleb Smirnoff
228571fe94fdSDimitry Andric /* $FreeBSD: projects/clang400-import/contrib/tcpdump/print-802_11.c 276788 2015-01-07 19:55:18Z delphij $ */
22863340d773SGleb Smirnoff /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */
22873340d773SGleb Smirnoff
22883340d773SGleb Smirnoff /*-
22893340d773SGleb Smirnoff * Copyright (c) 2003, 2004 David Young. All rights reserved.
22903340d773SGleb Smirnoff *
22913340d773SGleb Smirnoff * Redistribution and use in source and binary forms, with or without
22923340d773SGleb Smirnoff * modification, are permitted provided that the following conditions
22933340d773SGleb Smirnoff * are met:
22943340d773SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright
22953340d773SGleb Smirnoff * notice, this list of conditions and the following disclaimer.
22963340d773SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright
22973340d773SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the
22983340d773SGleb Smirnoff * documentation and/or other materials provided with the distribution.
22993340d773SGleb Smirnoff * 3. The name of David Young may not be used to endorse or promote
23003340d773SGleb Smirnoff * products derived from this software without specific prior
23013340d773SGleb Smirnoff * written permission.
23023340d773SGleb Smirnoff *
23033340d773SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
23043340d773SGleb Smirnoff * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23053340d773SGleb Smirnoff * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23063340d773SGleb Smirnoff * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
23073340d773SGleb Smirnoff * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23083340d773SGleb Smirnoff * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23093340d773SGleb Smirnoff * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23103340d773SGleb Smirnoff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23113340d773SGleb Smirnoff * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23123340d773SGleb Smirnoff * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23133340d773SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
23143340d773SGleb Smirnoff * OF SUCH DAMAGE.
23153340d773SGleb Smirnoff */
23163340d773SGleb Smirnoff
23173340d773SGleb Smirnoff /* A generic radio capture format is desirable. It must be
23183340d773SGleb Smirnoff * rigidly defined (e.g., units for fields should be given),
23193340d773SGleb Smirnoff * and easily extensible.
23203340d773SGleb Smirnoff *
23213340d773SGleb Smirnoff * The following is an extensible radio capture format. It is
23223340d773SGleb Smirnoff * based on a bitmap indicating which fields are present.
23233340d773SGleb Smirnoff *
23243340d773SGleb Smirnoff * I am trying to describe precisely what the application programmer
23253340d773SGleb Smirnoff * should expect in the following, and for that reason I tell the
23263340d773SGleb Smirnoff * units and origin of each measurement (where it applies), or else I
23273340d773SGleb Smirnoff * use sufficiently weaselly language ("is a monotonically nondecreasing
23283340d773SGleb Smirnoff * function of...") that I cannot set false expectations for lawyerly
23293340d773SGleb Smirnoff * readers.
23303340d773SGleb Smirnoff */
23313340d773SGleb Smirnoff
23323340d773SGleb Smirnoff /*
23333340d773SGleb Smirnoff * The radio capture header precedes the 802.11 header.
23343340d773SGleb Smirnoff *
23353340d773SGleb Smirnoff * Note well: all radiotap fields are little-endian.
23363340d773SGleb Smirnoff */
23373340d773SGleb Smirnoff struct ieee80211_radiotap_header {
2338ee67461eSJoseph Mingrone nd_uint8_t it_version; /* Version 0. Only increases
23393340d773SGleb Smirnoff * for drastic changes,
23403340d773SGleb Smirnoff * introduction of compatible
23413340d773SGleb Smirnoff * new fields does not count.
23423340d773SGleb Smirnoff */
2343ee67461eSJoseph Mingrone nd_uint8_t it_pad;
2344ee67461eSJoseph Mingrone nd_uint16_t it_len; /* length of the whole
23453340d773SGleb Smirnoff * header in bytes, including
23463340d773SGleb Smirnoff * it_version, it_pad,
23473340d773SGleb Smirnoff * it_len, and data fields.
23483340d773SGleb Smirnoff */
2349ee67461eSJoseph Mingrone nd_uint32_t it_present; /* A bitmap telling which
23503340d773SGleb Smirnoff * fields are present. Set bit 31
23513340d773SGleb Smirnoff * (0x80000000) to extend the
23523340d773SGleb Smirnoff * bitmap by another 32 bits.
23533340d773SGleb Smirnoff * Additional extensions are made
23543340d773SGleb Smirnoff * by setting bit 31.
23553340d773SGleb Smirnoff */
23563340d773SGleb Smirnoff };
23573340d773SGleb Smirnoff
23583340d773SGleb Smirnoff /* Name Data type Units
23593340d773SGleb Smirnoff * ---- --------- -----
23603340d773SGleb Smirnoff *
23613340d773SGleb Smirnoff * IEEE80211_RADIOTAP_TSFT uint64_t microseconds
23623340d773SGleb Smirnoff *
23633340d773SGleb Smirnoff * Value in microseconds of the MAC's 64-bit 802.11 Time
23643340d773SGleb Smirnoff * Synchronization Function timer when the first bit of the
23653340d773SGleb Smirnoff * MPDU arrived at the MAC. For received frames, only.
23663340d773SGleb Smirnoff *
23673340d773SGleb Smirnoff * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
23683340d773SGleb Smirnoff *
23693340d773SGleb Smirnoff * Tx/Rx frequency in MHz, followed by flags (see below).
23703340d773SGleb Smirnoff * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
23713340d773SGleb Smirnoff * represent an HT channel as there is not enough room in
23723340d773SGleb Smirnoff * the flags word.
23733340d773SGleb Smirnoff *
23743340d773SGleb Smirnoff * IEEE80211_RADIOTAP_FHSS uint16_t see below
23753340d773SGleb Smirnoff *
23763340d773SGleb Smirnoff * For frequency-hopping radios, the hop set (first byte)
23773340d773SGleb Smirnoff * and pattern (second byte).
23783340d773SGleb Smirnoff *
23793340d773SGleb Smirnoff * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index
23803340d773SGleb Smirnoff *
23813340d773SGleb Smirnoff * Tx/Rx data rate. If bit 0x80 is set then it represents an
23823340d773SGleb Smirnoff * an MCS index and not an IEEE rate.
23833340d773SGleb Smirnoff *
23843340d773SGleb Smirnoff * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
23853340d773SGleb Smirnoff * one milliwatt (dBm)
23863340d773SGleb Smirnoff *
23873340d773SGleb Smirnoff * RF signal power at the antenna, decibel difference from
23883340d773SGleb Smirnoff * one milliwatt.
23893340d773SGleb Smirnoff *
23903340d773SGleb Smirnoff * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from
23913340d773SGleb Smirnoff * one milliwatt (dBm)
23923340d773SGleb Smirnoff *
23933340d773SGleb Smirnoff * RF noise power at the antenna, decibel difference from one
23943340d773SGleb Smirnoff * milliwatt.
23953340d773SGleb Smirnoff *
23963340d773SGleb Smirnoff * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
23973340d773SGleb Smirnoff *
23983340d773SGleb Smirnoff * RF signal power at the antenna, decibel difference from an
23993340d773SGleb Smirnoff * arbitrary, fixed reference.
24003340d773SGleb Smirnoff *
24013340d773SGleb Smirnoff * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
24023340d773SGleb Smirnoff *
24033340d773SGleb Smirnoff * RF noise power at the antenna, decibel difference from an
24043340d773SGleb Smirnoff * arbitrary, fixed reference point.
24053340d773SGleb Smirnoff *
24063340d773SGleb Smirnoff * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
24073340d773SGleb Smirnoff *
24083340d773SGleb Smirnoff * Quality of Barker code lock. Unitless. Monotonically
24093340d773SGleb Smirnoff * nondecreasing with "better" lock strength. Called "Signal
24103340d773SGleb Smirnoff * Quality" in datasheets. (Is there a standard way to measure
24113340d773SGleb Smirnoff * this?)
24123340d773SGleb Smirnoff *
24133340d773SGleb Smirnoff * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
24143340d773SGleb Smirnoff *
24153340d773SGleb Smirnoff * Transmit power expressed as unitless distance from max
24163340d773SGleb Smirnoff * power set at factory calibration. 0 is max power.
24173340d773SGleb Smirnoff * Monotonically nondecreasing with lower power levels.
24183340d773SGleb Smirnoff *
24193340d773SGleb Smirnoff * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
24203340d773SGleb Smirnoff *
24213340d773SGleb Smirnoff * Transmit power expressed as decibel distance from max power
24223340d773SGleb Smirnoff * set at factory calibration. 0 is max power. Monotonically
24233340d773SGleb Smirnoff * nondecreasing with lower power levels.
24243340d773SGleb Smirnoff *
24253340d773SGleb Smirnoff * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from
24263340d773SGleb Smirnoff * one milliwatt (dBm)
24273340d773SGleb Smirnoff *
24283340d773SGleb Smirnoff * Transmit power expressed as dBm (decibels from a 1 milliwatt
24293340d773SGleb Smirnoff * reference). This is the absolute power level measured at
24303340d773SGleb Smirnoff * the antenna port.
24313340d773SGleb Smirnoff *
24323340d773SGleb Smirnoff * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
24333340d773SGleb Smirnoff *
24343340d773SGleb Smirnoff * Properties of transmitted and received frames. See flags
24353340d773SGleb Smirnoff * defined below.
24363340d773SGleb Smirnoff *
24373340d773SGleb Smirnoff * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
24383340d773SGleb Smirnoff *
24393340d773SGleb Smirnoff * Unitless indication of the Rx/Tx antenna for this packet.
24403340d773SGleb Smirnoff * The first antenna is antenna 0.
24413340d773SGleb Smirnoff *
24423340d773SGleb Smirnoff * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
24433340d773SGleb Smirnoff *
24443340d773SGleb Smirnoff * Properties of received frames. See flags defined below.
24453340d773SGleb Smirnoff *
24463340d773SGleb Smirnoff * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap
24473340d773SGleb Smirnoff * uint16_t MHz
24483340d773SGleb Smirnoff * uint8_t channel number
24493340d773SGleb Smirnoff * uint8_t .5 dBm
24503340d773SGleb Smirnoff *
24513340d773SGleb Smirnoff * Extended channel specification: flags (see below) followed by
24523340d773SGleb Smirnoff * frequency in MHz, the corresponding IEEE channel number, and
24533340d773SGleb Smirnoff * finally the maximum regulatory transmit power cap in .5 dBm
24543340d773SGleb Smirnoff * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL
24553340d773SGleb Smirnoff * and only one of the two should be present.
24563340d773SGleb Smirnoff *
24573340d773SGleb Smirnoff * IEEE80211_RADIOTAP_MCS uint8_t known
24583340d773SGleb Smirnoff * uint8_t flags
24593340d773SGleb Smirnoff * uint8_t mcs
24603340d773SGleb Smirnoff *
24613340d773SGleb Smirnoff * Bitset indicating which fields have known values, followed
24623340d773SGleb Smirnoff * by bitset of flag values, followed by the MCS rate index as
24633340d773SGleb Smirnoff * in IEEE 802.11n.
24643340d773SGleb Smirnoff *
24653340d773SGleb Smirnoff *
24663340d773SGleb Smirnoff * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
24673340d773SGleb Smirnoff *
24683340d773SGleb Smirnoff * Contains the AMPDU information for the subframe.
24693340d773SGleb Smirnoff *
24703340d773SGleb Smirnoff * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
24713340d773SGleb Smirnoff *
24723340d773SGleb Smirnoff * Contains VHT information about this frame.
24733340d773SGleb Smirnoff *
24743340d773SGleb Smirnoff * IEEE80211_RADIOTAP_VENDOR_NAMESPACE
24753340d773SGleb Smirnoff * uint8_t OUI[3]
24763340d773SGleb Smirnoff * uint8_t subspace
24773340d773SGleb Smirnoff * uint16_t length
24783340d773SGleb Smirnoff *
24793340d773SGleb Smirnoff * The Vendor Namespace Field contains three sub-fields. The first
24803340d773SGleb Smirnoff * sub-field is 3 bytes long. It contains the vendor's IEEE 802
24813340d773SGleb Smirnoff * Organizationally Unique Identifier (OUI). The fourth byte is a
24823340d773SGleb Smirnoff * vendor-specific "namespace selector."
24833340d773SGleb Smirnoff *
24843340d773SGleb Smirnoff */
24853340d773SGleb Smirnoff enum ieee80211_radiotap_type {
24863340d773SGleb Smirnoff IEEE80211_RADIOTAP_TSFT = 0,
24873340d773SGleb Smirnoff IEEE80211_RADIOTAP_FLAGS = 1,
24883340d773SGleb Smirnoff IEEE80211_RADIOTAP_RATE = 2,
24893340d773SGleb Smirnoff IEEE80211_RADIOTAP_CHANNEL = 3,
24903340d773SGleb Smirnoff IEEE80211_RADIOTAP_FHSS = 4,
24913340d773SGleb Smirnoff IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
24923340d773SGleb Smirnoff IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
24933340d773SGleb Smirnoff IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
24943340d773SGleb Smirnoff IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
24953340d773SGleb Smirnoff IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
24963340d773SGleb Smirnoff IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
24973340d773SGleb Smirnoff IEEE80211_RADIOTAP_ANTENNA = 11,
24983340d773SGleb Smirnoff IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
24993340d773SGleb Smirnoff IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
25003340d773SGleb Smirnoff IEEE80211_RADIOTAP_RX_FLAGS = 14,
25013340d773SGleb Smirnoff /* NB: gap for netbsd definitions */
25023340d773SGleb Smirnoff IEEE80211_RADIOTAP_XCHANNEL = 18,
25033340d773SGleb Smirnoff IEEE80211_RADIOTAP_MCS = 19,
25043340d773SGleb Smirnoff IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
25053340d773SGleb Smirnoff IEEE80211_RADIOTAP_VHT = 21,
25063340d773SGleb Smirnoff IEEE80211_RADIOTAP_NAMESPACE = 29,
25073340d773SGleb Smirnoff IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
25083340d773SGleb Smirnoff IEEE80211_RADIOTAP_EXT = 31
25093340d773SGleb Smirnoff };
25103340d773SGleb Smirnoff
25113340d773SGleb Smirnoff /* channel attributes */
25123340d773SGleb Smirnoff #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */
25133340d773SGleb Smirnoff #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */
25143340d773SGleb Smirnoff #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */
25153340d773SGleb Smirnoff #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */
25163340d773SGleb Smirnoff #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */
25173340d773SGleb Smirnoff #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */
25183340d773SGleb Smirnoff #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */
25193340d773SGleb Smirnoff #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */
25203340d773SGleb Smirnoff #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */
25213340d773SGleb Smirnoff #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */
25223340d773SGleb Smirnoff #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */
25233340d773SGleb Smirnoff #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */
25243340d773SGleb Smirnoff #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */
25253340d773SGleb Smirnoff #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */
25263340d773SGleb Smirnoff #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */
25273340d773SGleb Smirnoff
25283340d773SGleb Smirnoff /* Useful combinations of channel characteristics, borrowed from Ethereal */
25293340d773SGleb Smirnoff #define IEEE80211_CHAN_A \
25303340d773SGleb Smirnoff (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
25313340d773SGleb Smirnoff #define IEEE80211_CHAN_B \
25323340d773SGleb Smirnoff (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
25333340d773SGleb Smirnoff #define IEEE80211_CHAN_G \
25343340d773SGleb Smirnoff (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
25353340d773SGleb Smirnoff #define IEEE80211_CHAN_TA \
25363340d773SGleb Smirnoff (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
25373340d773SGleb Smirnoff #define IEEE80211_CHAN_TG \
25383340d773SGleb Smirnoff (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO)
25393340d773SGleb Smirnoff
25403340d773SGleb Smirnoff
25413340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_FLAGS */
25423340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
25433340d773SGleb Smirnoff * during CFP
25443340d773SGleb Smirnoff */
25453340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
25463340d773SGleb Smirnoff * with short
25473340d773SGleb Smirnoff * preamble
25483340d773SGleb Smirnoff */
25493340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
25503340d773SGleb Smirnoff * with WEP encryption
25513340d773SGleb Smirnoff */
25523340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
25533340d773SGleb Smirnoff * with fragmentation
25543340d773SGleb Smirnoff */
25553340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
25563340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
25573340d773SGleb Smirnoff * 802.11 header and payload
25583340d773SGleb Smirnoff * (to 32-bit boundary)
25593340d773SGleb Smirnoff */
25603340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */
25613340d773SGleb Smirnoff
25623340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_RX_FLAGS */
25633340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
25643340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */
25653340d773SGleb Smirnoff
25663340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_MCS known */
25673340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01
25683340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */
25693340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04
25703340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08
25713340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10
25723340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20
25733340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40
25743340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80
25753340d773SGleb Smirnoff
25763340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_MCS flags */
25773340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03
25783340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0
25793340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1
25803340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2
25813340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3
25823340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */
25833340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08
25843340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
25853340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
25863340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_STBC_1 1
25873340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_STBC_2 2
25883340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_STBC_3 3
25893340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
25903340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80
25913340d773SGleb Smirnoff
25923340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
25933340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
25943340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
25953340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
25963340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
25973340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
25983340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
25993340d773SGleb Smirnoff
26003340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_VHT known */
26013340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001
26023340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002
26033340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004
26043340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008
26053340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010
26063340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020
26073340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040
26083340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080
26093340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100
26103340d773SGleb Smirnoff
26113340d773SGleb Smirnoff /* For IEEE80211_RADIOTAP_VHT flags */
26123340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_STBC 0x01
26133340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02
26143340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04
26153340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08
26163340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10
26173340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20
26183340d773SGleb Smirnoff
26193340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f
26203340d773SGleb Smirnoff
26213340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f
26223340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0
26233340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4
26243340d773SGleb Smirnoff
26253340d773SGleb Smirnoff #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01
26263340d773SGleb Smirnoff
26276efb4aa1SSam Leffler #define IEEE80211_CHAN_FHSS \
26286efb4aa1SSam Leffler (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
26296efb4aa1SSam Leffler #define IEEE80211_CHAN_A \
26306efb4aa1SSam Leffler (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
26316efb4aa1SSam Leffler #define IEEE80211_CHAN_B \
26326efb4aa1SSam Leffler (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
26336efb4aa1SSam Leffler #define IEEE80211_CHAN_PUREG \
26346efb4aa1SSam Leffler (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
26356efb4aa1SSam Leffler #define IEEE80211_CHAN_G \
26366efb4aa1SSam Leffler (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
26376efb4aa1SSam Leffler
26386efb4aa1SSam Leffler #define IS_CHAN_FHSS(flags) \
26396efb4aa1SSam Leffler ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
26406efb4aa1SSam Leffler #define IS_CHAN_A(flags) \
26416efb4aa1SSam Leffler ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
26426efb4aa1SSam Leffler #define IS_CHAN_B(flags) \
26436efb4aa1SSam Leffler ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
26446efb4aa1SSam Leffler #define IS_CHAN_PUREG(flags) \
26456efb4aa1SSam Leffler ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
26466efb4aa1SSam Leffler #define IS_CHAN_G(flags) \
26476efb4aa1SSam Leffler ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
26486efb4aa1SSam Leffler #define IS_CHAN_ANYG(flags) \
26496efb4aa1SSam Leffler (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
26506efb4aa1SSam Leffler
26516efb4aa1SSam Leffler static void
print_chaninfo(netdissect_options * ndo,uint16_t freq,uint32_t flags,uint32_t presentflags)26523c602fabSXin LI print_chaninfo(netdissect_options *ndo,
2653ee67461eSJoseph Mingrone uint16_t freq, uint32_t flags, uint32_t presentflags)
26546efb4aa1SSam Leffler {
2655ee67461eSJoseph Mingrone ND_PRINT("%u MHz", freq);
26563340d773SGleb Smirnoff if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
26573340d773SGleb Smirnoff /*
26583340d773SGleb Smirnoff * We have the MCS field, so this is 11n, regardless
26593340d773SGleb Smirnoff * of what the channel flags say.
26603340d773SGleb Smirnoff */
2661ee67461eSJoseph Mingrone ND_PRINT(" 11n");
26623340d773SGleb Smirnoff } else {
26636efb4aa1SSam Leffler if (IS_CHAN_FHSS(flags))
2664ee67461eSJoseph Mingrone ND_PRINT(" FHSS");
26656efb4aa1SSam Leffler if (IS_CHAN_A(flags)) {
26666efb4aa1SSam Leffler if (flags & IEEE80211_CHAN_HALF)
2667ee67461eSJoseph Mingrone ND_PRINT(" 11a/10Mhz");
26686efb4aa1SSam Leffler else if (flags & IEEE80211_CHAN_QUARTER)
2669ee67461eSJoseph Mingrone ND_PRINT(" 11a/5Mhz");
26706efb4aa1SSam Leffler else
2671ee67461eSJoseph Mingrone ND_PRINT(" 11a");
26726efb4aa1SSam Leffler }
26736efb4aa1SSam Leffler if (IS_CHAN_ANYG(flags)) {
26746efb4aa1SSam Leffler if (flags & IEEE80211_CHAN_HALF)
2675ee67461eSJoseph Mingrone ND_PRINT(" 11g/10Mhz");
26766efb4aa1SSam Leffler else if (flags & IEEE80211_CHAN_QUARTER)
2677ee67461eSJoseph Mingrone ND_PRINT(" 11g/5Mhz");
26786efb4aa1SSam Leffler else
2679ee67461eSJoseph Mingrone ND_PRINT(" 11g");
26806efb4aa1SSam Leffler } else if (IS_CHAN_B(flags))
2681ee67461eSJoseph Mingrone ND_PRINT(" 11b");
26826efb4aa1SSam Leffler if (flags & IEEE80211_CHAN_TURBO)
2683ee67461eSJoseph Mingrone ND_PRINT(" Turbo");
26843340d773SGleb Smirnoff }
26853340d773SGleb Smirnoff /*
26863340d773SGleb Smirnoff * These apply to 11n.
26873340d773SGleb Smirnoff */
26886efb4aa1SSam Leffler if (flags & IEEE80211_CHAN_HT20)
2689ee67461eSJoseph Mingrone ND_PRINT(" ht/20");
26906efb4aa1SSam Leffler else if (flags & IEEE80211_CHAN_HT40D)
2691ee67461eSJoseph Mingrone ND_PRINT(" ht/40-");
26926efb4aa1SSam Leffler else if (flags & IEEE80211_CHAN_HT40U)
2693ee67461eSJoseph Mingrone ND_PRINT(" ht/40+");
2694ee67461eSJoseph Mingrone ND_PRINT(" ");
26956efb4aa1SSam Leffler }
26966efb4aa1SSam Leffler
26971de50e9fSSam Leffler static int
print_radiotap_field(netdissect_options * ndo,struct cpack_state * s,uint32_t bit,uint8_t * flagsp,uint32_t presentflags)26983c602fabSXin LI print_radiotap_field(netdissect_options *ndo,
26993340d773SGleb Smirnoff struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
27003340d773SGleb Smirnoff uint32_t presentflags)
27011de50e9fSSam Leffler {
27023340d773SGleb Smirnoff u_int i;
27031de50e9fSSam Leffler int rc;
27041de50e9fSSam Leffler
27051de50e9fSSam Leffler switch (bit) {
2706cac3dcd5SXin LI
27073340d773SGleb Smirnoff case IEEE80211_RADIOTAP_TSFT: {
27083340d773SGleb Smirnoff uint64_t tsft;
2709cac3dcd5SXin LI
2710ee67461eSJoseph Mingrone rc = nd_cpack_uint64(ndo, s, &tsft);
27113340d773SGleb Smirnoff if (rc != 0)
27123340d773SGleb Smirnoff goto trunc;
2713ee67461eSJoseph Mingrone ND_PRINT("%" PRIu64 "us tsft ", tsft);
2714cac3dcd5SXin LI break;
2715cac3dcd5SXin LI }
2716cac3dcd5SXin LI
27173340d773SGleb Smirnoff case IEEE80211_RADIOTAP_FLAGS: {
27183340d773SGleb Smirnoff uint8_t flagsval;
2719cac3dcd5SXin LI
2720ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &flagsval);
27213340d773SGleb Smirnoff if (rc != 0)
27223340d773SGleb Smirnoff goto trunc;
27233340d773SGleb Smirnoff *flagsp = flagsval;
27243340d773SGleb Smirnoff if (flagsval & IEEE80211_RADIOTAP_F_CFP)
2725ee67461eSJoseph Mingrone ND_PRINT("cfp ");
27263340d773SGleb Smirnoff if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
2727ee67461eSJoseph Mingrone ND_PRINT("short preamble ");
27283340d773SGleb Smirnoff if (flagsval & IEEE80211_RADIOTAP_F_WEP)
2729ee67461eSJoseph Mingrone ND_PRINT("wep ");
27303340d773SGleb Smirnoff if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
2731ee67461eSJoseph Mingrone ND_PRINT("fragmented ");
27323340d773SGleb Smirnoff if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
2733ee67461eSJoseph Mingrone ND_PRINT("bad-fcs ");
2734cac3dcd5SXin LI break;
2735cac3dcd5SXin LI }
27361de50e9fSSam Leffler
27373340d773SGleb Smirnoff case IEEE80211_RADIOTAP_RATE: {
27383340d773SGleb Smirnoff uint8_t rate;
27391de50e9fSSam Leffler
2740ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &rate);
27413340d773SGleb Smirnoff if (rc != 0)
27423340d773SGleb Smirnoff goto trunc;
2743cac3dcd5SXin LI /*
2744cac3dcd5SXin LI * XXX On FreeBSD rate & 0x80 means we have an MCS. On
2745cac3dcd5SXin LI * Linux and AirPcap it does not. (What about
2746ee67461eSJoseph Mingrone * macOS, NetBSD, OpenBSD, and DragonFly BSD?)
2747cac3dcd5SXin LI *
2748cac3dcd5SXin LI * This is an issue either for proprietary extensions
2749cac3dcd5SXin LI * to 11a or 11g, which do exist, or for 11n
2750cac3dcd5SXin LI * implementations that stuff a rate value into
2751cac3dcd5SXin LI * this field, which also appear to exist.
2752cac3dcd5SXin LI *
2753cac3dcd5SXin LI * We currently handle that by assuming that
2754cac3dcd5SXin LI * if the 0x80 bit is set *and* the remaining
2755cac3dcd5SXin LI * bits have a value between 0 and 15 it's
2756cac3dcd5SXin LI * an MCS value, otherwise it's a rate. If
2757cac3dcd5SXin LI * there are cases where systems that use
2758cac3dcd5SXin LI * "0x80 + MCS index" for MCS indices > 15,
2759cac3dcd5SXin LI * or stuff a rate value here between 64 and
2760cac3dcd5SXin LI * 71.5 Mb/s in here, we'll need a preference
2761cac3dcd5SXin LI * setting. Such rates do exist, e.g. 11n
2762cac3dcd5SXin LI * MCS 7 at 20 MHz with a long guard interval.
2763cac3dcd5SXin LI */
27643340d773SGleb Smirnoff if (rate >= 0x80 && rate <= 0x8f) {
2765cac3dcd5SXin LI /*
2766cac3dcd5SXin LI * XXX - we don't know the channel width
2767cac3dcd5SXin LI * or guard interval length, so we can't
2768cac3dcd5SXin LI * convert this to a data rate.
2769cac3dcd5SXin LI *
2770cac3dcd5SXin LI * If you want us to show a data rate,
2771cac3dcd5SXin LI * use the MCS field, not the Rate field;
2772cac3dcd5SXin LI * the MCS field includes not only the
2773cac3dcd5SXin LI * MCS index, it also includes bandwidth
2774cac3dcd5SXin LI * and guard interval information.
2775cac3dcd5SXin LI *
2776cac3dcd5SXin LI * XXX - can we get the channel width
2777cac3dcd5SXin LI * from XChannel and the guard interval
2778cac3dcd5SXin LI * information from Flags, at least on
2779cac3dcd5SXin LI * FreeBSD?
2780cac3dcd5SXin LI */
2781ee67461eSJoseph Mingrone ND_PRINT("MCS %u ", rate & 0x7f);
2782cac3dcd5SXin LI } else
2783ee67461eSJoseph Mingrone ND_PRINT("%2.1f Mb/s ", .5 * rate);
27841de50e9fSSam Leffler break;
27853340d773SGleb Smirnoff }
27863340d773SGleb Smirnoff
27873340d773SGleb Smirnoff case IEEE80211_RADIOTAP_CHANNEL: {
27883340d773SGleb Smirnoff uint16_t frequency;
27893340d773SGleb Smirnoff uint16_t flags;
27903340d773SGleb Smirnoff
2791ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &frequency);
27923340d773SGleb Smirnoff if (rc != 0)
27933340d773SGleb Smirnoff goto trunc;
2794ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &flags);
27953340d773SGleb Smirnoff if (rc != 0)
27963340d773SGleb Smirnoff goto trunc;
27973340d773SGleb Smirnoff /*
27983340d773SGleb Smirnoff * If CHANNEL and XCHANNEL are both present, skip
27993340d773SGleb Smirnoff * CHANNEL.
28003340d773SGleb Smirnoff */
28013340d773SGleb Smirnoff if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
28021de50e9fSSam Leffler break;
28033340d773SGleb Smirnoff print_chaninfo(ndo, frequency, flags, presentflags);
28041de50e9fSSam Leffler break;
28053340d773SGleb Smirnoff }
28063340d773SGleb Smirnoff
28073340d773SGleb Smirnoff case IEEE80211_RADIOTAP_FHSS: {
28083340d773SGleb Smirnoff uint8_t hopset;
28093340d773SGleb Smirnoff uint8_t hoppat;
28103340d773SGleb Smirnoff
2811ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &hopset);
28123340d773SGleb Smirnoff if (rc != 0)
28133340d773SGleb Smirnoff goto trunc;
2814ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &hoppat);
28153340d773SGleb Smirnoff if (rc != 0)
28163340d773SGleb Smirnoff goto trunc;
2817ee67461eSJoseph Mingrone ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
28181de50e9fSSam Leffler break;
28193340d773SGleb Smirnoff }
28203340d773SGleb Smirnoff
28213340d773SGleb Smirnoff case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
28223340d773SGleb Smirnoff int8_t dbm_antsignal;
28233340d773SGleb Smirnoff
2824ee67461eSJoseph Mingrone rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
28253340d773SGleb Smirnoff if (rc != 0)
28263340d773SGleb Smirnoff goto trunc;
2827ee67461eSJoseph Mingrone ND_PRINT("%ddBm signal ", dbm_antsignal);
28281de50e9fSSam Leffler break;
28293340d773SGleb Smirnoff }
28303340d773SGleb Smirnoff
28313340d773SGleb Smirnoff case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
28323340d773SGleb Smirnoff int8_t dbm_antnoise;
28333340d773SGleb Smirnoff
2834ee67461eSJoseph Mingrone rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
28353340d773SGleb Smirnoff if (rc != 0)
28363340d773SGleb Smirnoff goto trunc;
2837ee67461eSJoseph Mingrone ND_PRINT("%ddBm noise ", dbm_antnoise);
28381de50e9fSSam Leffler break;
28393340d773SGleb Smirnoff }
28403340d773SGleb Smirnoff
28413340d773SGleb Smirnoff case IEEE80211_RADIOTAP_LOCK_QUALITY: {
28423340d773SGleb Smirnoff uint16_t lock_quality;
28433340d773SGleb Smirnoff
2844ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &lock_quality);
28453340d773SGleb Smirnoff if (rc != 0)
28463340d773SGleb Smirnoff goto trunc;
2847ee67461eSJoseph Mingrone ND_PRINT("%u sq ", lock_quality);
28481de50e9fSSam Leffler break;
28493340d773SGleb Smirnoff }
28503340d773SGleb Smirnoff
28513340d773SGleb Smirnoff case IEEE80211_RADIOTAP_TX_ATTENUATION: {
2852ee67461eSJoseph Mingrone int16_t tx_attenuation;
28533340d773SGleb Smirnoff
2854ee67461eSJoseph Mingrone rc = nd_cpack_int16(ndo, s, &tx_attenuation);
28553340d773SGleb Smirnoff if (rc != 0)
28563340d773SGleb Smirnoff goto trunc;
2857ee67461eSJoseph Mingrone ND_PRINT("%d tx power ", -tx_attenuation);
28581de50e9fSSam Leffler break;
28593340d773SGleb Smirnoff }
28603340d773SGleb Smirnoff
28613340d773SGleb Smirnoff case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
2862ee67461eSJoseph Mingrone int8_t db_tx_attenuation;
28633340d773SGleb Smirnoff
2864ee67461eSJoseph Mingrone rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
28653340d773SGleb Smirnoff if (rc != 0)
28663340d773SGleb Smirnoff goto trunc;
2867ee67461eSJoseph Mingrone ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
28681de50e9fSSam Leffler break;
28693340d773SGleb Smirnoff }
28703340d773SGleb Smirnoff
28713340d773SGleb Smirnoff case IEEE80211_RADIOTAP_DBM_TX_POWER: {
28723340d773SGleb Smirnoff int8_t dbm_tx_power;
28733340d773SGleb Smirnoff
2874ee67461eSJoseph Mingrone rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
28753340d773SGleb Smirnoff if (rc != 0)
28763340d773SGleb Smirnoff goto trunc;
2877ee67461eSJoseph Mingrone ND_PRINT("%ddBm tx power ", dbm_tx_power);
28781de50e9fSSam Leffler break;
28793340d773SGleb Smirnoff }
28803340d773SGleb Smirnoff
28813340d773SGleb Smirnoff case IEEE80211_RADIOTAP_ANTENNA: {
28823340d773SGleb Smirnoff uint8_t antenna;
28833340d773SGleb Smirnoff
2884ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &antenna);
28853340d773SGleb Smirnoff if (rc != 0)
28863340d773SGleb Smirnoff goto trunc;
2887ee67461eSJoseph Mingrone ND_PRINT("antenna %u ", antenna);
28881de50e9fSSam Leffler break;
28893340d773SGleb Smirnoff }
28903340d773SGleb Smirnoff
28913340d773SGleb Smirnoff case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
28923340d773SGleb Smirnoff uint8_t db_antsignal;
28933340d773SGleb Smirnoff
2894ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &db_antsignal);
28953340d773SGleb Smirnoff if (rc != 0)
28963340d773SGleb Smirnoff goto trunc;
2897ee67461eSJoseph Mingrone ND_PRINT("%udB signal ", db_antsignal);
28981de50e9fSSam Leffler break;
28993340d773SGleb Smirnoff }
29003340d773SGleb Smirnoff
29013340d773SGleb Smirnoff case IEEE80211_RADIOTAP_DB_ANTNOISE: {
29023340d773SGleb Smirnoff uint8_t db_antnoise;
29033340d773SGleb Smirnoff
2904ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &db_antnoise);
29053340d773SGleb Smirnoff if (rc != 0)
29063340d773SGleb Smirnoff goto trunc;
2907ee67461eSJoseph Mingrone ND_PRINT("%udB noise ", db_antnoise);
29083340d773SGleb Smirnoff break;
29093340d773SGleb Smirnoff }
29103340d773SGleb Smirnoff
29113340d773SGleb Smirnoff case IEEE80211_RADIOTAP_RX_FLAGS: {
29123340d773SGleb Smirnoff uint16_t rx_flags;
29133340d773SGleb Smirnoff
2914ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &rx_flags);
29153340d773SGleb Smirnoff if (rc != 0)
29163340d773SGleb Smirnoff goto trunc;
2917cac3dcd5SXin LI /* Do nothing for now */
2918cac3dcd5SXin LI break;
29193340d773SGleb Smirnoff }
29203340d773SGleb Smirnoff
29213340d773SGleb Smirnoff case IEEE80211_RADIOTAP_XCHANNEL: {
29223340d773SGleb Smirnoff uint32_t flags;
29233340d773SGleb Smirnoff uint16_t frequency;
29243340d773SGleb Smirnoff uint8_t channel;
29253340d773SGleb Smirnoff uint8_t maxpower;
29263340d773SGleb Smirnoff
2927ee67461eSJoseph Mingrone rc = nd_cpack_uint32(ndo, s, &flags);
29283340d773SGleb Smirnoff if (rc != 0)
29293340d773SGleb Smirnoff goto trunc;
2930ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &frequency);
29313340d773SGleb Smirnoff if (rc != 0)
29323340d773SGleb Smirnoff goto trunc;
2933ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &channel);
29343340d773SGleb Smirnoff if (rc != 0)
29353340d773SGleb Smirnoff goto trunc;
2936ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &maxpower);
29373340d773SGleb Smirnoff if (rc != 0)
29383340d773SGleb Smirnoff goto trunc;
29393340d773SGleb Smirnoff print_chaninfo(ndo, frequency, flags, presentflags);
29406efb4aa1SSam Leffler break;
29413340d773SGleb Smirnoff }
29423340d773SGleb Smirnoff
2943cac3dcd5SXin LI case IEEE80211_RADIOTAP_MCS: {
29443340d773SGleb Smirnoff uint8_t known;
29453340d773SGleb Smirnoff uint8_t flags;
29463340d773SGleb Smirnoff uint8_t mcs_index;
29473340d773SGleb Smirnoff static const char *ht_bandwidth[4] = {
2948cac3dcd5SXin LI "20 MHz",
2949cac3dcd5SXin LI "40 MHz",
2950cac3dcd5SXin LI "20 MHz (L)",
2951cac3dcd5SXin LI "20 MHz (U)"
2952cac3dcd5SXin LI };
2953cac3dcd5SXin LI float htrate;
2954cac3dcd5SXin LI
2955ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &known);
29563340d773SGleb Smirnoff if (rc != 0)
29573340d773SGleb Smirnoff goto trunc;
2958ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &flags);
29593340d773SGleb Smirnoff if (rc != 0)
29603340d773SGleb Smirnoff goto trunc;
2961ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &mcs_index);
29623340d773SGleb Smirnoff if (rc != 0)
29633340d773SGleb Smirnoff goto trunc;
29643340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
2965cac3dcd5SXin LI /*
2966cac3dcd5SXin LI * We know the MCS index.
2967cac3dcd5SXin LI */
29683340d773SGleb Smirnoff if (mcs_index <= MAX_MCS_INDEX) {
2969cac3dcd5SXin LI /*
2970cac3dcd5SXin LI * And it's in-range.
2971cac3dcd5SXin LI */
29723340d773SGleb Smirnoff if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
2973cac3dcd5SXin LI /*
2974cac3dcd5SXin LI * And we know both the bandwidth and
2975cac3dcd5SXin LI * the guard interval, so we can look
2976cac3dcd5SXin LI * up the rate.
2977cac3dcd5SXin LI */
2978cac3dcd5SXin LI htrate =
2979ee67461eSJoseph Mingrone ieee80211_float_htrates
2980ee67461eSJoseph Mingrone [mcs_index]
2981ee67461eSJoseph Mingrone [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
29823340d773SGleb Smirnoff [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
2983cac3dcd5SXin LI } else {
2984cac3dcd5SXin LI /*
2985cac3dcd5SXin LI * We don't know both the bandwidth
2986cac3dcd5SXin LI * and the guard interval, so we can
2987cac3dcd5SXin LI * only report the MCS index.
2988cac3dcd5SXin LI */
2989cac3dcd5SXin LI htrate = 0.0;
2990cac3dcd5SXin LI }
2991cac3dcd5SXin LI } else {
2992cac3dcd5SXin LI /*
2993cac3dcd5SXin LI * The MCS value is out of range.
2994cac3dcd5SXin LI */
2995cac3dcd5SXin LI htrate = 0.0;
2996cac3dcd5SXin LI }
2997cac3dcd5SXin LI if (htrate != 0.0) {
2998cac3dcd5SXin LI /*
2999cac3dcd5SXin LI * We have the rate.
3000cac3dcd5SXin LI * Print it.
3001cac3dcd5SXin LI */
3002ee67461eSJoseph Mingrone ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
3003cac3dcd5SXin LI } else {
3004cac3dcd5SXin LI /*
3005cac3dcd5SXin LI * We at least have the MCS index.
3006cac3dcd5SXin LI * Print it.
3007cac3dcd5SXin LI */
3008ee67461eSJoseph Mingrone ND_PRINT("MCS %u ", mcs_index);
3009cac3dcd5SXin LI }
3010cac3dcd5SXin LI }
30113340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
3012ee67461eSJoseph Mingrone ND_PRINT("%s ",
3013ee67461eSJoseph Mingrone ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
3014cac3dcd5SXin LI }
30153340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
3016ee67461eSJoseph Mingrone ND_PRINT("%s GI ",
30173340d773SGleb Smirnoff (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
3018ee67461eSJoseph Mingrone "short" : "long");
3019cac3dcd5SXin LI }
30203340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
3021ee67461eSJoseph Mingrone ND_PRINT("%s ",
30223340d773SGleb Smirnoff (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
3023ee67461eSJoseph Mingrone "greenfield" : "mixed");
3024cac3dcd5SXin LI }
30253340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
3026ee67461eSJoseph Mingrone ND_PRINT("%s FEC ",
30273340d773SGleb Smirnoff (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
3028ee67461eSJoseph Mingrone "LDPC" : "BCC");
3029cac3dcd5SXin LI }
30303340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
3031ee67461eSJoseph Mingrone ND_PRINT("RX-STBC%u ",
3032ee67461eSJoseph Mingrone (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
30333c602fabSXin LI }
3034cac3dcd5SXin LI break;
3035cac3dcd5SXin LI }
30363340d773SGleb Smirnoff
30373340d773SGleb Smirnoff case IEEE80211_RADIOTAP_AMPDU_STATUS: {
30383340d773SGleb Smirnoff uint32_t reference_num;
30393340d773SGleb Smirnoff uint16_t flags;
30403340d773SGleb Smirnoff uint8_t delim_crc;
30413340d773SGleb Smirnoff uint8_t reserved;
30423340d773SGleb Smirnoff
3043ee67461eSJoseph Mingrone rc = nd_cpack_uint32(ndo, s, &reference_num);
30443340d773SGleb Smirnoff if (rc != 0)
30453340d773SGleb Smirnoff goto trunc;
3046ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &flags);
30473340d773SGleb Smirnoff if (rc != 0)
30483340d773SGleb Smirnoff goto trunc;
3049ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &delim_crc);
30503340d773SGleb Smirnoff if (rc != 0)
30513340d773SGleb Smirnoff goto trunc;
3052ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &reserved);
30533340d773SGleb Smirnoff if (rc != 0)
30543340d773SGleb Smirnoff goto trunc;
30553340d773SGleb Smirnoff /* Do nothing for now */
30563340d773SGleb Smirnoff break;
30571de50e9fSSam Leffler }
30583340d773SGleb Smirnoff
30593340d773SGleb Smirnoff case IEEE80211_RADIOTAP_VHT: {
30603340d773SGleb Smirnoff uint16_t known;
30613340d773SGleb Smirnoff uint8_t flags;
30623340d773SGleb Smirnoff uint8_t bandwidth;
30633340d773SGleb Smirnoff uint8_t mcs_nss[4];
30643340d773SGleb Smirnoff uint8_t coding;
30653340d773SGleb Smirnoff uint8_t group_id;
30663340d773SGleb Smirnoff uint16_t partial_aid;
30673340d773SGleb Smirnoff static const char *vht_bandwidth[32] = {
30683340d773SGleb Smirnoff "20 MHz",
30693340d773SGleb Smirnoff "40 MHz",
30703340d773SGleb Smirnoff "20 MHz (L)",
30713340d773SGleb Smirnoff "20 MHz (U)",
30723340d773SGleb Smirnoff "80 MHz",
30733340d773SGleb Smirnoff "80 MHz (L)",
30743340d773SGleb Smirnoff "80 MHz (U)",
30753340d773SGleb Smirnoff "80 MHz (LL)",
30763340d773SGleb Smirnoff "80 MHz (LU)",
30773340d773SGleb Smirnoff "80 MHz (UL)",
30783340d773SGleb Smirnoff "80 MHz (UU)",
30793340d773SGleb Smirnoff "160 MHz",
30803340d773SGleb Smirnoff "160 MHz (L)",
30813340d773SGleb Smirnoff "160 MHz (U)",
30823340d773SGleb Smirnoff "160 MHz (LL)",
30833340d773SGleb Smirnoff "160 MHz (LU)",
30843340d773SGleb Smirnoff "160 MHz (UL)",
30853340d773SGleb Smirnoff "160 MHz (UU)",
30863340d773SGleb Smirnoff "160 MHz (LLL)",
30873340d773SGleb Smirnoff "160 MHz (LLU)",
30883340d773SGleb Smirnoff "160 MHz (LUL)",
30893340d773SGleb Smirnoff "160 MHz (UUU)",
30903340d773SGleb Smirnoff "160 MHz (ULL)",
30913340d773SGleb Smirnoff "160 MHz (ULU)",
30923340d773SGleb Smirnoff "160 MHz (UUL)",
30933340d773SGleb Smirnoff "160 MHz (UUU)",
30943340d773SGleb Smirnoff "unknown (26)",
30953340d773SGleb Smirnoff "unknown (27)",
30963340d773SGleb Smirnoff "unknown (28)",
30973340d773SGleb Smirnoff "unknown (29)",
30983340d773SGleb Smirnoff "unknown (30)",
30993340d773SGleb Smirnoff "unknown (31)"
31003340d773SGleb Smirnoff };
31013340d773SGleb Smirnoff
3102ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &known);
31033340d773SGleb Smirnoff if (rc != 0)
31043340d773SGleb Smirnoff goto trunc;
3105ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &flags);
31063340d773SGleb Smirnoff if (rc != 0)
31073340d773SGleb Smirnoff goto trunc;
3108ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &bandwidth);
31093340d773SGleb Smirnoff if (rc != 0)
31103340d773SGleb Smirnoff goto trunc;
31113340d773SGleb Smirnoff for (i = 0; i < 4; i++) {
3112ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
31133340d773SGleb Smirnoff if (rc != 0)
31143340d773SGleb Smirnoff goto trunc;
31153340d773SGleb Smirnoff }
3116ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &coding);
31173340d773SGleb Smirnoff if (rc != 0)
31183340d773SGleb Smirnoff goto trunc;
3119ee67461eSJoseph Mingrone rc = nd_cpack_uint8(ndo, s, &group_id);
31203340d773SGleb Smirnoff if (rc != 0)
31213340d773SGleb Smirnoff goto trunc;
3122ee67461eSJoseph Mingrone rc = nd_cpack_uint16(ndo, s, &partial_aid);
31233340d773SGleb Smirnoff if (rc != 0)
31243340d773SGleb Smirnoff goto trunc;
31253340d773SGleb Smirnoff for (i = 0; i < 4; i++) {
31263340d773SGleb Smirnoff u_int nss, mcs;
31273340d773SGleb Smirnoff nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
31283340d773SGleb Smirnoff mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
31293340d773SGleb Smirnoff
31303340d773SGleb Smirnoff if (nss == 0)
31313340d773SGleb Smirnoff continue;
31323340d773SGleb Smirnoff
3133ee67461eSJoseph Mingrone ND_PRINT("User %u MCS %u ", i, mcs);
3134ee67461eSJoseph Mingrone ND_PRINT("%s FEC ",
31353340d773SGleb Smirnoff (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
3136ee67461eSJoseph Mingrone "LDPC" : "BCC");
31373340d773SGleb Smirnoff }
31383340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
3139ee67461eSJoseph Mingrone ND_PRINT("%s ",
3140ee67461eSJoseph Mingrone vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
31413340d773SGleb Smirnoff }
31423340d773SGleb Smirnoff if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
3143ee67461eSJoseph Mingrone ND_PRINT("%s GI ",
31443340d773SGleb Smirnoff (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
3145ee67461eSJoseph Mingrone "short" : "long");
31463340d773SGleb Smirnoff }
31473340d773SGleb Smirnoff break;
31483340d773SGleb Smirnoff }
31493340d773SGleb Smirnoff
31503340d773SGleb Smirnoff default:
31513340d773SGleb Smirnoff /* this bit indicates a field whose
31523340d773SGleb Smirnoff * size we do not know, so we cannot
31533340d773SGleb Smirnoff * proceed. Just print the bit number.
31543340d773SGleb Smirnoff */
3155ee67461eSJoseph Mingrone ND_PRINT("[bit %u] ", bit);
31563340d773SGleb Smirnoff return -1;
31573340d773SGleb Smirnoff }
31583340d773SGleb Smirnoff
31593340d773SGleb Smirnoff return 0;
31603340d773SGleb Smirnoff
31613340d773SGleb Smirnoff trunc:
3162ee67461eSJoseph Mingrone nd_print_trunc(ndo);
31633340d773SGleb Smirnoff return rc;
31643340d773SGleb Smirnoff }
31653340d773SGleb Smirnoff
31663340d773SGleb Smirnoff
31673340d773SGleb Smirnoff static int
print_in_radiotap_namespace(netdissect_options * ndo,struct cpack_state * s,uint8_t * flags,uint32_t presentflags,int bit0)31683340d773SGleb Smirnoff print_in_radiotap_namespace(netdissect_options *ndo,
31693340d773SGleb Smirnoff struct cpack_state *s, uint8_t *flags,
31703340d773SGleb Smirnoff uint32_t presentflags, int bit0)
31713340d773SGleb Smirnoff {
31723340d773SGleb Smirnoff #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
31733340d773SGleb Smirnoff #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
31743340d773SGleb Smirnoff #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
31753340d773SGleb Smirnoff #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
31763340d773SGleb Smirnoff #define BITNO_2(x) (((x) & 2) ? 1 : 0)
31773340d773SGleb Smirnoff uint32_t present, next_present;
31783340d773SGleb Smirnoff int bitno;
31793340d773SGleb Smirnoff enum ieee80211_radiotap_type bit;
31803340d773SGleb Smirnoff int rc;
31813340d773SGleb Smirnoff
31823340d773SGleb Smirnoff for (present = presentflags; present; present = next_present) {
31833340d773SGleb Smirnoff /*
31843340d773SGleb Smirnoff * Clear the least significant bit that is set.
31853340d773SGleb Smirnoff */
31863340d773SGleb Smirnoff next_present = present & (present - 1);
31873340d773SGleb Smirnoff
31883340d773SGleb Smirnoff /*
31893340d773SGleb Smirnoff * Get the bit number, within this presence word,
31903340d773SGleb Smirnoff * of the remaining least significant bit that
31913340d773SGleb Smirnoff * is set.
31923340d773SGleb Smirnoff */
31933340d773SGleb Smirnoff bitno = BITNO_32(present ^ next_present);
31943340d773SGleb Smirnoff
31953340d773SGleb Smirnoff /*
31963340d773SGleb Smirnoff * Stop if this is one of the "same meaning
31973340d773SGleb Smirnoff * in all presence flags" bits.
31983340d773SGleb Smirnoff */
31993340d773SGleb Smirnoff if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
32003340d773SGleb Smirnoff break;
32013340d773SGleb Smirnoff
32023340d773SGleb Smirnoff /*
32033340d773SGleb Smirnoff * Get the radiotap bit number of that bit.
32043340d773SGleb Smirnoff */
32053340d773SGleb Smirnoff bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
32063340d773SGleb Smirnoff
32073340d773SGleb Smirnoff rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
32083340d773SGleb Smirnoff if (rc != 0)
32093340d773SGleb Smirnoff return rc;
32103340d773SGleb Smirnoff }
32113340d773SGleb Smirnoff
32121de50e9fSSam Leffler return 0;
32131de50e9fSSam Leffler }
32141de50e9fSSam Leffler
321539e421e8SCy Schubert u_int
ieee802_11_radio_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)32163c602fabSXin LI ieee802_11_radio_print(netdissect_options *ndo,
32173c602fabSXin LI const u_char *p, u_int length, u_int caplen)
32185b0fe478SBruce M Simpson {
321927df3f5dSRui Paulo #define BIT(n) (1U << n)
32201de50e9fSSam Leffler #define IS_EXTENDED(__p) \
3221ee67461eSJoseph Mingrone (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
32221de50e9fSSam Leffler
32231de50e9fSSam Leffler struct cpack_state cpacker;
32243340d773SGleb Smirnoff const struct ieee80211_radiotap_header *hdr;
32253340d773SGleb Smirnoff uint32_t presentflags;
3226ee67461eSJoseph Mingrone const nd_uint32_t *presentp, *last_presentp;
32273340d773SGleb Smirnoff int vendor_namespace;
32283340d773SGleb Smirnoff uint8_t vendor_oui[3];
32293340d773SGleb Smirnoff uint8_t vendor_subnamespace;
32303340d773SGleb Smirnoff uint16_t skip_length;
32311de50e9fSSam Leffler int bit0;
32321de50e9fSSam Leffler u_int len;
32333c602fabSXin LI uint8_t flags;
3234abf25193SMax Laier int pad;
323527df3f5dSRui Paulo u_int fcslen;
32361de50e9fSSam Leffler
3237ee67461eSJoseph Mingrone ndo->ndo_protocol = "802.11_radio";
32381de50e9fSSam Leffler if (caplen < sizeof(*hdr)) {
3239ee67461eSJoseph Mingrone nd_print_trunc(ndo);
32401de50e9fSSam Leffler return caplen;
32411de50e9fSSam Leffler }
32421de50e9fSSam Leffler
32433340d773SGleb Smirnoff hdr = (const struct ieee80211_radiotap_header *)p;
32441de50e9fSSam Leffler
3245ee67461eSJoseph Mingrone len = GET_LE_U_2(hdr->it_len);
324639e421e8SCy Schubert if (len < sizeof(*hdr)) {
324739e421e8SCy Schubert /*
324839e421e8SCy Schubert * The length is the length of the entire header, so
324939e421e8SCy Schubert * it must be as large as the fixed-length part of
325039e421e8SCy Schubert * the header.
325139e421e8SCy Schubert */
3252ee67461eSJoseph Mingrone nd_print_trunc(ndo);
325339e421e8SCy Schubert return caplen;
325439e421e8SCy Schubert }
32551de50e9fSSam Leffler
32563340d773SGleb Smirnoff /*
32573340d773SGleb Smirnoff * If we don't have the entire radiotap header, just give up.
32583340d773SGleb Smirnoff */
32591de50e9fSSam Leffler if (caplen < len) {
3260ee67461eSJoseph Mingrone nd_print_trunc(ndo);
32611de50e9fSSam Leffler return caplen;
32621de50e9fSSam Leffler }
3263ee67461eSJoseph Mingrone nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
3264ee67461eSJoseph Mingrone nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
32651de50e9fSSam Leffler for (last_presentp = &hdr->it_present;
32663340d773SGleb Smirnoff (const u_char*)(last_presentp + 1) <= p + len &&
32673340d773SGleb Smirnoff IS_EXTENDED(last_presentp);
32683c602fabSXin LI last_presentp++)
3269ee67461eSJoseph Mingrone nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
32701de50e9fSSam Leffler
32711de50e9fSSam Leffler /* are there more bitmap extensions than bytes in header? */
32723340d773SGleb Smirnoff if ((const u_char*)(last_presentp + 1) > p + len) {
3273ee67461eSJoseph Mingrone nd_print_trunc(ndo);
32741de50e9fSSam Leffler return caplen;
32751de50e9fSSam Leffler }
32761de50e9fSSam Leffler
32773340d773SGleb Smirnoff /*
32783340d773SGleb Smirnoff * Start out at the beginning of the default radiotap namespace.
32793340d773SGleb Smirnoff */
32803340d773SGleb Smirnoff bit0 = 0;
32813340d773SGleb Smirnoff vendor_namespace = 0;
32823340d773SGleb Smirnoff memset(vendor_oui, 0, 3);
32833340d773SGleb Smirnoff vendor_subnamespace = 0;
32843340d773SGleb Smirnoff skip_length = 0;
328527df3f5dSRui Paulo /* Assume no flags */
328627df3f5dSRui Paulo flags = 0;
3287abf25193SMax Laier /* Assume no Atheros padding between 802.11 header and body */
3288abf25193SMax Laier pad = 0;
328927df3f5dSRui Paulo /* Assume no FCS at end of frame */
329027df3f5dSRui Paulo fcslen = 0;
32913340d773SGleb Smirnoff for (presentp = &hdr->it_present; presentp <= last_presentp;
32923340d773SGleb Smirnoff presentp++) {
3293ee67461eSJoseph Mingrone presentflags = GET_LE_U_4(presentp);
3294cac3dcd5SXin LI
32953340d773SGleb Smirnoff /*
32963340d773SGleb Smirnoff * If this is a vendor namespace, we don't handle it.
32973340d773SGleb Smirnoff */
32983340d773SGleb Smirnoff if (vendor_namespace) {
32993340d773SGleb Smirnoff /*
33003340d773SGleb Smirnoff * Skip past the stuff we don't understand.
33013340d773SGleb Smirnoff * If we add support for any vendor namespaces,
33023340d773SGleb Smirnoff * it'd be added here; use vendor_oui and
33033340d773SGleb Smirnoff * vendor_subnamespace to interpret the fields.
33043340d773SGleb Smirnoff */
3305ee67461eSJoseph Mingrone if (nd_cpack_advance(&cpacker, skip_length) != 0) {
33063340d773SGleb Smirnoff /*
33073340d773SGleb Smirnoff * Ran out of space in the packet.
33083340d773SGleb Smirnoff */
33093340d773SGleb Smirnoff break;
33103340d773SGleb Smirnoff }
3311cac3dcd5SXin LI
33123340d773SGleb Smirnoff /*
33133340d773SGleb Smirnoff * We've skipped it all; nothing more to
33143340d773SGleb Smirnoff * skip.
33153340d773SGleb Smirnoff */
33163340d773SGleb Smirnoff skip_length = 0;
33173340d773SGleb Smirnoff } else {
33183340d773SGleb Smirnoff if (print_in_radiotap_namespace(ndo, &cpacker,
33193340d773SGleb Smirnoff &flags, presentflags, bit0) != 0) {
33203340d773SGleb Smirnoff /*
33213340d773SGleb Smirnoff * Fatal error - can't process anything
33223340d773SGleb Smirnoff * more in the radiotap header.
33233340d773SGleb Smirnoff */
33243340d773SGleb Smirnoff break;
33251de50e9fSSam Leffler }
33261de50e9fSSam Leffler }
332727df3f5dSRui Paulo
33283340d773SGleb Smirnoff /*
33293340d773SGleb Smirnoff * Handle the namespace switch bits; we've already handled
33303340d773SGleb Smirnoff * the extension bit in all but the last word above.
33313340d773SGleb Smirnoff */
33323340d773SGleb Smirnoff switch (presentflags &
33333340d773SGleb Smirnoff (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
33343340d773SGleb Smirnoff
33353340d773SGleb Smirnoff case 0:
33363340d773SGleb Smirnoff /*
33373340d773SGleb Smirnoff * We're not changing namespaces.
33383340d773SGleb Smirnoff * advance to the next 32 bits in the current
33393340d773SGleb Smirnoff * namespace.
33403340d773SGleb Smirnoff */
33413340d773SGleb Smirnoff bit0 += 32;
33423340d773SGleb Smirnoff break;
33433340d773SGleb Smirnoff
33443340d773SGleb Smirnoff case BIT(IEEE80211_RADIOTAP_NAMESPACE):
33453340d773SGleb Smirnoff /*
33463340d773SGleb Smirnoff * We're switching to the radiotap namespace.
33473340d773SGleb Smirnoff * Reset the presence-bitmap index to 0, and
33483340d773SGleb Smirnoff * reset the namespace to the default radiotap
33493340d773SGleb Smirnoff * namespace.
33503340d773SGleb Smirnoff */
33513340d773SGleb Smirnoff bit0 = 0;
33523340d773SGleb Smirnoff vendor_namespace = 0;
33533340d773SGleb Smirnoff memset(vendor_oui, 0, 3);
33543340d773SGleb Smirnoff vendor_subnamespace = 0;
33553340d773SGleb Smirnoff skip_length = 0;
33563340d773SGleb Smirnoff break;
33573340d773SGleb Smirnoff
33583340d773SGleb Smirnoff case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
33593340d773SGleb Smirnoff /*
33603340d773SGleb Smirnoff * We're switching to a vendor namespace.
33613340d773SGleb Smirnoff * Reset the presence-bitmap index to 0,
33623340d773SGleb Smirnoff * note that we're in a vendor namespace,
33633340d773SGleb Smirnoff * and fetch the fields of the Vendor Namespace
33643340d773SGleb Smirnoff * item.
33653340d773SGleb Smirnoff */
33663340d773SGleb Smirnoff bit0 = 0;
33673340d773SGleb Smirnoff vendor_namespace = 1;
3368ee67461eSJoseph Mingrone if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
3369ee67461eSJoseph Mingrone nd_print_trunc(ndo);
33703340d773SGleb Smirnoff break;
33713340d773SGleb Smirnoff }
3372ee67461eSJoseph Mingrone if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
3373ee67461eSJoseph Mingrone nd_print_trunc(ndo);
33743340d773SGleb Smirnoff break;
33753340d773SGleb Smirnoff }
3376ee67461eSJoseph Mingrone if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
3377ee67461eSJoseph Mingrone nd_print_trunc(ndo);
33783340d773SGleb Smirnoff break;
33793340d773SGleb Smirnoff }
3380ee67461eSJoseph Mingrone if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
3381ee67461eSJoseph Mingrone nd_print_trunc(ndo);
33823340d773SGleb Smirnoff break;
33833340d773SGleb Smirnoff }
3384ee67461eSJoseph Mingrone if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
3385ee67461eSJoseph Mingrone nd_print_trunc(ndo);
33863340d773SGleb Smirnoff break;
33873340d773SGleb Smirnoff }
3388ee67461eSJoseph Mingrone if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
3389ee67461eSJoseph Mingrone nd_print_trunc(ndo);
33903340d773SGleb Smirnoff break;
33913340d773SGleb Smirnoff }
33923340d773SGleb Smirnoff break;
33933340d773SGleb Smirnoff
33943340d773SGleb Smirnoff default:
33953340d773SGleb Smirnoff /*
33963340d773SGleb Smirnoff * Illegal combination. The behavior in this
33973340d773SGleb Smirnoff * case is undefined by the radiotap spec; we
33983340d773SGleb Smirnoff * just ignore both bits.
33993340d773SGleb Smirnoff */
34003340d773SGleb Smirnoff break;
34013340d773SGleb Smirnoff }
34023340d773SGleb Smirnoff }
34033340d773SGleb Smirnoff
340427df3f5dSRui Paulo if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
340527df3f5dSRui Paulo pad = 1; /* Atheros padding */
340627df3f5dSRui Paulo if (flags & IEEE80211_RADIOTAP_F_FCS)
340727df3f5dSRui Paulo fcslen = 4; /* FCS at end of packet */
34083c602fabSXin LI return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
340927df3f5dSRui Paulo fcslen);
34101de50e9fSSam Leffler #undef BITNO_32
34111de50e9fSSam Leffler #undef BITNO_16
34121de50e9fSSam Leffler #undef BITNO_8
34131de50e9fSSam Leffler #undef BITNO_4
34141de50e9fSSam Leffler #undef BITNO_2
34151de50e9fSSam Leffler #undef BIT
34161de50e9fSSam Leffler }
34171de50e9fSSam Leffler
34181de50e9fSSam Leffler static u_int
ieee802_11_radio_avs_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3419ee67461eSJoseph Mingrone ieee802_11_radio_avs_print(netdissect_options *ndo,
34203c602fabSXin LI const u_char *p, u_int length, u_int caplen)
34211de50e9fSSam Leffler {
34223c602fabSXin LI uint32_t caphdr_len;
34235b0fe478SBruce M Simpson
3424ee67461eSJoseph Mingrone ndo->ndo_protocol = "802.11_radio_avs";
3425a5779b6eSRui Paulo if (caplen < 8) {
3426ee67461eSJoseph Mingrone nd_print_trunc(ndo);
3427a5779b6eSRui Paulo return caplen;
3428a5779b6eSRui Paulo }
3429a5779b6eSRui Paulo
3430ee67461eSJoseph Mingrone caphdr_len = GET_BE_U_4(p + 4);
34315b0fe478SBruce M Simpson if (caphdr_len < 8) {
34325b0fe478SBruce M Simpson /*
34335b0fe478SBruce M Simpson * Yow! The capture header length is claimed not
34345b0fe478SBruce M Simpson * to be large enough to include even the version
34355b0fe478SBruce M Simpson * cookie or capture header length!
34365b0fe478SBruce M Simpson */
3437ee67461eSJoseph Mingrone nd_print_trunc(ndo);
34385b0fe478SBruce M Simpson return caplen;
34395b0fe478SBruce M Simpson }
34405b0fe478SBruce M Simpson
34415b0fe478SBruce M Simpson if (caplen < caphdr_len) {
3442ee67461eSJoseph Mingrone nd_print_trunc(ndo);
34435b0fe478SBruce M Simpson return caplen;
34445b0fe478SBruce M Simpson }
34455b0fe478SBruce M Simpson
34463c602fabSXin LI return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
344727df3f5dSRui Paulo length - caphdr_len, caplen - caphdr_len, 0, 0);
34485b0fe478SBruce M Simpson }
34495b0fe478SBruce M Simpson
34505b0fe478SBruce M Simpson #define PRISM_HDR_LEN 144
34515b0fe478SBruce M Simpson
3452a5779b6eSRui Paulo #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
34535b0fe478SBruce M Simpson #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
3454a5779b6eSRui Paulo #define WLANCAP_MAGIC_COOKIE_V2 0x80211002
34555b0fe478SBruce M Simpson
34565b0fe478SBruce M Simpson /*
34575b0fe478SBruce M Simpson * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
34585b0fe478SBruce M Simpson * containing information such as radio information, which we
34595b0fe478SBruce M Simpson * currently ignore.
34605b0fe478SBruce M Simpson *
3461a5779b6eSRui Paulo * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
3462a5779b6eSRui Paulo * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
3463a5779b6eSRui Paulo * (currently, on Linux, there's no ARPHRD_ type for
3464a5779b6eSRui Paulo * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
3465a5779b6eSRui Paulo * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
3466a5779b6eSRui Paulo * the AVS header, and the first 4 bytes of the header are used to
3467a5779b6eSRui Paulo * indicate whether it's a Prism header or an AVS header).
34685b0fe478SBruce M Simpson */
3469ee67461eSJoseph Mingrone void
prism_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)34703c602fabSXin LI prism_if_print(netdissect_options *ndo,
34713c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p)
34725b0fe478SBruce M Simpson {
34735b0fe478SBruce M Simpson u_int caplen = h->caplen;
34745b0fe478SBruce M Simpson u_int length = h->len;
34753c602fabSXin LI uint32_t msgcode;
34765b0fe478SBruce M Simpson
3477ee67461eSJoseph Mingrone ndo->ndo_protocol = "prism";
34785b0fe478SBruce M Simpson if (caplen < 4) {
3479ee67461eSJoseph Mingrone nd_print_trunc(ndo);
3480ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
3481ee67461eSJoseph Mingrone return;
34825b0fe478SBruce M Simpson }
34835b0fe478SBruce M Simpson
3484ee67461eSJoseph Mingrone msgcode = GET_BE_U_4(p);
3485a5779b6eSRui Paulo if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
3486ee67461eSJoseph Mingrone msgcode == WLANCAP_MAGIC_COOKIE_V2) {
3487ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
3488ee67461eSJoseph Mingrone return;
3489ee67461eSJoseph Mingrone }
34905b0fe478SBruce M Simpson
34915b0fe478SBruce M Simpson if (caplen < PRISM_HDR_LEN) {
3492ee67461eSJoseph Mingrone nd_print_trunc(ndo);
3493ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen;
3494ee67461eSJoseph Mingrone return;
34955b0fe478SBruce M Simpson }
34965b0fe478SBruce M Simpson
3497ee67461eSJoseph Mingrone p += PRISM_HDR_LEN;
3498ee67461eSJoseph Mingrone length -= PRISM_HDR_LEN;
3499ee67461eSJoseph Mingrone caplen -= PRISM_HDR_LEN;
3500ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
3501ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
35025b0fe478SBruce M Simpson }
35035b0fe478SBruce M Simpson
35045b0fe478SBruce M Simpson /*
35055b0fe478SBruce M Simpson * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
3506a5779b6eSRui Paulo * header, containing information such as radio information.
35075b0fe478SBruce M Simpson */
3508ee67461eSJoseph Mingrone void
ieee802_11_radio_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)35093c602fabSXin LI ieee802_11_radio_if_print(netdissect_options *ndo,
35103c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p)
35115b0fe478SBruce M Simpson {
3512ee67461eSJoseph Mingrone ndo->ndo_protocol = "802.11_radio";
3513ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
35145b0fe478SBruce M Simpson }
35155b0fe478SBruce M Simpson
3516a5779b6eSRui Paulo /*
3517a5779b6eSRui Paulo * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
3518a5779b6eSRui Paulo * extra header, containing information such as radio information,
3519a5779b6eSRui Paulo * which we currently ignore.
3520a5779b6eSRui Paulo */
3521ee67461eSJoseph Mingrone void
ieee802_11_radio_avs_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)35223c602fabSXin LI ieee802_11_radio_avs_if_print(netdissect_options *ndo,
35233c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p)
3524a5779b6eSRui Paulo {
3525ee67461eSJoseph Mingrone ndo->ndo_protocol = "802.11_radio_avs";
3526ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
3527a90e161bSBill Fenner }
3528