xref: /dflybsd-src/contrib/tcpdump/print-802_11.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (c) 2001
341c99275SPeter Avalos  *	Fortress Technologies, Inc.  All rights reserved.
441c99275SPeter Avalos  *      Charlie Lenahan (clenahan@fortresstech.com)
541c99275SPeter Avalos  *
641c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
741c99275SPeter Avalos  * modification, are permitted provided that: (1) source code distributions
841c99275SPeter Avalos  * retain the above copyright notice and this paragraph in its entirety, (2)
941c99275SPeter Avalos  * distributions including binary code include the above copyright notice and
1041c99275SPeter Avalos  * this paragraph in its entirety in the documentation or other materials
1141c99275SPeter Avalos  * provided with the distribution, and (3) all advertising materials mentioning
1241c99275SPeter Avalos  * features or use of this software display the following acknowledgement:
1341c99275SPeter Avalos  * ``This product includes software developed by the University of California,
1441c99275SPeter Avalos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1541c99275SPeter Avalos  * the University nor the names of its contributors may be used to endorse
1641c99275SPeter Avalos  * or promote products derived from this software without specific prior
1741c99275SPeter Avalos  * written permission.
1841c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1941c99275SPeter Avalos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
2041c99275SPeter Avalos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2141c99275SPeter Avalos  */
2241c99275SPeter Avalos 
23411677aeSAaron LI /* \summary: IEEE 802.11 printer */
2441c99275SPeter Avalos 
2541c99275SPeter Avalos #ifdef HAVE_CONFIG_H
26*ed775ee7SAntonio Huete Jimenez #include <config.h>
2741c99275SPeter Avalos #endif
2841c99275SPeter Avalos 
29*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3041c99275SPeter Avalos 
3141c99275SPeter Avalos #include <string.h>
3241c99275SPeter Avalos 
33411677aeSAaron LI #include "netdissect.h"
3441c99275SPeter Avalos #include "addrtoname.h"
3541c99275SPeter Avalos 
3641c99275SPeter Avalos #include "extract.h"
3741c99275SPeter Avalos 
3841c99275SPeter Avalos #include "cpack.h"
3941c99275SPeter Avalos 
4041c99275SPeter Avalos 
41411677aeSAaron LI /* Lengths of 802.11 header components. */
42411677aeSAaron LI #define	IEEE802_11_FC_LEN		2
43411677aeSAaron LI #define	IEEE802_11_DUR_LEN		2
44411677aeSAaron LI #define	IEEE802_11_DA_LEN		6
45411677aeSAaron LI #define	IEEE802_11_SA_LEN		6
46411677aeSAaron LI #define	IEEE802_11_BSSID_LEN		6
47411677aeSAaron LI #define	IEEE802_11_RA_LEN		6
48411677aeSAaron LI #define	IEEE802_11_TA_LEN		6
49411677aeSAaron LI #define	IEEE802_11_ADDR1_LEN		6
50411677aeSAaron LI #define	IEEE802_11_SEQ_LEN		2
51411677aeSAaron LI #define	IEEE802_11_CTL_LEN		2
52411677aeSAaron LI #define	IEEE802_11_CARRIED_FC_LEN	2
53411677aeSAaron LI #define	IEEE802_11_HT_CONTROL_LEN	4
54411677aeSAaron LI #define	IEEE802_11_IV_LEN		3
55411677aeSAaron LI #define	IEEE802_11_KID_LEN		1
5627bfbee1SPeter Avalos 
57411677aeSAaron LI /* Frame check sequence length. */
58411677aeSAaron LI #define	IEEE802_11_FCS_LEN		4
59411677aeSAaron LI 
60411677aeSAaron LI /* Lengths of beacon components. */
61411677aeSAaron LI #define	IEEE802_11_TSTAMP_LEN		8
62411677aeSAaron LI #define	IEEE802_11_BCNINT_LEN		2
63411677aeSAaron LI #define	IEEE802_11_CAPINFO_LEN		2
64411677aeSAaron LI #define	IEEE802_11_LISTENINT_LEN	2
65411677aeSAaron LI 
66411677aeSAaron LI #define	IEEE802_11_AID_LEN		2
67411677aeSAaron LI #define	IEEE802_11_STATUS_LEN		2
68411677aeSAaron LI #define	IEEE802_11_REASON_LEN		2
69411677aeSAaron LI 
70411677aeSAaron LI /* Length of previous AP in reassocation frame */
71411677aeSAaron LI #define	IEEE802_11_AP_LEN		6
72411677aeSAaron LI 
73411677aeSAaron LI #define	T_MGMT 0x0  /* management */
74411677aeSAaron LI #define	T_CTRL 0x1  /* control */
75411677aeSAaron LI #define	T_DATA 0x2 /* data */
76411677aeSAaron LI #define	T_RESV 0x3  /* reserved */
77411677aeSAaron LI 
78411677aeSAaron LI #define	ST_ASSOC_REQUEST	0x0
79411677aeSAaron LI #define	ST_ASSOC_RESPONSE	0x1
80411677aeSAaron LI #define	ST_REASSOC_REQUEST	0x2
81411677aeSAaron LI #define	ST_REASSOC_RESPONSE	0x3
82411677aeSAaron LI #define	ST_PROBE_REQUEST	0x4
83411677aeSAaron LI #define	ST_PROBE_RESPONSE	0x5
84411677aeSAaron LI /* RESERVED			0x6  */
85411677aeSAaron LI /* RESERVED			0x7  */
86411677aeSAaron LI #define	ST_BEACON		0x8
87411677aeSAaron LI #define	ST_ATIM			0x9
88411677aeSAaron LI #define	ST_DISASSOC		0xA
89411677aeSAaron LI #define	ST_AUTH			0xB
90411677aeSAaron LI #define	ST_DEAUTH		0xC
91411677aeSAaron LI #define	ST_ACTION		0xD
92411677aeSAaron LI /* RESERVED			0xE  */
93411677aeSAaron LI /* RESERVED			0xF  */
94411677aeSAaron LI 
95411677aeSAaron LI static const struct tok st_str[] = {
96411677aeSAaron LI 	{ ST_ASSOC_REQUEST,    "Assoc Request"    },
97411677aeSAaron LI 	{ ST_ASSOC_RESPONSE,   "Assoc Response"   },
98411677aeSAaron LI 	{ ST_REASSOC_REQUEST,  "ReAssoc Request"  },
99411677aeSAaron LI 	{ ST_REASSOC_RESPONSE, "ReAssoc Response" },
100411677aeSAaron LI 	{ ST_PROBE_REQUEST,    "Probe Request"    },
101411677aeSAaron LI 	{ ST_PROBE_RESPONSE,   "Probe Response"   },
102411677aeSAaron LI 	{ ST_BEACON,           "Beacon"           },
103411677aeSAaron LI 	{ ST_ATIM,             "ATIM"             },
104411677aeSAaron LI 	{ ST_DISASSOC,         "Disassociation"   },
105411677aeSAaron LI 	{ ST_AUTH,             "Authentication"   },
106411677aeSAaron LI 	{ ST_DEAUTH,           "DeAuthentication" },
107411677aeSAaron LI 	{ ST_ACTION,           "Action"           },
108411677aeSAaron LI 	{ 0, NULL }
10927bfbee1SPeter Avalos };
11027bfbee1SPeter Avalos 
111411677aeSAaron LI #define CTRL_CONTROL_WRAPPER	0x7
112411677aeSAaron LI #define	CTRL_BAR	0x8
113411677aeSAaron LI #define	CTRL_BA		0x9
114411677aeSAaron LI #define	CTRL_PS_POLL	0xA
115411677aeSAaron LI #define	CTRL_RTS	0xB
116411677aeSAaron LI #define	CTRL_CTS	0xC
117411677aeSAaron LI #define	CTRL_ACK	0xD
118411677aeSAaron LI #define	CTRL_CF_END	0xE
119411677aeSAaron LI #define	CTRL_END_ACK	0xF
120411677aeSAaron LI 
121411677aeSAaron LI static const struct tok ctrl_str[] = {
122411677aeSAaron LI 	{ CTRL_CONTROL_WRAPPER, "Control Wrapper" },
123411677aeSAaron LI 	{ CTRL_BAR,             "BAR"             },
124411677aeSAaron LI 	{ CTRL_BA,              "BA"              },
125411677aeSAaron LI 	{ CTRL_PS_POLL,         "Power Save-Poll" },
126411677aeSAaron LI 	{ CTRL_RTS,             "Request-To-Send" },
127411677aeSAaron LI 	{ CTRL_CTS,             "Clear-To-Send"   },
128411677aeSAaron LI 	{ CTRL_ACK,             "Acknowledgment"  },
129411677aeSAaron LI 	{ CTRL_CF_END,          "CF-End"          },
130411677aeSAaron LI 	{ CTRL_END_ACK,         "CF-End+CF-Ack"   },
131411677aeSAaron LI 	{ 0, NULL }
132411677aeSAaron LI };
133411677aeSAaron LI 
134411677aeSAaron LI #define	DATA_DATA			0x0
135411677aeSAaron LI #define	DATA_DATA_CF_ACK		0x1
136411677aeSAaron LI #define	DATA_DATA_CF_POLL		0x2
137411677aeSAaron LI #define	DATA_DATA_CF_ACK_POLL		0x3
138411677aeSAaron LI #define	DATA_NODATA			0x4
139411677aeSAaron LI #define	DATA_NODATA_CF_ACK		0x5
140411677aeSAaron LI #define	DATA_NODATA_CF_POLL		0x6
141411677aeSAaron LI #define	DATA_NODATA_CF_ACK_POLL		0x7
142411677aeSAaron LI 
143411677aeSAaron LI #define DATA_QOS_DATA			0x8
144411677aeSAaron LI #define DATA_QOS_DATA_CF_ACK		0x9
145411677aeSAaron LI #define DATA_QOS_DATA_CF_POLL		0xA
146411677aeSAaron LI #define DATA_QOS_DATA_CF_ACK_POLL	0xB
147411677aeSAaron LI #define DATA_QOS_NODATA			0xC
148411677aeSAaron LI #define DATA_QOS_CF_POLL_NODATA		0xE
149411677aeSAaron LI #define DATA_QOS_CF_ACK_POLL_NODATA	0xF
150411677aeSAaron LI 
151411677aeSAaron LI /*
152411677aeSAaron LI  * The subtype field of a data frame is, in effect, composed of 4 flag
153411677aeSAaron LI  * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
154411677aeSAaron LI  * any data), and QoS.
155411677aeSAaron LI  */
156411677aeSAaron LI #define DATA_FRAME_IS_CF_ACK(x)		((x) & 0x01)
157411677aeSAaron LI #define DATA_FRAME_IS_CF_POLL(x)	((x) & 0x02)
158411677aeSAaron LI #define DATA_FRAME_IS_NULL(x)		((x) & 0x04)
159411677aeSAaron LI #define DATA_FRAME_IS_QOS(x)		((x) & 0x08)
160411677aeSAaron LI 
161411677aeSAaron LI /*
162411677aeSAaron LI  * Bits in the frame control field.
163411677aeSAaron LI  */
164411677aeSAaron LI #define	FC_VERSION(fc)		((fc) & 0x3)
165411677aeSAaron LI #define	FC_TYPE(fc)		(((fc) >> 2) & 0x3)
166411677aeSAaron LI #define	FC_SUBTYPE(fc)		(((fc) >> 4) & 0xF)
167411677aeSAaron LI #define	FC_TO_DS(fc)		((fc) & 0x0100)
168411677aeSAaron LI #define	FC_FROM_DS(fc)		((fc) & 0x0200)
169411677aeSAaron LI #define	FC_MORE_FLAG(fc)	((fc) & 0x0400)
170411677aeSAaron LI #define	FC_RETRY(fc)		((fc) & 0x0800)
171411677aeSAaron LI #define	FC_POWER_MGMT(fc)	((fc) & 0x1000)
172411677aeSAaron LI #define	FC_MORE_DATA(fc)	((fc) & 0x2000)
173411677aeSAaron LI #define	FC_PROTECTED(fc)	((fc) & 0x4000)
174411677aeSAaron LI #define	FC_ORDER(fc)		((fc) & 0x8000)
175411677aeSAaron LI 
176411677aeSAaron LI struct mgmt_header_t {
177*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
178*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
179*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	da;
180*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	sa;
181*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	bssid;
182*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	seq_ctrl;
183411677aeSAaron LI };
184411677aeSAaron LI 
185411677aeSAaron LI #define	MGMT_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
186411677aeSAaron LI 			 IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\
187411677aeSAaron LI 			 IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN)
188411677aeSAaron LI 
189411677aeSAaron LI #define	CAPABILITY_ESS(cap)	((cap) & 0x0001)
190411677aeSAaron LI #define	CAPABILITY_IBSS(cap)	((cap) & 0x0002)
191411677aeSAaron LI #define	CAPABILITY_CFP(cap)	((cap) & 0x0004)
192411677aeSAaron LI #define	CAPABILITY_CFP_REQ(cap)	((cap) & 0x0008)
193411677aeSAaron LI #define	CAPABILITY_PRIVACY(cap)	((cap) & 0x0010)
194411677aeSAaron LI 
195411677aeSAaron LI struct ssid_t {
196411677aeSAaron LI 	uint8_t		element_id;
197411677aeSAaron LI 	uint8_t		length;
198411677aeSAaron LI 	u_char		ssid[33];  /* 32 + 1 for null */
199411677aeSAaron LI };
200411677aeSAaron LI 
201411677aeSAaron LI struct rates_t {
202411677aeSAaron LI 	uint8_t		element_id;
203411677aeSAaron LI 	uint8_t		length;
204411677aeSAaron LI 	uint8_t		rate[16];
205411677aeSAaron LI };
206411677aeSAaron LI 
207411677aeSAaron LI struct challenge_t {
208411677aeSAaron LI 	uint8_t		element_id;
209411677aeSAaron LI 	uint8_t		length;
210411677aeSAaron LI 	uint8_t		text[254]; /* 1-253 + 1 for null */
211411677aeSAaron LI };
212411677aeSAaron LI 
213411677aeSAaron LI struct fh_t {
214411677aeSAaron LI 	uint8_t		element_id;
215411677aeSAaron LI 	uint8_t		length;
216411677aeSAaron LI 	uint16_t	dwell_time;
217411677aeSAaron LI 	uint8_t		hop_set;
218411677aeSAaron LI 	uint8_t	hop_pattern;
219411677aeSAaron LI 	uint8_t		hop_index;
220411677aeSAaron LI };
221411677aeSAaron LI 
222411677aeSAaron LI struct ds_t {
223411677aeSAaron LI 	uint8_t		element_id;
224411677aeSAaron LI 	uint8_t		length;
225411677aeSAaron LI 	uint8_t		channel;
226411677aeSAaron LI };
227411677aeSAaron LI 
228411677aeSAaron LI struct cf_t {
229411677aeSAaron LI 	uint8_t		element_id;
230411677aeSAaron LI 	uint8_t		length;
231411677aeSAaron LI 	uint8_t		count;
232411677aeSAaron LI 	uint8_t		period;
233411677aeSAaron LI 	uint16_t	max_duration;
234*ed775ee7SAntonio Huete Jimenez 	uint16_t	dur_remaining;
235411677aeSAaron LI };
236411677aeSAaron LI 
237411677aeSAaron LI struct tim_t {
238411677aeSAaron LI 	uint8_t		element_id;
239411677aeSAaron LI 	uint8_t		length;
240411677aeSAaron LI 	uint8_t		count;
241411677aeSAaron LI 	uint8_t		period;
242411677aeSAaron LI 	uint8_t		bitmap_control;
243411677aeSAaron LI 	uint8_t		bitmap[251];
244411677aeSAaron LI };
245411677aeSAaron LI 
246411677aeSAaron LI #define	E_SSID		0
247411677aeSAaron LI #define	E_RATES	1
248411677aeSAaron LI #define	E_FH		2
249411677aeSAaron LI #define	E_DS		3
250411677aeSAaron LI #define	E_CF		4
251411677aeSAaron LI #define	E_TIM		5
252411677aeSAaron LI #define	E_IBSS		6
253411677aeSAaron LI /* reserved		7 */
254411677aeSAaron LI /* reserved		8 */
255411677aeSAaron LI /* reserved		9 */
256411677aeSAaron LI /* reserved		10 */
257411677aeSAaron LI /* reserved		11 */
258411677aeSAaron LI /* reserved		12 */
259411677aeSAaron LI /* reserved		13 */
260411677aeSAaron LI /* reserved		14 */
261411677aeSAaron LI /* reserved		15 */
262411677aeSAaron LI /* reserved		16 */
263411677aeSAaron LI 
264411677aeSAaron LI #define	E_CHALLENGE	16
265411677aeSAaron LI /* reserved		17 */
266411677aeSAaron LI /* reserved		18 */
267411677aeSAaron LI /* reserved		19 */
268411677aeSAaron LI /* reserved		16 */
269411677aeSAaron LI /* reserved		16 */
270411677aeSAaron LI 
271411677aeSAaron LI 
272411677aeSAaron LI struct mgmt_body_t {
273411677aeSAaron LI 	uint8_t		timestamp[IEEE802_11_TSTAMP_LEN];
274411677aeSAaron LI 	uint16_t	beacon_interval;
275411677aeSAaron LI 	uint16_t	listen_interval;
276411677aeSAaron LI 	uint16_t	status_code;
277411677aeSAaron LI 	uint16_t	aid;
278411677aeSAaron LI 	u_char		ap[IEEE802_11_AP_LEN];
279411677aeSAaron LI 	uint16_t	reason_code;
280411677aeSAaron LI 	uint16_t	auth_alg;
281411677aeSAaron LI 	uint16_t	auth_trans_seq_num;
282411677aeSAaron LI 	int		challenge_present;
283411677aeSAaron LI 	struct challenge_t  challenge;
284411677aeSAaron LI 	uint16_t	capability_info;
285411677aeSAaron LI 	int		ssid_present;
286411677aeSAaron LI 	struct ssid_t	ssid;
287411677aeSAaron LI 	int		rates_present;
288411677aeSAaron LI 	struct rates_t	rates;
289411677aeSAaron LI 	int		ds_present;
290411677aeSAaron LI 	struct ds_t	ds;
291411677aeSAaron LI 	int		cf_present;
292411677aeSAaron LI 	struct cf_t	cf;
293411677aeSAaron LI 	int		fh_present;
294411677aeSAaron LI 	struct fh_t	fh;
295411677aeSAaron LI 	int		tim_present;
296411677aeSAaron LI 	struct tim_t	tim;
297411677aeSAaron LI };
298411677aeSAaron LI 
299411677aeSAaron LI struct ctrl_control_wrapper_hdr_t {
300*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
301*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
302*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	addr1;
303*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	carried_fc[IEEE802_11_CARRIED_FC_LEN];
304*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	ht_control[IEEE802_11_HT_CONTROL_LEN];
305411677aeSAaron LI };
306411677aeSAaron LI 
307411677aeSAaron LI #define	CTRL_CONTROL_WRAPPER_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
308411677aeSAaron LI 					 IEEE802_11_ADDR1_LEN+\
309411677aeSAaron LI 					 IEEE802_11_CARRIED_FC_LEN+\
310411677aeSAaron LI 					 IEEE802_11_HT_CONTROL_LEN)
311411677aeSAaron LI 
312411677aeSAaron LI struct ctrl_rts_hdr_t {
313*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
314*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
315*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
316*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ta;
317411677aeSAaron LI };
318411677aeSAaron LI 
319411677aeSAaron LI #define	CTRL_RTS_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
320411677aeSAaron LI 			 IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
321411677aeSAaron LI 
322411677aeSAaron LI struct ctrl_cts_hdr_t {
323*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
324*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
325*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
326411677aeSAaron LI };
327411677aeSAaron LI 
328411677aeSAaron LI #define	CTRL_CTS_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
329411677aeSAaron LI 
330411677aeSAaron LI struct ctrl_ack_hdr_t {
331*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
332*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
333*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
334411677aeSAaron LI };
335411677aeSAaron LI 
336411677aeSAaron LI #define	CTRL_ACK_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
337411677aeSAaron LI 
338411677aeSAaron LI struct ctrl_ps_poll_hdr_t {
339*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
340*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	aid;
341*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	bssid;
342*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ta;
343411677aeSAaron LI };
344411677aeSAaron LI 
345411677aeSAaron LI #define	CTRL_PS_POLL_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
346411677aeSAaron LI 				 IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN)
347411677aeSAaron LI 
348411677aeSAaron LI struct ctrl_end_hdr_t {
349*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
350*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
351*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
352*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	bssid;
353411677aeSAaron LI };
354411677aeSAaron LI 
355411677aeSAaron LI #define	CTRL_END_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
356411677aeSAaron LI 			 IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
357411677aeSAaron LI 
358411677aeSAaron LI struct ctrl_end_ack_hdr_t {
359*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
360*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
361*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
362*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	bssid;
363411677aeSAaron LI };
364411677aeSAaron LI 
365411677aeSAaron LI #define	CTRL_END_ACK_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
366411677aeSAaron LI 				 IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
367411677aeSAaron LI 
368411677aeSAaron LI struct ctrl_ba_hdr_t {
369*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
370*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	duration;
371*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
372411677aeSAaron LI };
373411677aeSAaron LI 
374411677aeSAaron LI #define	CTRL_BA_HDRLEN	(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
375411677aeSAaron LI 
376411677aeSAaron LI struct ctrl_bar_hdr_t {
377*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	fc;
378*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	dur;
379*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ra;
380*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	ta;
381*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	ctl;
382*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	seq;
383411677aeSAaron LI };
384411677aeSAaron LI 
385411677aeSAaron LI #define	CTRL_BAR_HDRLEN		(IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
386411677aeSAaron LI 				 IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\
387411677aeSAaron LI 				 IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN)
388411677aeSAaron LI 
389411677aeSAaron LI struct meshcntl_t {
390*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	flags;
391*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	ttl;
392*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	seq;
393*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	addr4;
394*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	addr5;
395*ed775ee7SAntonio Huete Jimenez 	nd_mac_addr	addr6;
396411677aeSAaron LI };
397411677aeSAaron LI 
398411677aeSAaron LI #define	IV_IV(iv)	((iv) & 0xFFFFFF)
399411677aeSAaron LI #define	IV_PAD(iv)	(((iv) >> 24) & 0x3F)
400411677aeSAaron LI #define	IV_KEYID(iv)	(((iv) >> 30) & 0x03)
401411677aeSAaron LI 
40241c99275SPeter Avalos #define PRINT_SSID(p) \
40327bfbee1SPeter Avalos 	if (p.ssid_present) { \
404*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ("); \
405*ed775ee7SAntonio Huete Jimenez 		fn_print_str(ndo, p.ssid.ssid); \
406*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(")"); \
40741c99275SPeter Avalos 	}
40841c99275SPeter Avalos 
40941c99275SPeter Avalos #define PRINT_RATE(_sep, _r, _suf) \
410*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
41141c99275SPeter Avalos #define PRINT_RATES(p) \
41227bfbee1SPeter Avalos 	if (p.rates_present) { \
41341c99275SPeter Avalos 		int z; \
41441c99275SPeter Avalos 		const char *sep = " ["; \
41541c99275SPeter Avalos 		for (z = 0; z < p.rates.length ; z++) { \
41641c99275SPeter Avalos 			PRINT_RATE(sep, p.rates.rate[z], \
41741c99275SPeter Avalos 				(p.rates.rate[z] & 0x80 ? "*" : "")); \
41841c99275SPeter Avalos 			sep = " "; \
41941c99275SPeter Avalos 		} \
42041c99275SPeter Avalos 		if (p.rates.length != 0) \
421*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" Mbit]"); \
42241c99275SPeter Avalos 	}
42341c99275SPeter Avalos 
42441c99275SPeter Avalos #define PRINT_DS_CHANNEL(p) \
42527bfbee1SPeter Avalos 	if (p.ds_present) \
426*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" CH: %u", p.ds.channel); \
427*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s", \
428*ed775ee7SAntonio Huete Jimenez 	    CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
42941c99275SPeter Avalos 
43027bfbee1SPeter Avalos #define MAX_MCS_INDEX	76
43127bfbee1SPeter Avalos 
43227bfbee1SPeter Avalos /*
43327bfbee1SPeter Avalos  * Indices are:
43427bfbee1SPeter Avalos  *
43527bfbee1SPeter Avalos  *	the MCS index (0-76);
43627bfbee1SPeter Avalos  *
43727bfbee1SPeter Avalos  *	0 for 20 MHz, 1 for 40 MHz;
43827bfbee1SPeter Avalos  *
43927bfbee1SPeter Avalos  *	0 for a long guard interval, 1 for a short guard interval.
44027bfbee1SPeter Avalos  */
44127bfbee1SPeter Avalos static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
44227bfbee1SPeter Avalos 	/* MCS  0  */
443*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {    6.5f,		/* SGI */    7.2f, },
444*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   13.5f,		/* SGI */   15.0f, },
44527bfbee1SPeter Avalos 	},
44627bfbee1SPeter Avalos 
44727bfbee1SPeter Avalos 	/* MCS  1  */
448*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   13.0f,		/* SGI */   14.4f, },
449*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   27.0f,		/* SGI */   30.0f, },
45027bfbee1SPeter Avalos 	},
45127bfbee1SPeter Avalos 
45227bfbee1SPeter Avalos 	/* MCS  2  */
453*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   19.5f,		/* SGI */   21.7f, },
454*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   40.5f,		/* SGI */   45.0f, },
45527bfbee1SPeter Avalos 	},
45627bfbee1SPeter Avalos 
45727bfbee1SPeter Avalos 	/* MCS  3  */
458*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   26.0f,		/* SGI */   28.9f, },
459*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   54.0f,		/* SGI */   60.0f, },
46027bfbee1SPeter Avalos 	},
46127bfbee1SPeter Avalos 
46227bfbee1SPeter Avalos 	/* MCS  4  */
463*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   39.0f,		/* SGI */   43.3f, },
464*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   81.0f,		/* SGI */   90.0f, },
46527bfbee1SPeter Avalos 	},
46627bfbee1SPeter Avalos 
46727bfbee1SPeter Avalos 	/* MCS  5  */
468*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   52.0f,		/* SGI */   57.8f, },
469*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  108.0f,		/* SGI */  120.0f, },
47027bfbee1SPeter Avalos 	},
47127bfbee1SPeter Avalos 
47227bfbee1SPeter Avalos 	/* MCS  6  */
473*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   58.5f,		/* SGI */   65.0f, },
474*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  121.5f,		/* SGI */  135.0f, },
47527bfbee1SPeter Avalos 	},
47627bfbee1SPeter Avalos 
47727bfbee1SPeter Avalos 	/* MCS  7  */
478*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   65.0f,		/* SGI */   72.2f, },
479*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   135.0f,	/* SGI */  150.0f, },
48027bfbee1SPeter Avalos 	},
48127bfbee1SPeter Avalos 
48227bfbee1SPeter Avalos 	/* MCS  8  */
483*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   13.0f,		/* SGI */   14.4f, },
484*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   27.0f,		/* SGI */   30.0f, },
48527bfbee1SPeter Avalos 	},
48627bfbee1SPeter Avalos 
48727bfbee1SPeter Avalos 	/* MCS  9  */
488*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   26.0f,		/* SGI */   28.9f, },
489*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   54.0f,		/* SGI */   60.0f, },
49027bfbee1SPeter Avalos 	},
49127bfbee1SPeter Avalos 
49227bfbee1SPeter Avalos 	/* MCS 10  */
493*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   39.0f,		/* SGI */   43.3f, },
494*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   81.0f,		/* SGI */   90.0f, },
49527bfbee1SPeter Avalos 	},
49627bfbee1SPeter Avalos 
49727bfbee1SPeter Avalos 	/* MCS 11  */
498*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   52.0f,		/* SGI */   57.8f, },
499*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  108.0f,		/* SGI */  120.0f, },
50027bfbee1SPeter Avalos 	},
50127bfbee1SPeter Avalos 
50227bfbee1SPeter Avalos 	/* MCS 12  */
503*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
504*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
50527bfbee1SPeter Avalos 	},
50627bfbee1SPeter Avalos 
50727bfbee1SPeter Avalos 	/* MCS 13  */
508*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  104.0f,		/* SGI */  115.6f, },
509*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  216.0f,		/* SGI */  240.0f, },
51027bfbee1SPeter Avalos 	},
51127bfbee1SPeter Avalos 
51227bfbee1SPeter Avalos 	/* MCS 14  */
513*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
514*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
51527bfbee1SPeter Avalos 	},
51627bfbee1SPeter Avalos 
51727bfbee1SPeter Avalos 	/* MCS 15  */
518*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  130.0f,		/* SGI */  144.4f, },
519*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  270.0f,		/* SGI */  300.0f, },
52027bfbee1SPeter Avalos 	},
52127bfbee1SPeter Avalos 
52227bfbee1SPeter Avalos 	/* MCS 16  */
523*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   19.5f,		/* SGI */   21.7f, },
524*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   40.5f,		/* SGI */   45.0f, },
52527bfbee1SPeter Avalos 	},
52627bfbee1SPeter Avalos 
52727bfbee1SPeter Avalos 	/* MCS 17  */
528*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   39.0f,		/* SGI */   43.3f, },
529*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   81.0f,		/* SGI */   90.0f, },
53027bfbee1SPeter Avalos 	},
53127bfbee1SPeter Avalos 
53227bfbee1SPeter Avalos 	/* MCS 18  */
533*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   58.5f,		/* SGI */   65.0f, },
534*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  121.5f,		/* SGI */  135.0f, },
53527bfbee1SPeter Avalos 	},
53627bfbee1SPeter Avalos 
53727bfbee1SPeter Avalos 	/* MCS 19  */
538*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
539*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
54027bfbee1SPeter Avalos 	},
54127bfbee1SPeter Avalos 
54227bfbee1SPeter Avalos 	/* MCS 20  */
543*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
544*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
54527bfbee1SPeter Avalos 	},
54627bfbee1SPeter Avalos 
54727bfbee1SPeter Avalos 	/* MCS 21  */
548*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  156.0f,		/* SGI */  173.3f, },
549*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  324.0f,		/* SGI */  360.0f, },
55027bfbee1SPeter Avalos 	},
55127bfbee1SPeter Avalos 
55227bfbee1SPeter Avalos 	/* MCS 22  */
553*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  175.5f,		/* SGI */  195.0f, },
554*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  364.5f,		/* SGI */  405.0f, },
55527bfbee1SPeter Avalos 	},
55627bfbee1SPeter Avalos 
55727bfbee1SPeter Avalos 	/* MCS 23  */
558*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  195.0f,		/* SGI */  216.7f, },
559*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  405.0f,		/* SGI */  450.0f, },
56027bfbee1SPeter Avalos 	},
56127bfbee1SPeter Avalos 
56227bfbee1SPeter Avalos 	/* MCS 24  */
563*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   26.0f,		/* SGI */   28.9f, },
564*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   54.0f,		/* SGI */   60.0f, },
56527bfbee1SPeter Avalos 	},
56627bfbee1SPeter Avalos 
56727bfbee1SPeter Avalos 	/* MCS 25  */
568*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   52.0f,		/* SGI */   57.8f, },
569*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  108.0f,		/* SGI */  120.0f, },
57027bfbee1SPeter Avalos 	},
57127bfbee1SPeter Avalos 
57227bfbee1SPeter Avalos 	/* MCS 26  */
573*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
574*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
57527bfbee1SPeter Avalos 	},
57627bfbee1SPeter Avalos 
57727bfbee1SPeter Avalos 	/* MCS 27  */
578*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  104.0f,		/* SGI */  115.6f, },
579*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  216.0f,		/* SGI */  240.0f, },
58027bfbee1SPeter Avalos 	},
58127bfbee1SPeter Avalos 
58227bfbee1SPeter Avalos 	/* MCS 28  */
583*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  156.0f,		/* SGI */  173.3f, },
584*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  324.0f,		/* SGI */  360.0f, },
58527bfbee1SPeter Avalos 	},
58627bfbee1SPeter Avalos 
58727bfbee1SPeter Avalos 	/* MCS 29  */
588*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  208.0f,		/* SGI */  231.1f, },
589*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  432.0f,		/* SGI */  480.0f, },
59027bfbee1SPeter Avalos 	},
59127bfbee1SPeter Avalos 
59227bfbee1SPeter Avalos 	/* MCS 30  */
593*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  234.0f,		/* SGI */  260.0f, },
594*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  486.0f,		/* SGI */  540.0f, },
59527bfbee1SPeter Avalos 	},
59627bfbee1SPeter Avalos 
59727bfbee1SPeter Avalos 	/* MCS 31  */
598*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  260.0f,		/* SGI */  288.9f, },
599*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  540.0f,		/* SGI */  600.0f, },
60027bfbee1SPeter Avalos 	},
60127bfbee1SPeter Avalos 
60227bfbee1SPeter Avalos 	/* MCS 32  */
603*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {    0.0f,		/* SGI */    0.0f, }, /* not valid */
604*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {    6.0f,		/* SGI */    6.7f, },
60527bfbee1SPeter Avalos 	},
60627bfbee1SPeter Avalos 
60727bfbee1SPeter Avalos 	/* MCS 33  */
608*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   39.0f,		/* SGI */   43.3f, },
609*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {   81.0f,		/* SGI */   90.0f, },
61027bfbee1SPeter Avalos 	},
61127bfbee1SPeter Avalos 
61227bfbee1SPeter Avalos 	/* MCS 34  */
613*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   52.0f,		/* SGI */   57.8f, },
614*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  108.0f,		/* SGI */  120.0f, },
61527bfbee1SPeter Avalos 	},
61627bfbee1SPeter Avalos 
61727bfbee1SPeter Avalos 	/* MCS 35  */
618*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   65.0f,		/* SGI */   72.2f, },
619*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  135.0f,		/* SGI */  150.0f, },
62027bfbee1SPeter Avalos 	},
62127bfbee1SPeter Avalos 
62227bfbee1SPeter Avalos 	/* MCS 36  */
623*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   58.5f,		/* SGI */   65.0f, },
624*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  121.5f,		/* SGI */  135.0f, },
62527bfbee1SPeter Avalos 	},
62627bfbee1SPeter Avalos 
62727bfbee1SPeter Avalos 	/* MCS 37  */
628*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
629*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
63027bfbee1SPeter Avalos 	},
63127bfbee1SPeter Avalos 
63227bfbee1SPeter Avalos 	/* MCS 38  */
633*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   97.5f,		/* SGI */  108.3f, },
634*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  202.5f,		/* SGI */  225.0f, },
63527bfbee1SPeter Avalos 	},
63627bfbee1SPeter Avalos 
63727bfbee1SPeter Avalos 	/* MCS 39  */
638*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   52.0f,		/* SGI */   57.8f, },
639*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  108.0f,		/* SGI */  120.0f, },
64027bfbee1SPeter Avalos 	},
64127bfbee1SPeter Avalos 
64227bfbee1SPeter Avalos 	/* MCS 40  */
643*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   65.0f,		/* SGI */   72.2f, },
644*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  135.0f,		/* SGI */  150.0f, },
64527bfbee1SPeter Avalos 	},
64627bfbee1SPeter Avalos 
64727bfbee1SPeter Avalos 	/* MCS 41  */
648*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   65.0f,		/* SGI */   72.2f, },
649*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  135.0f,		/* SGI */  150.0f, },
65027bfbee1SPeter Avalos 	},
65127bfbee1SPeter Avalos 
65227bfbee1SPeter Avalos 	/* MCS 42  */
653*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
654*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
65527bfbee1SPeter Avalos 	},
65627bfbee1SPeter Avalos 
65727bfbee1SPeter Avalos 	/* MCS 43  */
658*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   91.0f,		/* SGI */  101.1f, },
659*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  189.0f,		/* SGI */  210.0f, },
66027bfbee1SPeter Avalos 	},
66127bfbee1SPeter Avalos 
66227bfbee1SPeter Avalos 	/* MCS 44  */
663*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   91.0f,		/* SGI */  101.1f, },
664*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  189.0f,		/* SGI */  210.0f, },
66527bfbee1SPeter Avalos 	},
66627bfbee1SPeter Avalos 
66727bfbee1SPeter Avalos 	/* MCS 45  */
668*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  104.0f,		/* SGI */  115.6f, },
669*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  216.0f,		/* SGI */  240.0f, },
67027bfbee1SPeter Avalos 	},
67127bfbee1SPeter Avalos 
67227bfbee1SPeter Avalos 	/* MCS 46  */
673*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
674*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
67527bfbee1SPeter Avalos 	},
67627bfbee1SPeter Avalos 
67727bfbee1SPeter Avalos 	/* MCS 47  */
678*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   97.5f,		/* SGI */  108.3f, },
679*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  202.5f,		/* SGI */  225.0f, },
68027bfbee1SPeter Avalos 	},
68127bfbee1SPeter Avalos 
68227bfbee1SPeter Avalos 	/* MCS 48  */
683*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   97.5f,		/* SGI */  108.3f, },
684*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  202.5f,		/* SGI */  225.0f, },
68527bfbee1SPeter Avalos 	},
68627bfbee1SPeter Avalos 
68727bfbee1SPeter Avalos 	/* MCS 49  */
688*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
689*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
69027bfbee1SPeter Avalos 	},
69127bfbee1SPeter Avalos 
69227bfbee1SPeter Avalos 	/* MCS 50  */
693*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  136.5f,		/* SGI */  151.7f, },
694*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  283.5f,		/* SGI */  315.0f, },
69527bfbee1SPeter Avalos 	},
69627bfbee1SPeter Avalos 
69727bfbee1SPeter Avalos 	/* MCS 51  */
698*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  136.5f,		/* SGI */  151.7f, },
699*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  283.5f,		/* SGI */  315.0f, },
70027bfbee1SPeter Avalos 	},
70127bfbee1SPeter Avalos 
70227bfbee1SPeter Avalos 	/* MCS 52  */
703*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  156.0f,		/* SGI */  173.3f, },
704*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  324.0f,		/* SGI */  360.0f, },
70527bfbee1SPeter Avalos 	},
70627bfbee1SPeter Avalos 
70727bfbee1SPeter Avalos 	/* MCS 53  */
708*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   65.0f,		/* SGI */   72.2f, },
709*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  135.0f,		/* SGI */  150.0f, },
71027bfbee1SPeter Avalos 	},
71127bfbee1SPeter Avalos 
71227bfbee1SPeter Avalos 	/* MCS 54  */
713*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
714*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
71527bfbee1SPeter Avalos 	},
71627bfbee1SPeter Avalos 
71727bfbee1SPeter Avalos 	/* MCS 55  */
718*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   91.0f,		/* SGI */  101.1f, },
719*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  189.0f,		/* SGI */  210.0f, },
72027bfbee1SPeter Avalos 	},
72127bfbee1SPeter Avalos 
72227bfbee1SPeter Avalos 	/* MCS 56  */
723*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   78.0f,		/* SGI */   86.7f, },
724*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  162.0f,		/* SGI */  180.0f, },
72527bfbee1SPeter Avalos 	},
72627bfbee1SPeter Avalos 
72727bfbee1SPeter Avalos 	/* MCS 57  */
728*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   91.0f,		/* SGI */  101.1f, },
729*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  189.0f,		/* SGI */  210.0f, },
73027bfbee1SPeter Avalos 	},
73127bfbee1SPeter Avalos 
73227bfbee1SPeter Avalos 	/* MCS 58  */
733*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  104.0f,		/* SGI */  115.6f, },
734*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  216.0f,		/* SGI */  240.0f, },
73527bfbee1SPeter Avalos 	},
73627bfbee1SPeter Avalos 
73727bfbee1SPeter Avalos 	/* MCS 59  */
738*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
739*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
74027bfbee1SPeter Avalos 	},
74127bfbee1SPeter Avalos 
74227bfbee1SPeter Avalos 	/* MCS 60  */
743*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  104.0f,		/* SGI */  115.6f, },
744*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  216.0f,		/* SGI */  240.0f, },
74527bfbee1SPeter Avalos 	},
74627bfbee1SPeter Avalos 
74727bfbee1SPeter Avalos 	/* MCS 61  */
748*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
749*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
75027bfbee1SPeter Avalos 	},
75127bfbee1SPeter Avalos 
75227bfbee1SPeter Avalos 	/* MCS 62  */
753*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  130.0f,		/* SGI */  144.4f, },
754*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  270.0f,		/* SGI */  300.0f, },
75527bfbee1SPeter Avalos 	},
75627bfbee1SPeter Avalos 
75727bfbee1SPeter Avalos 	/* MCS 63  */
758*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  130.0f,		/* SGI */  144.4f, },
759*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  270.0f,		/* SGI */  300.0f, },
76027bfbee1SPeter Avalos 	},
76127bfbee1SPeter Avalos 
76227bfbee1SPeter Avalos 	/* MCS 64  */
763*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  143.0f,		/* SGI */  158.9f, },
764*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  297.0f,		/* SGI */  330.0f, },
76527bfbee1SPeter Avalos 	},
76627bfbee1SPeter Avalos 
76727bfbee1SPeter Avalos 	/* MCS 65  */
768*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {   97.5f,		/* SGI */  108.3f, },
769*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  202.5f,		/* SGI */  225.0f, },
77027bfbee1SPeter Avalos 	},
77127bfbee1SPeter Avalos 
77227bfbee1SPeter Avalos 	/* MCS 66  */
773*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
774*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
77527bfbee1SPeter Avalos 	},
77627bfbee1SPeter Avalos 
77727bfbee1SPeter Avalos 	/* MCS 67  */
778*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  136.5f,		/* SGI */  151.7f, },
779*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  283.5f,		/* SGI */  315.0f, },
78027bfbee1SPeter Avalos 	},
78127bfbee1SPeter Avalos 
78227bfbee1SPeter Avalos 	/* MCS 68  */
783*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  117.0f,		/* SGI */  130.0f, },
784*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  243.0f,		/* SGI */  270.0f, },
78527bfbee1SPeter Avalos 	},
78627bfbee1SPeter Avalos 
78727bfbee1SPeter Avalos 	/* MCS 69  */
788*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  136.5f,		/* SGI */  151.7f, },
789*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  283.5f,		/* SGI */  315.0f, },
79027bfbee1SPeter Avalos 	},
79127bfbee1SPeter Avalos 
79227bfbee1SPeter Avalos 	/* MCS 70  */
793*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  156.0f,		/* SGI */  173.3f, },
794*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  324.0f,		/* SGI */  360.0f, },
79527bfbee1SPeter Avalos 	},
79627bfbee1SPeter Avalos 
79727bfbee1SPeter Avalos 	/* MCS 71  */
798*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  175.5f,		/* SGI */  195.0f, },
799*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  364.5f,		/* SGI */  405.0f, },
80027bfbee1SPeter Avalos 	},
80127bfbee1SPeter Avalos 
80227bfbee1SPeter Avalos 	/* MCS 72  */
803*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  156.0f,		/* SGI */  173.3f, },
804*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  324.0f,		/* SGI */  360.0f, },
80527bfbee1SPeter Avalos 	},
80627bfbee1SPeter Avalos 
80727bfbee1SPeter Avalos 	/* MCS 73  */
808*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  175.5f,		/* SGI */  195.0f, },
809*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  364.5f,		/* SGI */  405.0f, },
81027bfbee1SPeter Avalos 	},
81127bfbee1SPeter Avalos 
81227bfbee1SPeter Avalos 	/* MCS 74  */
813*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  195.0f,		/* SGI */  216.7f, },
814*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  405.0f,		/* SGI */  450.0f, },
81527bfbee1SPeter Avalos 	},
81627bfbee1SPeter Avalos 
81727bfbee1SPeter Avalos 	/* MCS 75  */
818*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  195.0f,		/* SGI */  216.7f, },
819*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  405.0f,		/* SGI */  450.0f, },
82027bfbee1SPeter Avalos 	},
82127bfbee1SPeter Avalos 
82227bfbee1SPeter Avalos 	/* MCS 76  */
823*ed775ee7SAntonio Huete Jimenez 	{	/* 20 Mhz */ {  214.5f,		/* SGI */  238.3f, },
824*ed775ee7SAntonio Huete Jimenez 		/* 40 Mhz */ {  445.5f,		/* SGI */  495.0f, },
82527bfbee1SPeter Avalos 	},
82627bfbee1SPeter Avalos };
82727bfbee1SPeter Avalos 
82841c99275SPeter Avalos static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
829*ed775ee7SAntonio Huete Jimenez #define NUM_AUTH_ALGS	(sizeof(auth_alg_text) / sizeof(auth_alg_text[0]))
83041c99275SPeter Avalos 
83141c99275SPeter Avalos static const char *status_text[] = {
8326263709fSPeter Avalos 	"Successful",						/*  0 */
83341c99275SPeter Avalos 	"Unspecified failure",					/*  1 */
834*ed775ee7SAntonio Huete Jimenez 	"TDLS wakeup schedule rejected but alternative schedule "
835*ed775ee7SAntonio Huete Jimenez 	  "provided",					/*  2 */
836*ed775ee7SAntonio Huete Jimenez 	"TDLS wakeup schedule rejected",/*  3 */
83741c99275SPeter Avalos 	"Reserved",						/*  4 */
838*ed775ee7SAntonio Huete Jimenez 	"Security disabled",			/*  5 */
839*ed775ee7SAntonio Huete Jimenez 	"Unacceptable lifetime",		/*  6 */
840*ed775ee7SAntonio Huete Jimenez 	"Not in same BSS",				/*  7 */
84141c99275SPeter Avalos 	"Reserved",						/*  8 */
84241c99275SPeter Avalos 	"Reserved",						/*  9 */
84327bfbee1SPeter Avalos 	"Cannot Support all requested capabilities in the Capability "
84427bfbee1SPeter Avalos 	  "Information field",					/* 10 */
84527bfbee1SPeter Avalos 	"Reassociation denied due to inability to confirm that association "
84627bfbee1SPeter Avalos 	  "exists",						/* 11 */
847*ed775ee7SAntonio Huete Jimenez 	"Association denied due to reason outside the scope of this "
84827bfbee1SPeter Avalos 	  "standard",						/* 12 */
849*ed775ee7SAntonio Huete Jimenez 	"Responding STA does not support the specified authentication "
85027bfbee1SPeter Avalos 	  "algorithm",						/* 13 */
85127bfbee1SPeter Avalos 	"Received an Authentication frame with authentication transaction "
85241c99275SPeter Avalos 	  "sequence number out of expected sequence",		/* 14 */
85341c99275SPeter Avalos 	"Authentication rejected because of challenge failure",	/* 15 */
85427bfbee1SPeter Avalos 	"Authentication rejected due to timeout waiting for next frame in "
85527bfbee1SPeter Avalos 	  "sequence",						/* 16 */
856*ed775ee7SAntonio Huete Jimenez 	"Association denied because AP is unable to handle "
857*ed775ee7SAntonio Huete Jimenez 	  "additional associated STAs",				/* 17 */
858*ed775ee7SAntonio Huete Jimenez 	"Association denied due to requesting STA not supporting "
859*ed775ee7SAntonio Huete Jimenez 	  "all of the data rates in the BSSBasicRateSet parameter, "
860*ed775ee7SAntonio Huete Jimenez 	  "the Basic HT-MCS Set field of the HT Operation "
861*ed775ee7SAntonio Huete Jimenez 	  "parameter, or the Basic VHT-MCS and NSS Set field in "
862*ed775ee7SAntonio Huete Jimenez 	  "the VHT Operation parameter",	/* 18 */
863*ed775ee7SAntonio Huete Jimenez 	"Association denied due to requesting STA not supporting "
864*ed775ee7SAntonio Huete Jimenez 	  "the short preamble option",				/* 19 */
865*ed775ee7SAntonio Huete Jimenez 	"Reserved",					/* 20 */
866*ed775ee7SAntonio Huete Jimenez 	"Reserved",					/* 21 */
86727bfbee1SPeter Avalos 	"Association request rejected because Spectrum Management "
86827bfbee1SPeter Avalos 	  "capability is required",				/* 22 */
86927bfbee1SPeter Avalos 	"Association request rejected because the information in the "
87027bfbee1SPeter Avalos 	  "Power Capability element is unacceptable",		/* 23 */
87127bfbee1SPeter Avalos 	"Association request rejected because the information in the "
87227bfbee1SPeter Avalos 	  "Supported Channels element is unacceptable",		/* 24 */
873*ed775ee7SAntonio Huete Jimenez 	"Association denied due to requesting STA not supporting "
874*ed775ee7SAntonio Huete Jimenez 	  "the Short Slot Time option",				/* 25 */
875*ed775ee7SAntonio Huete Jimenez 	"Reserved",				/* 26 */
87627bfbee1SPeter Avalos 	"Association denied because the requested STA does not support HT "
87727bfbee1SPeter Avalos 	  "features",						/* 27 */
878*ed775ee7SAntonio Huete Jimenez 	"R0KH unreachable",					/* 28 */
879*ed775ee7SAntonio Huete Jimenez 	"Association denied because the requesting STA does not "
880*ed775ee7SAntonio Huete Jimenez 	  "support the phased coexistence operation (PCO) "
881*ed775ee7SAntonio Huete Jimenez 	  "transition time required by the AP",		/* 29 */
882*ed775ee7SAntonio Huete Jimenez 	"Association request rejected temporarily; try again "
883*ed775ee7SAntonio Huete Jimenez 	  "later",							/* 30 */
884*ed775ee7SAntonio Huete Jimenez 	"Robust management frame policy violation",	/* 31 */
88527bfbee1SPeter Avalos 	"Unspecified, QoS-related failure",			/* 32 */
886*ed775ee7SAntonio Huete Jimenez 	"Association denied because QoS AP or PCP has "
887*ed775ee7SAntonio Huete Jimenez 	  "insufficient bandwidth to handle another QoS "
888*ed775ee7SAntonio Huete Jimenez 	  "STA",									/* 33 */
88927bfbee1SPeter Avalos 	"Association denied due to excessive frame loss rates and/or "
89027bfbee1SPeter Avalos 	  "poor conditions on current operating channel",	/* 34 */
891*ed775ee7SAntonio Huete Jimenez 	"Association (with QoS BSS) denied because the requesting STA "
892*ed775ee7SAntonio Huete Jimenez 	  "does not support the QoS facility",			/* 35 */
893*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 36 */
89427bfbee1SPeter Avalos 	"The request has been declined",			/* 37 */
89527bfbee1SPeter Avalos 	"The request has not been successful as one or more parameters "
89627bfbee1SPeter Avalos 	  "have invalid values",				/* 38 */
897*ed775ee7SAntonio Huete Jimenez 	"The allocation or TS has not been created because the request "
898*ed775ee7SAntonio Huete Jimenez 	  "cannot be honored; however, a suggested TSPEC/DMG TSPEC is "
899*ed775ee7SAntonio Huete Jimenez 	  "provided so that the initiating STA can attempt to set "
900*ed775ee7SAntonio Huete Jimenez 	  "another allocation or TS with the suggested changes to the "
901*ed775ee7SAntonio Huete Jimenez 	  "TSPEC/DMG TSPEC",					/* 39 */
902*ed775ee7SAntonio Huete Jimenez 	"Invalid element, i.e., an element defined in this standard "
903*ed775ee7SAntonio Huete Jimenez 	  "for which the content does not meet the specifications in "
904*ed775ee7SAntonio Huete Jimenez 	  "Clause 9",								/* 40 */
905*ed775ee7SAntonio Huete Jimenez 	"Invalid group cipher",						/* 41 */
906*ed775ee7SAntonio Huete Jimenez 	"Invalid pairwise cipher",					/* 42 */
907*ed775ee7SAntonio Huete Jimenez 	"Invalid AKMP",								/* 43 */
908*ed775ee7SAntonio Huete Jimenez 	"Unsupported RSNE version",					/* 44 */
909*ed775ee7SAntonio Huete Jimenez 	"Invalid RSNE capabilities",				/* 45 */
910*ed775ee7SAntonio Huete Jimenez 	"Cipher suite rejected because of security policy",		/* 46 */
911*ed775ee7SAntonio Huete Jimenez 	"The TS or allocation has not been created; however, the "
912*ed775ee7SAntonio Huete Jimenez 	  "HC or PCP might be capable of creating a TS or "
913*ed775ee7SAntonio Huete Jimenez 	  "allocation, in response to a request, after the time "
914*ed775ee7SAntonio Huete Jimenez 	  "indicated in the TS Delay element",		/* 47 */
91527bfbee1SPeter Avalos 	"Direct Link is not allowed in the BSS by policy",	/* 48 */
916*ed775ee7SAntonio Huete Jimenez 	"The Destination STA is not present within this BSS",	/* 49 */
917*ed775ee7SAntonio Huete Jimenez 	"The Destination STA is not a QoS STA",		/* 50 */
91827bfbee1SPeter Avalos 
919*ed775ee7SAntonio Huete Jimenez 	"Association denied because the listen interval is "
920*ed775ee7SAntonio Huete Jimenez 	  "too large",								/* 51 */
921*ed775ee7SAntonio Huete Jimenez 	"Invalid FT Action frame count",			/* 52 */
922*ed775ee7SAntonio Huete Jimenez 	"Invalid pairwise master key identifier (PMKID)", /* 53 */
923*ed775ee7SAntonio Huete Jimenez 	"Invalid MDE",								/* 54 */
924*ed775ee7SAntonio Huete Jimenez 	"Invalid FTE",								/* 55 */
925*ed775ee7SAntonio Huete Jimenez 	"Requested TCLAS processing is not supported by the AP "
926*ed775ee7SAntonio Huete Jimenez 	  "or PCP",									/* 56 */
927*ed775ee7SAntonio Huete Jimenez 	"The AP or PCP has insufficient TCLAS processing "
928*ed775ee7SAntonio Huete Jimenez 	  "resources to satisfy the request",		/* 57 */
929*ed775ee7SAntonio Huete Jimenez 	"The TS has not been created because the request "
930*ed775ee7SAntonio Huete Jimenez 	  "cannot be honored; however, the HC or PCP suggests "
931*ed775ee7SAntonio Huete Jimenez 	  "that the STA transition to a different BSS to set up "
932*ed775ee7SAntonio Huete Jimenez 	  "the TS",									/* 58 */
933*ed775ee7SAntonio Huete Jimenez 	"GAS Advertisement Protocol not supported",	/* 59 */
934*ed775ee7SAntonio Huete Jimenez 	"No outstanding GAS request",				/* 60 */
935*ed775ee7SAntonio Huete Jimenez 	"GAS Response not received from the Advertisement "
936*ed775ee7SAntonio Huete Jimenez 	  "Server",									/* 61 */
937*ed775ee7SAntonio Huete Jimenez 	"STA timed out waiting for GAS Query Response", /* 62 */
938*ed775ee7SAntonio Huete Jimenez 	"LARGE GAS Response is larger than query response "
939*ed775ee7SAntonio Huete Jimenez 	  "length limit",							/* 63 */
940*ed775ee7SAntonio Huete Jimenez 	"Request refused because home network does not support "
941*ed775ee7SAntonio Huete Jimenez 	  "request",								/* 64 */
942*ed775ee7SAntonio Huete Jimenez 	"Advertisement Server in the network is not currently "
943*ed775ee7SAntonio Huete Jimenez 	  "reachable",								/* 65 */
944*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 66 */
945*ed775ee7SAntonio Huete Jimenez 	"Request refused due to permissions received via SSPN "
946*ed775ee7SAntonio Huete Jimenez 	  "interface",								/* 67 */
947*ed775ee7SAntonio Huete Jimenez 	"Request refused because the AP or PCP does not "
948*ed775ee7SAntonio Huete Jimenez 	  "support unauthenticated access",			/* 68 */
949*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 69 */
950*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 70 */
951*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 71 */
952*ed775ee7SAntonio Huete Jimenez 	"Invalid contents of RSNE", 				/* 72 */
953*ed775ee7SAntonio Huete Jimenez 	"U-APSD coexistence is not supported", 		/* 73 */
954*ed775ee7SAntonio Huete Jimenez 	"Requested U-APSD coexistence mode is not supported", /* 74 */
955*ed775ee7SAntonio Huete Jimenez 	"Requested Interval/Duration value cannot be "
956*ed775ee7SAntonio Huete Jimenez 	  "supported with U-APSD coexistence",		/* 75 */
957*ed775ee7SAntonio Huete Jimenez 	"Authentication is rejected because an Anti-Clogging "
958*ed775ee7SAntonio Huete Jimenez 	  "Token is required",						/* 76 */
959*ed775ee7SAntonio Huete Jimenez 	"Authentication is rejected because the offered "
960*ed775ee7SAntonio Huete Jimenez 	  "finite cyclic group is not supported",	/* 77 */
961*ed775ee7SAntonio Huete Jimenez 	"The TBTT adjustment request has not been successful "
962*ed775ee7SAntonio Huete Jimenez 	  "because the STA could not find an alternative TBTT", /* 78 */
963*ed775ee7SAntonio Huete Jimenez 	"Transmission failure",						/* 79 */
964*ed775ee7SAntonio Huete Jimenez 	"Requested TCLAS Not Supported",			/* 80 */
965*ed775ee7SAntonio Huete Jimenez 	"TCLAS Resources Exhausted",				/* 81 */
966*ed775ee7SAntonio Huete Jimenez 	"Rejected with Suggested BSS transition",	/* 82 */
967*ed775ee7SAntonio Huete Jimenez 	"Reject with recommended schedule",			/* 83 */
968*ed775ee7SAntonio Huete Jimenez 	"Reject because no wakeup schedule specified", /* 84 */
969*ed775ee7SAntonio Huete Jimenez 	"Success, the destination STA is in power save mode", /* 85 */
970*ed775ee7SAntonio Huete Jimenez 	"FST pending, in process of admitting FST session", /* 86 */
971*ed775ee7SAntonio Huete Jimenez 	"Performing FST now",						/* 87 */
972*ed775ee7SAntonio Huete Jimenez 	"FST pending, gap(s) in block ack window",	/* 88 */
973*ed775ee7SAntonio Huete Jimenez 	"Reject because of U-PID setting",			/* 89 */
974*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 90 */
975*ed775ee7SAntonio Huete Jimenez 	"Reserved",									/* 91 */
976*ed775ee7SAntonio Huete Jimenez 	"(Re)Association refused for some external reason", /* 92 */
977*ed775ee7SAntonio Huete Jimenez 	"(Re)Association refused because of memory limits "
978*ed775ee7SAntonio Huete Jimenez 	  "at the AP",								/* 93 */
979*ed775ee7SAntonio Huete Jimenez 	"(Re)Association refused because emergency services "
980*ed775ee7SAntonio Huete Jimenez 	  "are not supported at the AP",			/* 94 */
981*ed775ee7SAntonio Huete Jimenez 	"GAS query response not yet received",		/* 95 */
982*ed775ee7SAntonio Huete Jimenez 	"Reject since the request is for transition to a "
983*ed775ee7SAntonio Huete Jimenez 	  "frequency band subject to DSE procedures and "
984*ed775ee7SAntonio Huete Jimenez 	  "FST Initiator is a dependent STA",		/* 96 */
985*ed775ee7SAntonio Huete Jimenez 	"Requested TCLAS processing has been terminated by "
986*ed775ee7SAntonio Huete Jimenez 	  "the AP",									/* 97 */
987*ed775ee7SAntonio Huete Jimenez 	"The TS schedule conflicts with an existing "
988*ed775ee7SAntonio Huete Jimenez 	  "schedule; an alternative schedule is provided", /* 98 */
989*ed775ee7SAntonio Huete Jimenez 	"The association has been denied; however, one or "
990*ed775ee7SAntonio Huete Jimenez 	  "more Multi-band elements are included that can "
991*ed775ee7SAntonio Huete Jimenez 	  "be used by the receiving STA to join the BSS", /* 99 */
992*ed775ee7SAntonio Huete Jimenez 	"The request failed due to a reservation conflict", /* 100 */
993*ed775ee7SAntonio Huete Jimenez 	"The request failed due to exceeded MAF limit", /* 101 */
994*ed775ee7SAntonio Huete Jimenez 	"The request failed due to exceeded MCCA track "
995*ed775ee7SAntonio Huete Jimenez 	  "limit",									/* 102 */
996*ed775ee7SAntonio Huete Jimenez 	"Association denied because the information in the"
997*ed775ee7SAntonio Huete Jimenez 	  "Spectrum Management field is unacceptable", /* 103 */
998*ed775ee7SAntonio Huete Jimenez 	"Association denied because the requesting STA "
999*ed775ee7SAntonio Huete Jimenez 	  "does not support VHT features",			/* 104 */
1000*ed775ee7SAntonio Huete Jimenez 	"Enablement denied", 						/* 105 */
1001*ed775ee7SAntonio Huete Jimenez 	"Enablement denied due to restriction from an "
1002*ed775ee7SAntonio Huete Jimenez 	  "authorized GDB",							/* 106 */
1003*ed775ee7SAntonio Huete Jimenez 	"Authorization deenabled",					/* 107 */
100441c99275SPeter Avalos };
1005*ed775ee7SAntonio Huete Jimenez #define NUM_STATUSES	(sizeof(status_text) / sizeof(status_text[0]))
100641c99275SPeter Avalos 
100741c99275SPeter Avalos static const char *reason_text[] = {
100841c99275SPeter Avalos 	"Reserved",						/* 0 */
100941c99275SPeter Avalos 	"Unspecified reason",					/* 1 */
101041c99275SPeter Avalos 	"Previous authentication no longer valid",		/* 2 */
1011*ed775ee7SAntonio Huete Jimenez 	"Deauthenticated because sending STA is leaving (or has left) "
101227bfbee1SPeter Avalos 	  "IBSS or ESS",					/* 3 */
101341c99275SPeter Avalos 	"Disassociated due to inactivity",			/* 4 */
101427bfbee1SPeter Avalos 	"Disassociated because AP is unable to handle all currently "
1015*ed775ee7SAntonio Huete Jimenez 	  " associated STAs",				/* 5 */
1016*ed775ee7SAntonio Huete Jimenez 	"Class 2 frame received from nonauthenticated STA", /* 6 */
1017*ed775ee7SAntonio Huete Jimenez 	"Class 3 frame received from nonassociated STA",	/* 7 */
1018*ed775ee7SAntonio Huete Jimenez 	"Disassociated because sending STA is leaving "
101927bfbee1SPeter Avalos 	  "(or has left) BSS",					/* 8 */
1020*ed775ee7SAntonio Huete Jimenez 	"STA requesting (re)association is not authenticated with "
1021*ed775ee7SAntonio Huete Jimenez 	  "responding STA",					/* 9 */
102227bfbee1SPeter Avalos 	"Disassociated because the information in the Power Capability "
102327bfbee1SPeter Avalos 	  "element is unacceptable",				/* 10 */
102427bfbee1SPeter Avalos 	"Disassociated because the information in the Supported Channels "
102527bfbee1SPeter Avalos 	  "element is unacceptable",				/* 11 */
1026*ed775ee7SAntonio Huete Jimenez 	"Disassociated due to BSS transition management",	/* 12 */
1027*ed775ee7SAntonio Huete Jimenez 	"Invalid element, i.e., an element defined in this standard for "
1028*ed775ee7SAntonio Huete Jimenez 	  "which the content does not meet the specifications "
1029*ed775ee7SAntonio Huete Jimenez 	  "in Clause 9",						/* 13 */
1030*ed775ee7SAntonio Huete Jimenez 	"Message integrity code (MIC) failure",	/* 14 */
103127bfbee1SPeter Avalos 	"4-Way Handshake timeout",				/* 15 */
1032*ed775ee7SAntonio Huete Jimenez 	"Group key handshake timeout",			/* 16 */
103327bfbee1SPeter Avalos 	"Information element in 4-Way Handshake different from (Re)Association"
1034*ed775ee7SAntonio Huete Jimenez 	  "Request/Probe Response/Beacon frame",	/* 17 */
1035*ed775ee7SAntonio Huete Jimenez 	"Invalid group cipher",					/* 18 */
1036*ed775ee7SAntonio Huete Jimenez 	"Invalid pairwise cipher",				/* 19 */
1037*ed775ee7SAntonio Huete Jimenez 	"Invalid AKMP",							/* 20 */
1038*ed775ee7SAntonio Huete Jimenez 	"Unsupported RSNE version",				/* 21 */
1039*ed775ee7SAntonio Huete Jimenez 	"Invalid RSNE capabilities",				/* 22 */
1040*ed775ee7SAntonio Huete Jimenez 	"IEEE 802.1X authentication failed",			/* 23 */
1041*ed775ee7SAntonio Huete Jimenez 	"Cipher suite rejected because of the security policy",		/* 24 */
1042*ed775ee7SAntonio Huete Jimenez 	"TDLS direct-link teardown due to TDLS peer STA "
1043*ed775ee7SAntonio Huete Jimenez 	  "unreachable via the TDLS direct link",				/* 25 */
1044*ed775ee7SAntonio Huete Jimenez 	"TDLS direct-link teardown for unspecified reason",		/* 26 */
1045*ed775ee7SAntonio Huete Jimenez 	"Disassociated because session terminated by SSP request",/* 27 */
1046*ed775ee7SAntonio Huete Jimenez 	"Disassociated because of lack of SSP roaming agreement",/* 28 */
1047*ed775ee7SAntonio Huete Jimenez 	"Requested service rejected because of SSP cipher suite or "
1048*ed775ee7SAntonio Huete Jimenez 	  "AKM requirement",						/* 29 */
1049*ed775ee7SAntonio Huete Jimenez 	"Requested service not authorized in this location",	/* 30 */
105027bfbee1SPeter Avalos 	"TS deleted because QoS AP lacks sufficient bandwidth for this "
105127bfbee1SPeter Avalos 	  "QoS STA due to a change in BSS service characteristics or "
105227bfbee1SPeter Avalos 	  "operational mode (e.g. an HT BSS change from 40 MHz channel "
105327bfbee1SPeter Avalos 	  "to 20 MHz channel)",					/* 31 */
105427bfbee1SPeter Avalos 	"Disassociated for unspecified, QoS-related reason",	/* 32 */
105527bfbee1SPeter Avalos 	"Disassociated because QoS AP lacks sufficient bandwidth for this "
105627bfbee1SPeter Avalos 	  "QoS STA",						/* 33 */
105727bfbee1SPeter Avalos 	"Disassociated because of excessive number of frames that need to be "
1058*ed775ee7SAntonio Huete Jimenez 	  "acknowledged, but are not acknowledged due to AP transmissions "
105927bfbee1SPeter Avalos 	  "and/or poor channel conditions",			/* 34 */
106027bfbee1SPeter Avalos 	"Disassociated because STA is transmitting outside the limits "
106127bfbee1SPeter Avalos 	  "of its TXOPs",					/* 35 */
106227bfbee1SPeter Avalos 	"Requested from peer STA as the STA is leaving the BSS "
106327bfbee1SPeter Avalos 	  "(or resetting)",					/* 36 */
106427bfbee1SPeter Avalos 	"Requested from peer STA as it does not want to use the "
106527bfbee1SPeter Avalos 	  "mechanism",						/* 37 */
106627bfbee1SPeter Avalos 	"Requested from peer STA as the STA received frames using the "
106727bfbee1SPeter Avalos 	  "mechanism for which a set up is required",		/* 38 */
106827bfbee1SPeter Avalos 	"Requested from peer STA due to time out",		/* 39 */
106927bfbee1SPeter Avalos 	"Reserved",						/* 40 */
107027bfbee1SPeter Avalos 	"Reserved",						/* 41 */
107127bfbee1SPeter Avalos 	"Reserved",						/* 42 */
107227bfbee1SPeter Avalos 	"Reserved",						/* 43 */
107327bfbee1SPeter Avalos 	"Reserved",						/* 44 */
107427bfbee1SPeter Avalos 	"Peer STA does not support the requested cipher suite",	/* 45 */
1075*ed775ee7SAntonio Huete Jimenez 	"In a DLS Teardown frame: The teardown was initiated by the "
1076*ed775ee7SAntonio Huete Jimenez 	  "DLS peer. In a Disassociation frame: Disassociated because "
1077*ed775ee7SAntonio Huete Jimenez 	  "authorized access limit reached",					/* 46 */
1078*ed775ee7SAntonio Huete Jimenez 	"In a DLS Teardown frame: The teardown was initiated by the "
1079*ed775ee7SAntonio Huete Jimenez 	  "AP. In a Disassociation frame: Disassociated due to external "
1080*ed775ee7SAntonio Huete Jimenez 	  "service requirements",								/* 47 */
1081*ed775ee7SAntonio Huete Jimenez 	"Invalid FT Action frame count",						/* 48 */
1082*ed775ee7SAntonio Huete Jimenez 	"Invalid pairwise master key identifier (PMKID)",		/* 49 */
1083*ed775ee7SAntonio Huete Jimenez 	"Invalid MDE",											/* 50 */
1084*ed775ee7SAntonio Huete Jimenez 	"Invalid FTE",											/* 51 */
1085*ed775ee7SAntonio Huete Jimenez 	"Mesh peering canceled for unknown reasons",			/* 52 */
1086*ed775ee7SAntonio Huete Jimenez 	"The mesh STA has reached the supported maximum number of "
1087*ed775ee7SAntonio Huete Jimenez 	  "peer mesh STAs",										/* 53 */
1088*ed775ee7SAntonio Huete Jimenez 	"The received information violates the Mesh Configuration "
1089*ed775ee7SAntonio Huete Jimenez 	  "policy configured in the mesh STA profile",			/* 54 */
1090*ed775ee7SAntonio Huete Jimenez 	"The mesh STA has received a Mesh Peering Close frame "
1091*ed775ee7SAntonio Huete Jimenez 	  "requesting to close the mesh peering",				/* 55 */
1092*ed775ee7SAntonio Huete Jimenez 	"The mesh STA has resent dot11MeshMaxRetries Mesh "
1093*ed775ee7SAntonio Huete Jimenez 	  "Peering Open frames, without receiving a Mesh Peering "
1094*ed775ee7SAntonio Huete Jimenez 	  "Confirm frame",										/* 56 */
1095*ed775ee7SAntonio Huete Jimenez 	"The confirmTimer for the mesh peering instance times out",	/* 57 */
1096*ed775ee7SAntonio Huete Jimenez 	"The mesh STA fails to unwrap the GTK or the values in the "
1097*ed775ee7SAntonio Huete Jimenez 	  "wrapped contents do not match",						/* 58 */
1098*ed775ee7SAntonio Huete Jimenez 	"The mesh STA receives inconsistent information about the "
1099*ed775ee7SAntonio Huete Jimenez 	  "mesh parameters between mesh peering Management frames",	/* 59 */
1100*ed775ee7SAntonio Huete Jimenez 	"The mesh STA fails the authenticated mesh peering exchange "
1101*ed775ee7SAntonio Huete Jimenez 	  "because due to failure in selecting either the pairwise "
1102*ed775ee7SAntonio Huete Jimenez 	  "ciphersuite or group ciphersuite",					/* 60 */
1103*ed775ee7SAntonio Huete Jimenez 	"The mesh STA does not have proxy information for this "
1104*ed775ee7SAntonio Huete Jimenez 	  "external destination",								/* 61 */
1105*ed775ee7SAntonio Huete Jimenez 	"The mesh STA does not have forwarding information for this "
1106*ed775ee7SAntonio Huete Jimenez 	  "destination",										/* 62 */
1107*ed775ee7SAntonio Huete Jimenez 	"The mesh STA determines that the link to the next hop of an "
1108*ed775ee7SAntonio Huete Jimenez 	  "active path in its forwarding information is no longer "
1109*ed775ee7SAntonio Huete Jimenez 	  "usable",												/* 63 */
1110*ed775ee7SAntonio Huete Jimenez 	"The Deauthentication frame was sent because the MAC "
1111*ed775ee7SAntonio Huete Jimenez 	  "address of the STA already exists in the mesh BSS",	/* 64 */
1112*ed775ee7SAntonio Huete Jimenez 	"The mesh STA performs channel switch to meet regulatory "
1113*ed775ee7SAntonio Huete Jimenez 	  "requirements",										/* 65 */
1114*ed775ee7SAntonio Huete Jimenez 	"The mesh STA performs channel switching with unspecified "
1115*ed775ee7SAntonio Huete Jimenez 	  "reason",												/* 66 */
111641c99275SPeter Avalos };
1117*ed775ee7SAntonio Huete Jimenez #define NUM_REASONS	(sizeof(reason_text) / sizeof(reason_text[0]))
111841c99275SPeter Avalos 
111941c99275SPeter Avalos static int
wep_print(netdissect_options * ndo,const u_char * p)1120411677aeSAaron LI wep_print(netdissect_options *ndo,
1121411677aeSAaron LI 	  const u_char *p)
112241c99275SPeter Avalos {
1123411677aeSAaron LI 	uint32_t iv;
112441c99275SPeter Avalos 
1125*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN);
1126*ed775ee7SAntonio Huete Jimenez 	iv = GET_LE_U_4(p);
112741c99275SPeter Avalos 
1128*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
1129*ed775ee7SAntonio Huete Jimenez 	    IV_KEYID(iv));
113041c99275SPeter Avalos 
113141c99275SPeter Avalos 	return 1;
1132*ed775ee7SAntonio Huete Jimenez trunc:
1133*ed775ee7SAntonio Huete Jimenez 	return 0;
113441c99275SPeter Avalos }
113541c99275SPeter Avalos 
113627bfbee1SPeter Avalos static int
parse_elements(netdissect_options * ndo,struct mgmt_body_t * pbody,const u_char * p,int offset,u_int length)1137411677aeSAaron LI parse_elements(netdissect_options *ndo,
1138411677aeSAaron LI 	       struct mgmt_body_t *pbody, const u_char *p, int offset,
113927bfbee1SPeter Avalos 	       u_int length)
114041c99275SPeter Avalos {
114127bfbee1SPeter Avalos 	u_int elementlen;
114227bfbee1SPeter Avalos 	struct ssid_t ssid;
114327bfbee1SPeter Avalos 	struct challenge_t challenge;
114427bfbee1SPeter Avalos 	struct rates_t rates;
114527bfbee1SPeter Avalos 	struct ds_t ds;
114627bfbee1SPeter Avalos 	struct cf_t cf;
114727bfbee1SPeter Avalos 	struct tim_t tim;
114827bfbee1SPeter Avalos 
114941c99275SPeter Avalos 	/*
115041c99275SPeter Avalos 	 * We haven't seen any elements yet.
115141c99275SPeter Avalos 	 */
115227bfbee1SPeter Avalos 	pbody->challenge_present = 0;
115327bfbee1SPeter Avalos 	pbody->ssid_present = 0;
115427bfbee1SPeter Avalos 	pbody->rates_present = 0;
115527bfbee1SPeter Avalos 	pbody->ds_present = 0;
115627bfbee1SPeter Avalos 	pbody->cf_present = 0;
115727bfbee1SPeter Avalos 	pbody->tim_present = 0;
115841c99275SPeter Avalos 
115927bfbee1SPeter Avalos 	while (length != 0) {
1160411677aeSAaron LI 		/* Make sure we at least have the element ID and length. */
1161*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_2(p + offset);
116227bfbee1SPeter Avalos 		if (length < 2)
1163*ed775ee7SAntonio Huete Jimenez 			goto trunc;
1164*ed775ee7SAntonio Huete Jimenez 		elementlen = GET_U_1(p + offset + 1);
1165411677aeSAaron LI 
1166411677aeSAaron LI 		/* Make sure we have the entire element. */
1167*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p + offset + 2, elementlen);
1168411677aeSAaron LI 		if (length < elementlen + 2)
1169*ed775ee7SAntonio Huete Jimenez 			goto trunc;
1170411677aeSAaron LI 
1171*ed775ee7SAntonio Huete Jimenez 		switch (GET_U_1(p + offset)) {
1172411677aeSAaron LI 		case E_SSID:
117327bfbee1SPeter Avalos 			memcpy(&ssid, p + offset, 2);
117441c99275SPeter Avalos 			offset += 2;
117527bfbee1SPeter Avalos 			length -= 2;
117627bfbee1SPeter Avalos 			if (ssid.length != 0) {
117727bfbee1SPeter Avalos 				if (ssid.length > sizeof(ssid.ssid) - 1)
117827bfbee1SPeter Avalos 					return 0;
117927bfbee1SPeter Avalos 				memcpy(&ssid.ssid, p + offset, ssid.length);
118027bfbee1SPeter Avalos 				offset += ssid.length;
118127bfbee1SPeter Avalos 				length -= ssid.length;
118241c99275SPeter Avalos 			}
118327bfbee1SPeter Avalos 			ssid.ssid[ssid.length] = '\0';
118427bfbee1SPeter Avalos 			/*
118527bfbee1SPeter Avalos 			 * Present and not truncated.
118627bfbee1SPeter Avalos 			 *
118727bfbee1SPeter Avalos 			 * If we haven't already seen an SSID IE,
118827bfbee1SPeter Avalos 			 * copy this one, otherwise ignore this one,
118927bfbee1SPeter Avalos 			 * so we later report the first one we saw.
119027bfbee1SPeter Avalos 			 */
119127bfbee1SPeter Avalos 			if (!pbody->ssid_present) {
119227bfbee1SPeter Avalos 				pbody->ssid = ssid;
119327bfbee1SPeter Avalos 				pbody->ssid_present = 1;
119427bfbee1SPeter Avalos 			}
119541c99275SPeter Avalos 			break;
119641c99275SPeter Avalos 		case E_CHALLENGE:
119727bfbee1SPeter Avalos 			memcpy(&challenge, p + offset, 2);
119841c99275SPeter Avalos 			offset += 2;
119927bfbee1SPeter Avalos 			length -= 2;
120027bfbee1SPeter Avalos 			if (challenge.length != 0) {
120127bfbee1SPeter Avalos 				if (challenge.length >
120227bfbee1SPeter Avalos 				    sizeof(challenge.text) - 1)
120327bfbee1SPeter Avalos 					return 0;
120427bfbee1SPeter Avalos 				memcpy(&challenge.text, p + offset,
120527bfbee1SPeter Avalos 				    challenge.length);
120627bfbee1SPeter Avalos 				offset += challenge.length;
120727bfbee1SPeter Avalos 				length -= challenge.length;
120841c99275SPeter Avalos 			}
120927bfbee1SPeter Avalos 			challenge.text[challenge.length] = '\0';
121027bfbee1SPeter Avalos 			/*
121127bfbee1SPeter Avalos 			 * Present and not truncated.
121227bfbee1SPeter Avalos 			 *
121327bfbee1SPeter Avalos 			 * If we haven't already seen a challenge IE,
121427bfbee1SPeter Avalos 			 * copy this one, otherwise ignore this one,
121527bfbee1SPeter Avalos 			 * so we later report the first one we saw.
121627bfbee1SPeter Avalos 			 */
121727bfbee1SPeter Avalos 			if (!pbody->challenge_present) {
121827bfbee1SPeter Avalos 				pbody->challenge = challenge;
121927bfbee1SPeter Avalos 				pbody->challenge_present = 1;
122027bfbee1SPeter Avalos 			}
122141c99275SPeter Avalos 			break;
122241c99275SPeter Avalos 		case E_RATES:
122327bfbee1SPeter Avalos 			memcpy(&rates, p + offset, 2);
122441c99275SPeter Avalos 			offset += 2;
122527bfbee1SPeter Avalos 			length -= 2;
122627bfbee1SPeter Avalos 			if (rates.length != 0) {
1227*ed775ee7SAntonio Huete Jimenez 				if (rates.length > sizeof(rates.rate))
122827bfbee1SPeter Avalos 					return 0;
122927bfbee1SPeter Avalos 				memcpy(&rates.rate, p + offset, rates.length);
123027bfbee1SPeter Avalos 				offset += rates.length;
123127bfbee1SPeter Avalos 				length -= rates.length;
123241c99275SPeter Avalos 			}
123327bfbee1SPeter Avalos 			/*
123427bfbee1SPeter Avalos 			 * Present and not truncated.
123527bfbee1SPeter Avalos 			 *
123627bfbee1SPeter Avalos 			 * If we haven't already seen a rates IE,
123727bfbee1SPeter Avalos 			 * copy this one if it's not zero-length,
123827bfbee1SPeter Avalos 			 * otherwise ignore this one, so we later
123927bfbee1SPeter Avalos 			 * report the first one we saw.
124027bfbee1SPeter Avalos 			 *
124127bfbee1SPeter Avalos 			 * We ignore zero-length rates IEs as some
124227bfbee1SPeter Avalos 			 * devices seem to put a zero-length rates
124327bfbee1SPeter Avalos 			 * IE, followed by an SSID IE, followed by
124427bfbee1SPeter Avalos 			 * a non-zero-length rates IE into frames,
124527bfbee1SPeter Avalos 			 * even though IEEE Std 802.11-2007 doesn't
124627bfbee1SPeter Avalos 			 * seem to indicate that a zero-length rates
124727bfbee1SPeter Avalos 			 * IE is valid.
124827bfbee1SPeter Avalos 			 */
124927bfbee1SPeter Avalos 			if (!pbody->rates_present && rates.length != 0) {
125027bfbee1SPeter Avalos 				pbody->rates = rates;
125127bfbee1SPeter Avalos 				pbody->rates_present = 1;
125227bfbee1SPeter Avalos 			}
125341c99275SPeter Avalos 			break;
125441c99275SPeter Avalos 		case E_DS:
1255411677aeSAaron LI 			memcpy(&ds, p + offset, 2);
1256411677aeSAaron LI 			offset += 2;
1257411677aeSAaron LI 			length -= 2;
1258411677aeSAaron LI 			if (ds.length != 1) {
1259411677aeSAaron LI 				offset += ds.length;
1260411677aeSAaron LI 				length -= ds.length;
1261411677aeSAaron LI 				break;
1262411677aeSAaron LI 			}
1263*ed775ee7SAntonio Huete Jimenez 			ds.channel = GET_U_1(p + offset);
1264411677aeSAaron LI 			offset += 1;
1265411677aeSAaron LI 			length -= 1;
126627bfbee1SPeter Avalos 			/*
126727bfbee1SPeter Avalos 			 * Present and not truncated.
126827bfbee1SPeter Avalos 			 *
126927bfbee1SPeter Avalos 			 * If we haven't already seen a DS IE,
127027bfbee1SPeter Avalos 			 * copy this one, otherwise ignore this one,
127127bfbee1SPeter Avalos 			 * so we later report the first one we saw.
127227bfbee1SPeter Avalos 			 */
127327bfbee1SPeter Avalos 			if (!pbody->ds_present) {
127427bfbee1SPeter Avalos 				pbody->ds = ds;
127527bfbee1SPeter Avalos 				pbody->ds_present = 1;
127627bfbee1SPeter Avalos 			}
127741c99275SPeter Avalos 			break;
127841c99275SPeter Avalos 		case E_CF:
1279411677aeSAaron LI 			memcpy(&cf, p + offset, 2);
1280411677aeSAaron LI 			offset += 2;
1281411677aeSAaron LI 			length -= 2;
1282411677aeSAaron LI 			if (cf.length != 6) {
1283411677aeSAaron LI 				offset += cf.length;
1284411677aeSAaron LI 				length -= cf.length;
1285411677aeSAaron LI 				break;
1286411677aeSAaron LI 			}
1287411677aeSAaron LI 			memcpy(&cf.count, p + offset, 6);
1288411677aeSAaron LI 			offset += 6;
1289411677aeSAaron LI 			length -= 6;
129027bfbee1SPeter Avalos 			/*
129127bfbee1SPeter Avalos 			 * Present and not truncated.
129227bfbee1SPeter Avalos 			 *
129327bfbee1SPeter Avalos 			 * If we haven't already seen a CF IE,
129427bfbee1SPeter Avalos 			 * copy this one, otherwise ignore this one,
129527bfbee1SPeter Avalos 			 * so we later report the first one we saw.
129627bfbee1SPeter Avalos 			 */
129727bfbee1SPeter Avalos 			if (!pbody->cf_present) {
129827bfbee1SPeter Avalos 				pbody->cf = cf;
129927bfbee1SPeter Avalos 				pbody->cf_present = 1;
130027bfbee1SPeter Avalos 			}
130141c99275SPeter Avalos 			break;
130241c99275SPeter Avalos 		case E_TIM:
130327bfbee1SPeter Avalos 			memcpy(&tim, p + offset, 2);
130441c99275SPeter Avalos 			offset += 2;
130527bfbee1SPeter Avalos 			length -= 2;
1306*ed775ee7SAntonio Huete Jimenez 			if (tim.length <= 3U) {
1307411677aeSAaron LI 				offset += tim.length;
1308411677aeSAaron LI 				length -= tim.length;
1309411677aeSAaron LI 				break;
1310411677aeSAaron LI 			}
1311*ed775ee7SAntonio Huete Jimenez 			if (tim.length - 3U > sizeof(tim.bitmap))
131227bfbee1SPeter Avalos 				return 0;
131327bfbee1SPeter Avalos 			memcpy(&tim.count, p + offset, 3);
131441c99275SPeter Avalos 			offset += 3;
131527bfbee1SPeter Avalos 			length -= 3;
131641c99275SPeter Avalos 
1317411677aeSAaron LI 			memcpy(tim.bitmap, p + offset, tim.length - 3);
131827bfbee1SPeter Avalos 			offset += tim.length - 3;
131927bfbee1SPeter Avalos 			length -= tim.length - 3;
132027bfbee1SPeter Avalos 			/*
132127bfbee1SPeter Avalos 			 * Present and not truncated.
132227bfbee1SPeter Avalos 			 *
132327bfbee1SPeter Avalos 			 * If we haven't already seen a TIM IE,
132427bfbee1SPeter Avalos 			 * copy this one, otherwise ignore this one,
132527bfbee1SPeter Avalos 			 * so we later report the first one we saw.
132627bfbee1SPeter Avalos 			 */
132727bfbee1SPeter Avalos 			if (!pbody->tim_present) {
132827bfbee1SPeter Avalos 				pbody->tim = tim;
132927bfbee1SPeter Avalos 				pbody->tim_present = 1;
133027bfbee1SPeter Avalos 			}
133141c99275SPeter Avalos 			break;
133241c99275SPeter Avalos 		default:
133341c99275SPeter Avalos #if 0
1334*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("(1) unhandled element_id (%u)  ",
1335*ed775ee7SAntonio Huete Jimenez 			    GET_U_1(p + offset));
133641c99275SPeter Avalos #endif
1337411677aeSAaron LI 			offset += 2 + elementlen;
1338411677aeSAaron LI 			length -= 2 + elementlen;
133941c99275SPeter Avalos 			break;
134041c99275SPeter Avalos 		}
134141c99275SPeter Avalos 	}
134227bfbee1SPeter Avalos 
134327bfbee1SPeter Avalos 	/* No problems found. */
134427bfbee1SPeter Avalos 	return 1;
1345*ed775ee7SAntonio Huete Jimenez trunc:
1346*ed775ee7SAntonio Huete Jimenez 	return 0;
134741c99275SPeter Avalos }
134841c99275SPeter Avalos 
134941c99275SPeter Avalos /*********************************************************************************
135041c99275SPeter Avalos  * Print Handle functions for the management frame types
135141c99275SPeter Avalos  *********************************************************************************/
135241c99275SPeter Avalos 
135341c99275SPeter Avalos static int
handle_beacon(netdissect_options * ndo,const u_char * p,u_int length)1354411677aeSAaron LI handle_beacon(netdissect_options *ndo,
1355411677aeSAaron LI 	      const u_char *p, u_int length)
135641c99275SPeter Avalos {
135741c99275SPeter Avalos 	struct mgmt_body_t pbody;
135841c99275SPeter Avalos 	int offset = 0;
135927bfbee1SPeter Avalos 	int ret;
136041c99275SPeter Avalos 
136141c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
136241c99275SPeter Avalos 
1363*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1364*ed775ee7SAntonio Huete Jimenez 		      IEEE802_11_CAPINFO_LEN);
136527bfbee1SPeter Avalos 	if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
136627bfbee1SPeter Avalos 	    IEEE802_11_CAPINFO_LEN)
1367*ed775ee7SAntonio Huete Jimenez 		goto trunc;
136841c99275SPeter Avalos 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
136941c99275SPeter Avalos 	offset += IEEE802_11_TSTAMP_LEN;
137027bfbee1SPeter Avalos 	length -= IEEE802_11_TSTAMP_LEN;
1371*ed775ee7SAntonio Huete Jimenez 	pbody.beacon_interval = GET_LE_U_2(p + offset);
137241c99275SPeter Avalos 	offset += IEEE802_11_BCNINT_LEN;
137327bfbee1SPeter Avalos 	length -= IEEE802_11_BCNINT_LEN;
1374*ed775ee7SAntonio Huete Jimenez 	pbody.capability_info = GET_LE_U_2(p + offset);
137541c99275SPeter Avalos 	offset += IEEE802_11_CAPINFO_LEN;
137627bfbee1SPeter Avalos 	length -= IEEE802_11_CAPINFO_LEN;
137741c99275SPeter Avalos 
1378411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
137941c99275SPeter Avalos 
138041c99275SPeter Avalos 	PRINT_SSID(pbody);
138141c99275SPeter Avalos 	PRINT_RATES(pbody);
1382*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" %s",
1383*ed775ee7SAntonio Huete Jimenez 	    CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
138441c99275SPeter Avalos 	PRINT_DS_CHANNEL(pbody);
138541c99275SPeter Avalos 
138627bfbee1SPeter Avalos 	return ret;
1387*ed775ee7SAntonio Huete Jimenez trunc:
1388*ed775ee7SAntonio Huete Jimenez 	return 0;
138941c99275SPeter Avalos }
139041c99275SPeter Avalos 
139141c99275SPeter Avalos static int
handle_assoc_request(netdissect_options * ndo,const u_char * p,u_int length)1392411677aeSAaron LI handle_assoc_request(netdissect_options *ndo,
1393411677aeSAaron LI 		     const u_char *p, u_int length)
139441c99275SPeter Avalos {
139541c99275SPeter Avalos 	struct mgmt_body_t pbody;
139641c99275SPeter Avalos 	int offset = 0;
139727bfbee1SPeter Avalos 	int ret;
139841c99275SPeter Avalos 
139941c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
140041c99275SPeter Avalos 
1401*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
140227bfbee1SPeter Avalos 	if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
1403*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1404*ed775ee7SAntonio Huete Jimenez 	pbody.capability_info = GET_LE_U_2(p);
140541c99275SPeter Avalos 	offset += IEEE802_11_CAPINFO_LEN;
140627bfbee1SPeter Avalos 	length -= IEEE802_11_CAPINFO_LEN;
1407*ed775ee7SAntonio Huete Jimenez 	pbody.listen_interval = GET_LE_U_2(p + offset);
140841c99275SPeter Avalos 	offset += IEEE802_11_LISTENINT_LEN;
140927bfbee1SPeter Avalos 	length -= IEEE802_11_LISTENINT_LEN;
141041c99275SPeter Avalos 
1411411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
141241c99275SPeter Avalos 
141341c99275SPeter Avalos 	PRINT_SSID(pbody);
141441c99275SPeter Avalos 	PRINT_RATES(pbody);
141527bfbee1SPeter Avalos 	return ret;
1416*ed775ee7SAntonio Huete Jimenez trunc:
1417*ed775ee7SAntonio Huete Jimenez 	return 0;
141841c99275SPeter Avalos }
141941c99275SPeter Avalos 
142041c99275SPeter Avalos static int
handle_assoc_response(netdissect_options * ndo,const u_char * p,u_int length)1421411677aeSAaron LI handle_assoc_response(netdissect_options *ndo,
1422411677aeSAaron LI 		      const u_char *p, u_int length)
142341c99275SPeter Avalos {
142441c99275SPeter Avalos 	struct mgmt_body_t pbody;
142541c99275SPeter Avalos 	int offset = 0;
142627bfbee1SPeter Avalos 	int ret;
142741c99275SPeter Avalos 
142841c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
142941c99275SPeter Avalos 
1430*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1431*ed775ee7SAntonio Huete Jimenez 		      IEEE802_11_AID_LEN);
143227bfbee1SPeter Avalos 	if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
143327bfbee1SPeter Avalos 	    IEEE802_11_AID_LEN)
1434*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1435*ed775ee7SAntonio Huete Jimenez 	pbody.capability_info = GET_LE_U_2(p);
143641c99275SPeter Avalos 	offset += IEEE802_11_CAPINFO_LEN;
143727bfbee1SPeter Avalos 	length -= IEEE802_11_CAPINFO_LEN;
1438*ed775ee7SAntonio Huete Jimenez 	pbody.status_code = GET_LE_U_2(p + offset);
143941c99275SPeter Avalos 	offset += IEEE802_11_STATUS_LEN;
144027bfbee1SPeter Avalos 	length -= IEEE802_11_STATUS_LEN;
1441*ed775ee7SAntonio Huete Jimenez 	pbody.aid = GET_LE_U_2(p + offset);
144241c99275SPeter Avalos 	offset += IEEE802_11_AID_LEN;
144327bfbee1SPeter Avalos 	length -= IEEE802_11_AID_LEN;
144441c99275SPeter Avalos 
1445411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
144641c99275SPeter Avalos 
1447*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
144841c99275SPeter Avalos 	    CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
144941c99275SPeter Avalos 	    (pbody.status_code < NUM_STATUSES
145041c99275SPeter Avalos 		? status_text[pbody.status_code]
1451*ed775ee7SAntonio Huete Jimenez 		: "n/a"));
145241c99275SPeter Avalos 
145327bfbee1SPeter Avalos 	return ret;
1454*ed775ee7SAntonio Huete Jimenez trunc:
1455*ed775ee7SAntonio Huete Jimenez 	return 0;
145641c99275SPeter Avalos }
145741c99275SPeter Avalos 
145841c99275SPeter Avalos static int
handle_reassoc_request(netdissect_options * ndo,const u_char * p,u_int length)1459411677aeSAaron LI handle_reassoc_request(netdissect_options *ndo,
1460411677aeSAaron LI 		       const u_char *p, u_int length)
146141c99275SPeter Avalos {
146241c99275SPeter Avalos 	struct mgmt_body_t pbody;
146341c99275SPeter Avalos 	int offset = 0;
146427bfbee1SPeter Avalos 	int ret;
146541c99275SPeter Avalos 
146641c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
146741c99275SPeter Avalos 
1468*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1469*ed775ee7SAntonio Huete Jimenez 		      IEEE802_11_AP_LEN);
147027bfbee1SPeter Avalos 	if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
147127bfbee1SPeter Avalos 	    IEEE802_11_AP_LEN)
1472*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1473*ed775ee7SAntonio Huete Jimenez 	pbody.capability_info = GET_LE_U_2(p);
147441c99275SPeter Avalos 	offset += IEEE802_11_CAPINFO_LEN;
147527bfbee1SPeter Avalos 	length -= IEEE802_11_CAPINFO_LEN;
1476*ed775ee7SAntonio Huete Jimenez 	pbody.listen_interval = GET_LE_U_2(p + offset);
147741c99275SPeter Avalos 	offset += IEEE802_11_LISTENINT_LEN;
147827bfbee1SPeter Avalos 	length -= IEEE802_11_LISTENINT_LEN;
147941c99275SPeter Avalos 	memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
148041c99275SPeter Avalos 	offset += IEEE802_11_AP_LEN;
148127bfbee1SPeter Avalos 	length -= IEEE802_11_AP_LEN;
148241c99275SPeter Avalos 
1483411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
148441c99275SPeter Avalos 
148541c99275SPeter Avalos 	PRINT_SSID(pbody);
1486*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" AP : %s", etheraddr_string(ndo,  pbody.ap ));
148741c99275SPeter Avalos 
148827bfbee1SPeter Avalos 	return ret;
1489*ed775ee7SAntonio Huete Jimenez trunc:
1490*ed775ee7SAntonio Huete Jimenez 	return 0;
149141c99275SPeter Avalos }
149241c99275SPeter Avalos 
149341c99275SPeter Avalos static int
handle_reassoc_response(netdissect_options * ndo,const u_char * p,u_int length)1494411677aeSAaron LI handle_reassoc_response(netdissect_options *ndo,
1495411677aeSAaron LI 			const u_char *p, u_int length)
149641c99275SPeter Avalos {
1497*ed775ee7SAntonio Huete Jimenez 	/* Same as a Association Response */
1498411677aeSAaron LI 	return handle_assoc_response(ndo, p, length);
149941c99275SPeter Avalos }
150041c99275SPeter Avalos 
150141c99275SPeter Avalos static int
handle_probe_request(netdissect_options * ndo,const u_char * p,u_int length)1502411677aeSAaron LI handle_probe_request(netdissect_options *ndo,
1503411677aeSAaron LI 		     const u_char *p, u_int length)
150441c99275SPeter Avalos {
150541c99275SPeter Avalos 	struct mgmt_body_t  pbody;
150641c99275SPeter Avalos 	int offset = 0;
150727bfbee1SPeter Avalos 	int ret;
150841c99275SPeter Avalos 
150941c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
151041c99275SPeter Avalos 
1511411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
151241c99275SPeter Avalos 
151341c99275SPeter Avalos 	PRINT_SSID(pbody);
151441c99275SPeter Avalos 	PRINT_RATES(pbody);
151541c99275SPeter Avalos 
151627bfbee1SPeter Avalos 	return ret;
151741c99275SPeter Avalos }
151841c99275SPeter Avalos 
151941c99275SPeter Avalos static int
handle_probe_response(netdissect_options * ndo,const u_char * p,u_int length)1520411677aeSAaron LI handle_probe_response(netdissect_options *ndo,
1521411677aeSAaron LI 		      const u_char *p, u_int length)
152241c99275SPeter Avalos {
152341c99275SPeter Avalos 	struct mgmt_body_t  pbody;
152441c99275SPeter Avalos 	int offset = 0;
152527bfbee1SPeter Avalos 	int ret;
152641c99275SPeter Avalos 
152741c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
152841c99275SPeter Avalos 
1529*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1530*ed775ee7SAntonio Huete Jimenez 		      IEEE802_11_CAPINFO_LEN);
153127bfbee1SPeter Avalos 	if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
153227bfbee1SPeter Avalos 	    IEEE802_11_CAPINFO_LEN)
1533*ed775ee7SAntonio Huete Jimenez 		goto trunc;
153441c99275SPeter Avalos 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
153541c99275SPeter Avalos 	offset += IEEE802_11_TSTAMP_LEN;
153627bfbee1SPeter Avalos 	length -= IEEE802_11_TSTAMP_LEN;
1537*ed775ee7SAntonio Huete Jimenez 	pbody.beacon_interval = GET_LE_U_2(p + offset);
153841c99275SPeter Avalos 	offset += IEEE802_11_BCNINT_LEN;
153927bfbee1SPeter Avalos 	length -= IEEE802_11_BCNINT_LEN;
1540*ed775ee7SAntonio Huete Jimenez 	pbody.capability_info = GET_LE_U_2(p + offset);
154141c99275SPeter Avalos 	offset += IEEE802_11_CAPINFO_LEN;
154227bfbee1SPeter Avalos 	length -= IEEE802_11_CAPINFO_LEN;
154341c99275SPeter Avalos 
1544411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
154541c99275SPeter Avalos 
154641c99275SPeter Avalos 	PRINT_SSID(pbody);
154741c99275SPeter Avalos 	PRINT_RATES(pbody);
154841c99275SPeter Avalos 	PRINT_DS_CHANNEL(pbody);
154941c99275SPeter Avalos 
155027bfbee1SPeter Avalos 	return ret;
1551*ed775ee7SAntonio Huete Jimenez trunc:
1552*ed775ee7SAntonio Huete Jimenez 	return 0;
155341c99275SPeter Avalos }
155441c99275SPeter Avalos 
155541c99275SPeter Avalos static int
handle_atim(void)155641c99275SPeter Avalos handle_atim(void)
155741c99275SPeter Avalos {
155841c99275SPeter Avalos 	/* the frame body for ATIM is null. */
155941c99275SPeter Avalos 	return 1;
156041c99275SPeter Avalos }
156141c99275SPeter Avalos 
156241c99275SPeter Avalos static int
handle_disassoc(netdissect_options * ndo,const u_char * p,u_int length)1563411677aeSAaron LI handle_disassoc(netdissect_options *ndo,
1564411677aeSAaron LI 		const u_char *p, u_int length)
156541c99275SPeter Avalos {
156641c99275SPeter Avalos 	struct mgmt_body_t  pbody;
156741c99275SPeter Avalos 
156841c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
156941c99275SPeter Avalos 
1570*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
157127bfbee1SPeter Avalos 	if (length < IEEE802_11_REASON_LEN)
1572*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1573*ed775ee7SAntonio Huete Jimenez 	pbody.reason_code = GET_LE_U_2(p);
157441c99275SPeter Avalos 
1575*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(": %s",
157641c99275SPeter Avalos 	    (pbody.reason_code < NUM_REASONS)
157741c99275SPeter Avalos 		? reason_text[pbody.reason_code]
1578*ed775ee7SAntonio Huete Jimenez 		: "Reserved");
157941c99275SPeter Avalos 
158041c99275SPeter Avalos 	return 1;
1581*ed775ee7SAntonio Huete Jimenez trunc:
1582*ed775ee7SAntonio Huete Jimenez 	return 0;
158341c99275SPeter Avalos }
158441c99275SPeter Avalos 
158541c99275SPeter Avalos static int
handle_auth(netdissect_options * ndo,const u_char * p,u_int length)1586411677aeSAaron LI handle_auth(netdissect_options *ndo,
1587411677aeSAaron LI 	    const u_char *p, u_int length)
158841c99275SPeter Avalos {
158941c99275SPeter Avalos 	struct mgmt_body_t  pbody;
159041c99275SPeter Avalos 	int offset = 0;
159127bfbee1SPeter Avalos 	int ret;
159241c99275SPeter Avalos 
159341c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
159441c99275SPeter Avalos 
1595*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_6(p);
159627bfbee1SPeter Avalos 	if (length < 6)
1597*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1598*ed775ee7SAntonio Huete Jimenez 	pbody.auth_alg = GET_LE_U_2(p);
159941c99275SPeter Avalos 	offset += 2;
160027bfbee1SPeter Avalos 	length -= 2;
1601*ed775ee7SAntonio Huete Jimenez 	pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
160241c99275SPeter Avalos 	offset += 2;
160327bfbee1SPeter Avalos 	length -= 2;
1604*ed775ee7SAntonio Huete Jimenez 	pbody.status_code = GET_LE_U_2(p + offset);
160541c99275SPeter Avalos 	offset += 2;
160627bfbee1SPeter Avalos 	length -= 2;
160741c99275SPeter Avalos 
1608411677aeSAaron LI 	ret = parse_elements(ndo, &pbody, p, offset, length);
160941c99275SPeter Avalos 
161041c99275SPeter Avalos 	if ((pbody.auth_alg == 1) &&
161141c99275SPeter Avalos 	    ((pbody.auth_trans_seq_num == 2) ||
161241c99275SPeter Avalos 	     (pbody.auth_trans_seq_num == 3))) {
1613*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" (%s)-%x [Challenge Text] %s",
161441c99275SPeter Avalos 		    (pbody.auth_alg < NUM_AUTH_ALGS)
161541c99275SPeter Avalos 			? auth_alg_text[pbody.auth_alg]
161641c99275SPeter Avalos 			: "Reserved",
161741c99275SPeter Avalos 		    pbody.auth_trans_seq_num,
161841c99275SPeter Avalos 		    ((pbody.auth_trans_seq_num % 2)
161941c99275SPeter Avalos 			? ((pbody.status_code < NUM_STATUSES)
162041c99275SPeter Avalos 			       ? status_text[pbody.status_code]
1621*ed775ee7SAntonio Huete Jimenez 			       : "n/a") : ""));
162227bfbee1SPeter Avalos 		return ret;
162341c99275SPeter Avalos 	}
1624*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" (%s)-%x: %s",
162541c99275SPeter Avalos 	    (pbody.auth_alg < NUM_AUTH_ALGS)
162641c99275SPeter Avalos 		? auth_alg_text[pbody.auth_alg]
162741c99275SPeter Avalos 		: "Reserved",
162841c99275SPeter Avalos 	    pbody.auth_trans_seq_num,
162941c99275SPeter Avalos 	    (pbody.auth_trans_seq_num % 2)
163041c99275SPeter Avalos 		? ((pbody.status_code < NUM_STATUSES)
163141c99275SPeter Avalos 		    ? status_text[pbody.status_code]
163241c99275SPeter Avalos 		    : "n/a")
1633*ed775ee7SAntonio Huete Jimenez 		: "");
163441c99275SPeter Avalos 
163527bfbee1SPeter Avalos 	return ret;
1636*ed775ee7SAntonio Huete Jimenez trunc:
1637*ed775ee7SAntonio Huete Jimenez 	return 0;
163841c99275SPeter Avalos }
163941c99275SPeter Avalos 
164041c99275SPeter Avalos static int
handle_deauth(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)1641411677aeSAaron LI handle_deauth(netdissect_options *ndo,
1642411677aeSAaron LI 	      const uint8_t *src, const u_char *p, u_int length)
164341c99275SPeter Avalos {
164441c99275SPeter Avalos 	struct mgmt_body_t  pbody;
164541c99275SPeter Avalos 	const char *reason = NULL;
164641c99275SPeter Avalos 
164741c99275SPeter Avalos 	memset(&pbody, 0, sizeof(pbody));
164841c99275SPeter Avalos 
1649*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
165027bfbee1SPeter Avalos 	if (length < IEEE802_11_REASON_LEN)
1651*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1652*ed775ee7SAntonio Huete Jimenez 	pbody.reason_code = GET_LE_U_2(p);
165341c99275SPeter Avalos 
165441c99275SPeter Avalos 	reason = (pbody.reason_code < NUM_REASONS)
165541c99275SPeter Avalos 			? reason_text[pbody.reason_code]
165641c99275SPeter Avalos 			: "Reserved";
165741c99275SPeter Avalos 
1658411677aeSAaron LI 	if (ndo->ndo_eflag) {
1659*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(": %s", reason);
166041c99275SPeter Avalos 	} else {
1661*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
166241c99275SPeter Avalos 	}
166341c99275SPeter Avalos 	return 1;
1664*ed775ee7SAntonio Huete Jimenez trunc:
1665*ed775ee7SAntonio Huete Jimenez 	return 0;
166641c99275SPeter Avalos }
166741c99275SPeter Avalos 
166827bfbee1SPeter Avalos #define	PRINT_HT_ACTION(v) (\
1669*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("TxChWidth"): \
1670*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("MIMOPwrSave"): \
1671*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
167227bfbee1SPeter Avalos #define	PRINT_BA_ACTION(v) (\
1673*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("ADDBA Request"): \
1674*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("ADDBA Response"): \
1675*ed775ee7SAntonio Huete Jimenez 	(v) == 2 ? ND_PRINT("DELBA"): \
1676*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
167727bfbee1SPeter Avalos #define	PRINT_MESHLINK_ACTION(v) (\
1678*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("Request"): \
1679*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("Report"): \
1680*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
168127bfbee1SPeter Avalos #define	PRINT_MESHPEERING_ACTION(v) (\
1682*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("Open"): \
1683*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("Confirm"): \
1684*ed775ee7SAntonio Huete Jimenez 	(v) == 2 ? ND_PRINT("Close"): \
1685*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
168627bfbee1SPeter Avalos #define	PRINT_MESHPATH_ACTION(v) (\
1687*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("Request"): \
1688*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("Report"): \
1689*ed775ee7SAntonio Huete Jimenez 	(v) == 2 ? ND_PRINT("Error"): \
1690*ed775ee7SAntonio Huete Jimenez 	(v) == 3 ? ND_PRINT("RootAnnouncement"): \
1691*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
1692411677aeSAaron LI 
1693411677aeSAaron LI #define PRINT_MESH_ACTION(v) (\
1694*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("MeshLink"): \
1695*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("HWMP"): \
1696*ed775ee7SAntonio Huete Jimenez 	(v) == 2 ? ND_PRINT("Gate Announcement"): \
1697*ed775ee7SAntonio Huete Jimenez 	(v) == 3 ? ND_PRINT("Congestion Control"): \
1698*ed775ee7SAntonio Huete Jimenez 	(v) == 4 ? ND_PRINT("MCCA Setup Request"): \
1699*ed775ee7SAntonio Huete Jimenez 	(v) == 5 ? ND_PRINT("MCCA Setup Reply"): \
1700*ed775ee7SAntonio Huete Jimenez 	(v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \
1701*ed775ee7SAntonio Huete Jimenez 	(v) == 7 ? ND_PRINT("MCCA Advertisement"): \
1702*ed775ee7SAntonio Huete Jimenez 	(v) == 8 ? ND_PRINT("MCCA Teardown"): \
1703*ed775ee7SAntonio Huete Jimenez 	(v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \
1704*ed775ee7SAntonio Huete Jimenez 	(v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \
1705*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
1706411677aeSAaron LI #define PRINT_MULTIHOP_ACTION(v) (\
1707*ed775ee7SAntonio Huete Jimenez 	(v) == 0 ? ND_PRINT("Proxy Update"): \
1708*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \
1709*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
1710411677aeSAaron LI #define PRINT_SELFPROT_ACTION(v) (\
1711*ed775ee7SAntonio Huete Jimenez 	(v) == 1 ? ND_PRINT("Peering Open"): \
1712*ed775ee7SAntonio Huete Jimenez 	(v) == 2 ? ND_PRINT("Peering Confirm"): \
1713*ed775ee7SAntonio Huete Jimenez 	(v) == 3 ? ND_PRINT("Peering Close"): \
1714*ed775ee7SAntonio Huete Jimenez 	(v) == 4 ? ND_PRINT("Group Key Inform"): \
1715*ed775ee7SAntonio Huete Jimenez 	(v) == 5 ? ND_PRINT("Group Key Acknowledge"): \
1716*ed775ee7SAntonio Huete Jimenez 		   ND_PRINT("Act#%u", (v)))
171727bfbee1SPeter Avalos 
171827bfbee1SPeter Avalos static int
handle_action(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)1719411677aeSAaron LI handle_action(netdissect_options *ndo,
1720411677aeSAaron LI 	      const uint8_t *src, const u_char *p, u_int length)
172127bfbee1SPeter Avalos {
1722*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_2(p);
172327bfbee1SPeter Avalos 	if (length < 2)
1724*ed775ee7SAntonio Huete Jimenez 		goto trunc;
1725411677aeSAaron LI 	if (ndo->ndo_eflag) {
1726*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(": ");
172727bfbee1SPeter Avalos 	} else {
1728*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
172927bfbee1SPeter Avalos 	}
1730*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(p)) {
1731*ed775ee7SAntonio Huete Jimenez 	case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break;
1732*ed775ee7SAntonio Huete Jimenez 	case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break;
1733*ed775ee7SAntonio Huete Jimenez 	case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break;
1734*ed775ee7SAntonio Huete Jimenez 	case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break;
1735*ed775ee7SAntonio Huete Jimenez 	case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break;
1736*ed775ee7SAntonio Huete Jimenez 	case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break;
1737411677aeSAaron LI 	case 14:
1738*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("MultiohopAction ");
1739*ed775ee7SAntonio Huete Jimenez 		PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break;
1740411677aeSAaron LI 	case 15:
1741*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("SelfprotectAction ");
1742*ed775ee7SAntonio Huete Jimenez 		PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break;
1743*ed775ee7SAntonio Huete Jimenez 	case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break;
174427bfbee1SPeter Avalos 	default:
1745*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1));
174627bfbee1SPeter Avalos 		break;
174727bfbee1SPeter Avalos 	}
174827bfbee1SPeter Avalos 	return 1;
1749*ed775ee7SAntonio Huete Jimenez trunc:
1750*ed775ee7SAntonio Huete Jimenez 	return 0;
175127bfbee1SPeter Avalos }
175227bfbee1SPeter Avalos 
175341c99275SPeter Avalos 
175441c99275SPeter Avalos /*********************************************************************************
175541c99275SPeter Avalos  * Print Body funcs
175641c99275SPeter Avalos  *********************************************************************************/
175741c99275SPeter Avalos 
175841c99275SPeter Avalos 
175941c99275SPeter Avalos static int
mgmt_body_print(netdissect_options * ndo,uint16_t fc,const uint8_t * src,const u_char * p,u_int length)1760411677aeSAaron LI mgmt_body_print(netdissect_options *ndo,
1761411677aeSAaron LI 		uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
176241c99275SPeter Avalos {
1763*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
1764411677aeSAaron LI 
1765411677aeSAaron LI 	/* There may be a problem w/ AP not having this bit set */
1766411677aeSAaron LI 	if (FC_PROTECTED(fc))
1767411677aeSAaron LI 		return wep_print(ndo, p);
176841c99275SPeter Avalos 	switch (FC_SUBTYPE(fc)) {
176941c99275SPeter Avalos 	case ST_ASSOC_REQUEST:
1770411677aeSAaron LI 		return handle_assoc_request(ndo, p, length);
177141c99275SPeter Avalos 	case ST_ASSOC_RESPONSE:
1772411677aeSAaron LI 		return handle_assoc_response(ndo, p, length);
177341c99275SPeter Avalos 	case ST_REASSOC_REQUEST:
1774411677aeSAaron LI 		return handle_reassoc_request(ndo, p, length);
177541c99275SPeter Avalos 	case ST_REASSOC_RESPONSE:
1776411677aeSAaron LI 		return handle_reassoc_response(ndo, p, length);
177741c99275SPeter Avalos 	case ST_PROBE_REQUEST:
1778411677aeSAaron LI 		return handle_probe_request(ndo, p, length);
177941c99275SPeter Avalos 	case ST_PROBE_RESPONSE:
1780411677aeSAaron LI 		return handle_probe_response(ndo, p, length);
178141c99275SPeter Avalos 	case ST_BEACON:
1782411677aeSAaron LI 		return handle_beacon(ndo, p, length);
178341c99275SPeter Avalos 	case ST_ATIM:
178441c99275SPeter Avalos 		return handle_atim();
178541c99275SPeter Avalos 	case ST_DISASSOC:
1786411677aeSAaron LI 		return handle_disassoc(ndo, p, length);
178741c99275SPeter Avalos 	case ST_AUTH:
1788411677aeSAaron LI 		return handle_auth(ndo, p, length);
178941c99275SPeter Avalos 	case ST_DEAUTH:
1790411677aeSAaron LI 		return handle_deauth(ndo, src, p, length);
179127bfbee1SPeter Avalos 	case ST_ACTION:
1792411677aeSAaron LI 		return handle_action(ndo, src, p, length);
179341c99275SPeter Avalos 	default:
179441c99275SPeter Avalos 		return 1;
179541c99275SPeter Avalos 	}
179641c99275SPeter Avalos }
179741c99275SPeter Avalos 
179841c99275SPeter Avalos 
179941c99275SPeter Avalos /*********************************************************************************
180041c99275SPeter Avalos  * Handles printing all the control frame types
180141c99275SPeter Avalos  *********************************************************************************/
180241c99275SPeter Avalos 
180341c99275SPeter Avalos static int
ctrl_body_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1804411677aeSAaron LI ctrl_body_print(netdissect_options *ndo,
1805411677aeSAaron LI 		uint16_t fc, const u_char *p)
180641c99275SPeter Avalos {
1807*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
180841c99275SPeter Avalos 	switch (FC_SUBTYPE(fc)) {
180927bfbee1SPeter Avalos 	case CTRL_CONTROL_WRAPPER:
181027bfbee1SPeter Avalos 		/* XXX - requires special handling */
181127bfbee1SPeter Avalos 		break;
181227bfbee1SPeter Avalos 	case CTRL_BAR:
1813*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
1814411677aeSAaron LI 		if (!ndo->ndo_eflag)
1815*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1816*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
1817*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
1818*ed775ee7SAntonio Huete Jimenez 			    GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
1819*ed775ee7SAntonio Huete Jimenez 			    GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
182027bfbee1SPeter Avalos 		break;
182127bfbee1SPeter Avalos 	case CTRL_BA:
1822*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
1823411677aeSAaron LI 		if (!ndo->ndo_eflag)
1824*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" RA:%s ",
1825*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
182627bfbee1SPeter Avalos 		break;
182741c99275SPeter Avalos 	case CTRL_PS_POLL:
1828*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
1829*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" AID(%x)",
1830*ed775ee7SAntonio Huete Jimenez 		    GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
183141c99275SPeter Avalos 		break;
183241c99275SPeter Avalos 	case CTRL_RTS:
1833*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
1834411677aeSAaron LI 		if (!ndo->ndo_eflag)
1835*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" TA:%s ",
1836*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
183741c99275SPeter Avalos 		break;
183841c99275SPeter Avalos 	case CTRL_CTS:
1839*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
1840411677aeSAaron LI 		if (!ndo->ndo_eflag)
1841*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" RA:%s ",
1842*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
184341c99275SPeter Avalos 		break;
184441c99275SPeter Avalos 	case CTRL_ACK:
1845*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
1846411677aeSAaron LI 		if (!ndo->ndo_eflag)
1847*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" RA:%s ",
1848*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
184941c99275SPeter Avalos 		break;
185041c99275SPeter Avalos 	case CTRL_CF_END:
1851*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
1852411677aeSAaron LI 		if (!ndo->ndo_eflag)
1853*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" RA:%s ",
1854*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
185541c99275SPeter Avalos 		break;
185641c99275SPeter Avalos 	case CTRL_END_ACK:
1857*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
1858411677aeSAaron LI 		if (!ndo->ndo_eflag)
1859*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" RA:%s ",
1860*ed775ee7SAntonio Huete Jimenez 			    GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
186141c99275SPeter Avalos 		break;
186241c99275SPeter Avalos 	}
186341c99275SPeter Avalos 	return 1;
1864*ed775ee7SAntonio Huete Jimenez trunc:
1865*ed775ee7SAntonio Huete Jimenez 	return 0;
186641c99275SPeter Avalos }
186741c99275SPeter Avalos 
186841c99275SPeter Avalos /*
186941c99275SPeter Avalos  *  Data Frame - Address field contents
187041c99275SPeter Avalos  *
187141c99275SPeter Avalos  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
187241c99275SPeter Avalos  *    0    |  0      |  DA    | SA     | BSSID  | n/a
187341c99275SPeter Avalos  *    0    |  1      |  DA    | BSSID  | SA     | n/a
187441c99275SPeter Avalos  *    1    |  0      |  BSSID | SA     | DA     | n/a
187541c99275SPeter Avalos  *    1    |  1      |  RA    | TA     | DA     | SA
187641c99275SPeter Avalos  */
187741c99275SPeter Avalos 
1878411677aeSAaron LI /*
1879411677aeSAaron LI  * Function to get source and destination MAC addresses for a data frame.
1880411677aeSAaron LI  */
188141c99275SPeter Avalos static void
get_data_src_dst_mac(uint16_t fc,const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)1882411677aeSAaron LI get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
1883411677aeSAaron LI 		     const uint8_t **dstp)
188441c99275SPeter Avalos {
188541c99275SPeter Avalos #define ADDR1  (p + 4)
188641c99275SPeter Avalos #define ADDR2  (p + 10)
188741c99275SPeter Avalos #define ADDR3  (p + 16)
188841c99275SPeter Avalos #define ADDR4  (p + 24)
188941c99275SPeter Avalos 
1890411677aeSAaron LI 	if (!FC_TO_DS(fc)) {
1891411677aeSAaron LI 		if (!FC_FROM_DS(fc)) {
1892411677aeSAaron LI 			/* not To DS and not From DS */
189341c99275SPeter Avalos 			*srcp = ADDR2;
189441c99275SPeter Avalos 			*dstp = ADDR1;
1895411677aeSAaron LI 		} else {
1896411677aeSAaron LI 			/* not To DS and From DS */
189741c99275SPeter Avalos 			*srcp = ADDR3;
189841c99275SPeter Avalos 			*dstp = ADDR1;
1899411677aeSAaron LI 		}
1900411677aeSAaron LI 	} else {
1901411677aeSAaron LI 		if (!FC_FROM_DS(fc)) {
1902411677aeSAaron LI 			/* From DS and not To DS */
190341c99275SPeter Avalos 			*srcp = ADDR2;
190441c99275SPeter Avalos 			*dstp = ADDR3;
1905411677aeSAaron LI 		} else {
1906411677aeSAaron LI 			/* To DS and From DS */
190741c99275SPeter Avalos 			*srcp = ADDR4;
190841c99275SPeter Avalos 			*dstp = ADDR3;
1909411677aeSAaron LI 		}
191041c99275SPeter Avalos 	}
191141c99275SPeter Avalos 
191241c99275SPeter Avalos #undef ADDR1
191341c99275SPeter Avalos #undef ADDR2
191441c99275SPeter Avalos #undef ADDR3
191541c99275SPeter Avalos #undef ADDR4
191641c99275SPeter Avalos }
191741c99275SPeter Avalos 
191841c99275SPeter Avalos static void
get_mgmt_src_dst_mac(const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)1919411677aeSAaron LI get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
192041c99275SPeter Avalos {
192141c99275SPeter Avalos 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
192241c99275SPeter Avalos 
192341c99275SPeter Avalos 	if (srcp != NULL)
192441c99275SPeter Avalos 		*srcp = hp->sa;
192541c99275SPeter Avalos 	if (dstp != NULL)
192641c99275SPeter Avalos 		*dstp = hp->da;
1927411677aeSAaron LI }
192841c99275SPeter Avalos 
1929411677aeSAaron LI /*
1930411677aeSAaron LI  * Print Header funcs
1931411677aeSAaron LI  */
1932411677aeSAaron LI 
1933411677aeSAaron LI static void
data_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1934411677aeSAaron LI data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1935411677aeSAaron LI {
1936411677aeSAaron LI 	u_int subtype = FC_SUBTYPE(fc);
1937411677aeSAaron LI 
1938411677aeSAaron LI 	if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
1939411677aeSAaron LI 	    DATA_FRAME_IS_QOS(subtype)) {
1940*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("CF ");
1941411677aeSAaron LI 		if (DATA_FRAME_IS_CF_ACK(subtype)) {
1942411677aeSAaron LI 			if (DATA_FRAME_IS_CF_POLL(subtype))
1943*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("Ack/Poll");
1944411677aeSAaron LI 			else
1945*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("Ack");
1946411677aeSAaron LI 		} else {
1947411677aeSAaron LI 			if (DATA_FRAME_IS_CF_POLL(subtype))
1948*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("Poll");
1949411677aeSAaron LI 		}
1950411677aeSAaron LI 		if (DATA_FRAME_IS_QOS(subtype))
1951*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("+QoS");
1952*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ");
1953411677aeSAaron LI 	}
1954411677aeSAaron LI 
1955411677aeSAaron LI #define ADDR1  (p + 4)
1956411677aeSAaron LI #define ADDR2  (p + 10)
1957411677aeSAaron LI #define ADDR3  (p + 16)
1958411677aeSAaron LI #define ADDR4  (p + 24)
1959411677aeSAaron LI 
1960411677aeSAaron LI 	if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1961*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("DA:%s SA:%s BSSID:%s ",
1962*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1963*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR3));
1964411677aeSAaron LI 	} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1965*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("DA:%s BSSID:%s SA:%s ",
1966*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1967*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR3));
1968411677aeSAaron LI 	} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1969*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("BSSID:%s SA:%s DA:%s ",
1970*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1971*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR3));
1972411677aeSAaron LI 	} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1973*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
1974*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1975*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
1976411677aeSAaron LI 	}
1977411677aeSAaron LI 
1978411677aeSAaron LI #undef ADDR1
1979411677aeSAaron LI #undef ADDR2
1980411677aeSAaron LI #undef ADDR3
1981411677aeSAaron LI #undef ADDR4
198241c99275SPeter Avalos }
198341c99275SPeter Avalos 
198441c99275SPeter Avalos static void
mgmt_header_print(netdissect_options * ndo,const u_char * p)1985411677aeSAaron LI mgmt_header_print(netdissect_options *ndo, const u_char *p)
198641c99275SPeter Avalos {
1987411677aeSAaron LI 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
198841c99275SPeter Avalos 
1989*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("BSSID:%s DA:%s SA:%s ",
1990*ed775ee7SAntonio Huete Jimenez 	    GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
1991*ed775ee7SAntonio Huete Jimenez 	    GET_ETHERADDR_STRING((hp)->sa));
1992411677aeSAaron LI }
1993411677aeSAaron LI 
1994411677aeSAaron LI static void
ctrl_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1995411677aeSAaron LI ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1996411677aeSAaron LI {
199741c99275SPeter Avalos 	switch (FC_SUBTYPE(fc)) {
199827bfbee1SPeter Avalos 	case CTRL_BAR:
1999*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
2000*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
2001*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
2002*ed775ee7SAntonio Huete Jimenez 		    GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
2003*ed775ee7SAntonio Huete Jimenez 		    GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
200427bfbee1SPeter Avalos 		break;
200527bfbee1SPeter Avalos 	case CTRL_BA:
2006*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s ",
2007*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
200827bfbee1SPeter Avalos 		break;
200941c99275SPeter Avalos 	case CTRL_PS_POLL:
2010*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("BSSID:%s TA:%s ",
2011*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
2012*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
201341c99275SPeter Avalos 		break;
201441c99275SPeter Avalos 	case CTRL_RTS:
2015*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s TA:%s ",
2016*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
2017*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
201841c99275SPeter Avalos 		break;
201941c99275SPeter Avalos 	case CTRL_CTS:
2020*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s ",
2021*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
202241c99275SPeter Avalos 		break;
202341c99275SPeter Avalos 	case CTRL_ACK:
2024*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s ",
2025*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
202641c99275SPeter Avalos 		break;
202741c99275SPeter Avalos 	case CTRL_CF_END:
2028*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s BSSID:%s ",
2029*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
2030*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
203141c99275SPeter Avalos 		break;
203241c99275SPeter Avalos 	case CTRL_END_ACK:
2033*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("RA:%s BSSID:%s ",
2034*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
2035*ed775ee7SAntonio Huete Jimenez 		    GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
203641c99275SPeter Avalos 		break;
203741c99275SPeter Avalos 	default:
2038411677aeSAaron LI 		/* We shouldn't get here - we should already have quit */
203941c99275SPeter Avalos 		break;
204041c99275SPeter Avalos 	}
204141c99275SPeter Avalos }
204241c99275SPeter Avalos 
204341c99275SPeter Avalos static int
extract_header_length(netdissect_options * ndo,uint16_t fc)2044411677aeSAaron LI extract_header_length(netdissect_options *ndo,
2045411677aeSAaron LI 		      uint16_t fc)
204641c99275SPeter Avalos {
204741c99275SPeter Avalos 	int len;
204841c99275SPeter Avalos 
204941c99275SPeter Avalos 	switch (FC_TYPE(fc)) {
205041c99275SPeter Avalos 	case T_MGMT:
205141c99275SPeter Avalos 		return MGMT_HDRLEN;
205241c99275SPeter Avalos 	case T_CTRL:
205341c99275SPeter Avalos 		switch (FC_SUBTYPE(fc)) {
2054411677aeSAaron LI 		case CTRL_CONTROL_WRAPPER:
2055411677aeSAaron LI 			return CTRL_CONTROL_WRAPPER_HDRLEN;
205627bfbee1SPeter Avalos 		case CTRL_BAR:
205727bfbee1SPeter Avalos 			return CTRL_BAR_HDRLEN;
2058411677aeSAaron LI 		case CTRL_BA:
2059411677aeSAaron LI 			return CTRL_BA_HDRLEN;
206041c99275SPeter Avalos 		case CTRL_PS_POLL:
206141c99275SPeter Avalos 			return CTRL_PS_POLL_HDRLEN;
206241c99275SPeter Avalos 		case CTRL_RTS:
206341c99275SPeter Avalos 			return CTRL_RTS_HDRLEN;
206441c99275SPeter Avalos 		case CTRL_CTS:
206541c99275SPeter Avalos 			return CTRL_CTS_HDRLEN;
206641c99275SPeter Avalos 		case CTRL_ACK:
206741c99275SPeter Avalos 			return CTRL_ACK_HDRLEN;
206841c99275SPeter Avalos 		case CTRL_CF_END:
206941c99275SPeter Avalos 			return CTRL_END_HDRLEN;
207041c99275SPeter Avalos 		case CTRL_END_ACK:
207141c99275SPeter Avalos 			return CTRL_END_ACK_HDRLEN;
207241c99275SPeter Avalos 		default:
2073*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
207441c99275SPeter Avalos 			return 0;
207541c99275SPeter Avalos 		}
207641c99275SPeter Avalos 	case T_DATA:
207741c99275SPeter Avalos 		len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
207841c99275SPeter Avalos 		if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
207941c99275SPeter Avalos 			len += 2;
208041c99275SPeter Avalos 		return len;
208141c99275SPeter Avalos 	default:
2082*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
208341c99275SPeter Avalos 		return 0;
208441c99275SPeter Avalos 	}
208541c99275SPeter Avalos }
208641c99275SPeter Avalos 
208727bfbee1SPeter Avalos static int
extract_mesh_header_length(netdissect_options * ndo,const u_char * p)2088*ed775ee7SAntonio Huete Jimenez extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
208927bfbee1SPeter Avalos {
2090*ed775ee7SAntonio Huete Jimenez 	return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
209127bfbee1SPeter Avalos }
209227bfbee1SPeter Avalos 
209341c99275SPeter Avalos /*
2094411677aeSAaron LI  * Print the 802.11 MAC header.
209541c99275SPeter Avalos  */
209627bfbee1SPeter Avalos static void
ieee_802_11_hdr_print(netdissect_options * ndo,uint16_t fc,const u_char * p,u_int hdrlen,u_int meshdrlen)2097411677aeSAaron LI ieee_802_11_hdr_print(netdissect_options *ndo,
2098411677aeSAaron LI 		      uint16_t fc, const u_char *p, u_int hdrlen,
2099411677aeSAaron LI 		      u_int meshdrlen)
210041c99275SPeter Avalos {
2101411677aeSAaron LI 	if (ndo->ndo_vflag) {
210241c99275SPeter Avalos 		if (FC_MORE_DATA(fc))
2103*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("More Data ");
210441c99275SPeter Avalos 		if (FC_MORE_FLAG(fc))
2105*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("More Fragments ");
210641c99275SPeter Avalos 		if (FC_POWER_MGMT(fc))
2107*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Pwr Mgmt ");
210841c99275SPeter Avalos 		if (FC_RETRY(fc))
2109*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Retry ");
211041c99275SPeter Avalos 		if (FC_ORDER(fc))
2111*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Strictly Ordered ");
2112411677aeSAaron LI 		if (FC_PROTECTED(fc))
2113*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Protected ");
211441c99275SPeter Avalos 		if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
2115*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%uus ",
2116*ed775ee7SAntonio Huete Jimenez 			    GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
211741c99275SPeter Avalos 	}
211827bfbee1SPeter Avalos 	if (meshdrlen != 0) {
211927bfbee1SPeter Avalos 		const struct meshcntl_t *mc =
2120*ed775ee7SAntonio Huete Jimenez 		    (const struct meshcntl_t *)(p + hdrlen - meshdrlen);
2121*ed775ee7SAntonio Huete Jimenez 		u_int ae = GET_U_1(mc->flags) & 3;
212227bfbee1SPeter Avalos 
2123*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
2124*ed775ee7SAntonio Huete Jimenez 		    GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
212527bfbee1SPeter Avalos 		if (ae > 0)
2126*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
212727bfbee1SPeter Avalos 		if (ae > 1)
2128*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
212927bfbee1SPeter Avalos 		if (ae > 2)
2130*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
2131*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(") ");
213227bfbee1SPeter Avalos 	}
213341c99275SPeter Avalos 
213441c99275SPeter Avalos 	switch (FC_TYPE(fc)) {
213541c99275SPeter Avalos 	case T_MGMT:
2136411677aeSAaron LI 		mgmt_header_print(ndo, p);
213741c99275SPeter Avalos 		break;
213841c99275SPeter Avalos 	case T_CTRL:
2139411677aeSAaron LI 		ctrl_header_print(ndo, fc, p);
214041c99275SPeter Avalos 		break;
214141c99275SPeter Avalos 	case T_DATA:
2142411677aeSAaron LI 		data_header_print(ndo, fc, p);
214341c99275SPeter Avalos 		break;
214441c99275SPeter Avalos 	default:
214541c99275SPeter Avalos 		break;
214641c99275SPeter Avalos 	}
214741c99275SPeter Avalos }
214841c99275SPeter Avalos 
214941c99275SPeter Avalos 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)2150411677aeSAaron LI ieee802_11_print(netdissect_options *ndo,
2151411677aeSAaron LI 		 const u_char *p, u_int length, u_int orig_caplen, int pad,
215227bfbee1SPeter Avalos 		 u_int fcslen)
215341c99275SPeter Avalos {
2154411677aeSAaron LI 	uint16_t fc;
215527bfbee1SPeter Avalos 	u_int caplen, hdrlen, meshdrlen;
2156411677aeSAaron LI 	struct lladdr_info src, dst;
2157411677aeSAaron LI 	int llc_hdrlen;
215841c99275SPeter Avalos 
2159*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "802.11";
216027bfbee1SPeter Avalos 	caplen = orig_caplen;
216127bfbee1SPeter Avalos 	/* Remove FCS, if present */
216227bfbee1SPeter Avalos 	if (length < fcslen) {
2163*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
216441c99275SPeter Avalos 		return caplen;
216541c99275SPeter Avalos 	}
216627bfbee1SPeter Avalos 	length -= fcslen;
216727bfbee1SPeter Avalos 	if (caplen > length) {
216827bfbee1SPeter Avalos 		/* Amount of FCS in actual packet data, if any */
216927bfbee1SPeter Avalos 		fcslen = caplen - length;
217027bfbee1SPeter Avalos 		caplen -= fcslen;
2171411677aeSAaron LI 		ndo->ndo_snapend -= fcslen;
217227bfbee1SPeter Avalos 	}
217327bfbee1SPeter Avalos 
217427bfbee1SPeter Avalos 	if (caplen < IEEE802_11_FC_LEN) {
2175*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
217627bfbee1SPeter Avalos 		return orig_caplen;
217727bfbee1SPeter Avalos 	}
217841c99275SPeter Avalos 
2179*ed775ee7SAntonio Huete Jimenez 	fc = GET_LE_U_2(p);
2180411677aeSAaron LI 	hdrlen = extract_header_length(ndo, fc);
2181411677aeSAaron LI 	if (hdrlen == 0) {
2182411677aeSAaron LI 		/* Unknown frame type or control frame subtype; quit. */
2183411677aeSAaron LI 		return (0);
2184411677aeSAaron LI 	}
218541c99275SPeter Avalos 	if (pad)
218641c99275SPeter Avalos 		hdrlen = roundup2(hdrlen, 4);
2187411677aeSAaron LI 	if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
218827bfbee1SPeter Avalos 	    DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
2189*ed775ee7SAntonio Huete Jimenez 		if(!ND_TTEST_1(p + hdrlen)) {
2190*ed775ee7SAntonio Huete Jimenez 			nd_print_trunc(ndo);
2191411677aeSAaron LI 			return hdrlen;
2192411677aeSAaron LI 		}
2193*ed775ee7SAntonio Huete Jimenez 		meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
219427bfbee1SPeter Avalos 		hdrlen += meshdrlen;
219527bfbee1SPeter Avalos 	} else
219627bfbee1SPeter Avalos 		meshdrlen = 0;
219727bfbee1SPeter Avalos 
219841c99275SPeter Avalos 	if (caplen < hdrlen) {
2199*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
220041c99275SPeter Avalos 		return hdrlen;
220141c99275SPeter Avalos 	}
220241c99275SPeter Avalos 
2203411677aeSAaron LI 	if (ndo->ndo_eflag)
2204411677aeSAaron LI 		ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
220541c99275SPeter Avalos 
220641c99275SPeter Avalos 	/*
220741c99275SPeter Avalos 	 * Go past the 802.11 header.
220841c99275SPeter Avalos 	 */
220941c99275SPeter Avalos 	length -= hdrlen;
221041c99275SPeter Avalos 	caplen -= hdrlen;
221141c99275SPeter Avalos 	p += hdrlen;
221241c99275SPeter Avalos 
2213411677aeSAaron LI 	src.addr_string = etheraddr_string;
2214411677aeSAaron LI 	dst.addr_string = etheraddr_string;
221541c99275SPeter Avalos 	switch (FC_TYPE(fc)) {
221641c99275SPeter Avalos 	case T_MGMT:
2217411677aeSAaron LI 		get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
2218411677aeSAaron LI 		if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
2219*ed775ee7SAntonio Huete Jimenez 			nd_print_trunc(ndo);
222041c99275SPeter Avalos 			return hdrlen;
222141c99275SPeter Avalos 		}
222241c99275SPeter Avalos 		break;
222341c99275SPeter Avalos 	case T_CTRL:
2224411677aeSAaron LI 		if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
2225*ed775ee7SAntonio Huete Jimenez 			nd_print_trunc(ndo);
222641c99275SPeter Avalos 			return hdrlen;
222741c99275SPeter Avalos 		}
222841c99275SPeter Avalos 		break;
222941c99275SPeter Avalos 	case T_DATA:
223041c99275SPeter Avalos 		if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
223141c99275SPeter Avalos 			return hdrlen;	/* no-data frame */
223241c99275SPeter Avalos 		/* There may be a problem w/ AP not having this bit set */
2233411677aeSAaron LI 		if (FC_PROTECTED(fc)) {
2234*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("Data");
2235411677aeSAaron LI 			if (!wep_print(ndo, p)) {
2236*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
223741c99275SPeter Avalos 				return hdrlen;
223841c99275SPeter Avalos 			}
2239411677aeSAaron LI 		} else {
2240411677aeSAaron LI 			get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
2241411677aeSAaron LI 			llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
2242411677aeSAaron LI 			if (llc_hdrlen < 0) {
224341c99275SPeter Avalos 				/*
224441c99275SPeter Avalos 				 * Some kinds of LLC packet we cannot
224541c99275SPeter Avalos 				 * handle intelligently
224641c99275SPeter Avalos 				 */
2247411677aeSAaron LI 				if (!ndo->ndo_suppress_default_print)
2248411677aeSAaron LI 					ND_DEFAULTPRINT(p, caplen);
2249411677aeSAaron LI 				llc_hdrlen = -llc_hdrlen;
2250411677aeSAaron LI 			}
2251411677aeSAaron LI 			hdrlen += llc_hdrlen;
225241c99275SPeter Avalos 		}
225341c99275SPeter Avalos 		break;
225441c99275SPeter Avalos 	default:
2255411677aeSAaron LI 		/* We shouldn't get here - we should already have quit */
225641c99275SPeter Avalos 		break;
225741c99275SPeter Avalos 	}
225841c99275SPeter Avalos 
225941c99275SPeter Avalos 	return hdrlen;
226041c99275SPeter Avalos }
226141c99275SPeter Avalos 
226241c99275SPeter Avalos /*
226341c99275SPeter Avalos  * This is the top level routine of the printer.  'p' points
226441c99275SPeter Avalos  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
226541c99275SPeter Avalos  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
226641c99275SPeter Avalos  * is the number of bytes actually captured.
226741c99275SPeter Avalos  */
2268*ed775ee7SAntonio Huete Jimenez void
ieee802_11_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)2269411677aeSAaron LI ieee802_11_if_print(netdissect_options *ndo,
2270411677aeSAaron LI 		    const struct pcap_pkthdr *h, const u_char *p)
227141c99275SPeter Avalos {
2272*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "802.11";
2273*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
227427bfbee1SPeter Avalos }
227527bfbee1SPeter Avalos 
2276411677aeSAaron LI 
2277411677aeSAaron LI /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
2278411677aeSAaron LI /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp  */
2279411677aeSAaron LI 
2280411677aeSAaron LI /*-
2281411677aeSAaron LI  * Copyright (c) 2003, 2004 David Young.  All rights reserved.
2282411677aeSAaron LI  *
2283411677aeSAaron LI  * Redistribution and use in source and binary forms, with or without
2284411677aeSAaron LI  * modification, are permitted provided that the following conditions
2285411677aeSAaron LI  * are met:
2286411677aeSAaron LI  * 1. Redistributions of source code must retain the above copyright
2287411677aeSAaron LI  *    notice, this list of conditions and the following disclaimer.
2288411677aeSAaron LI  * 2. Redistributions in binary form must reproduce the above copyright
2289411677aeSAaron LI  *    notice, this list of conditions and the following disclaimer in the
2290411677aeSAaron LI  *    documentation and/or other materials provided with the distribution.
2291411677aeSAaron LI  * 3. The name of David Young may not be used to endorse or promote
2292411677aeSAaron LI  *    products derived from this software without specific prior
2293411677aeSAaron LI  *    written permission.
2294411677aeSAaron LI  *
2295411677aeSAaron LI  * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
2296411677aeSAaron LI  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2297411677aeSAaron LI  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2298411677aeSAaron LI  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
2299411677aeSAaron LI  * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2300411677aeSAaron LI  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2301411677aeSAaron LI  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2302411677aeSAaron LI  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2303411677aeSAaron LI  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2304411677aeSAaron LI  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2305411677aeSAaron LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2306411677aeSAaron LI  * OF SUCH DAMAGE.
2307411677aeSAaron LI  */
2308411677aeSAaron LI 
2309411677aeSAaron LI /* A generic radio capture format is desirable. It must be
2310411677aeSAaron LI  * rigidly defined (e.g., units for fields should be given),
2311411677aeSAaron LI  * and easily extensible.
2312411677aeSAaron LI  *
2313411677aeSAaron LI  * The following is an extensible radio capture format. It is
2314411677aeSAaron LI  * based on a bitmap indicating which fields are present.
2315411677aeSAaron LI  *
2316411677aeSAaron LI  * I am trying to describe precisely what the application programmer
2317411677aeSAaron LI  * should expect in the following, and for that reason I tell the
2318411677aeSAaron LI  * units and origin of each measurement (where it applies), or else I
2319411677aeSAaron LI  * use sufficiently weaselly language ("is a monotonically nondecreasing
2320411677aeSAaron LI  * function of...") that I cannot set false expectations for lawyerly
2321411677aeSAaron LI  * readers.
2322411677aeSAaron LI  */
2323411677aeSAaron LI 
2324411677aeSAaron LI /*
2325411677aeSAaron LI  * The radio capture header precedes the 802.11 header.
2326411677aeSAaron LI  *
2327411677aeSAaron LI  * Note well: all radiotap fields are little-endian.
2328411677aeSAaron LI  */
2329411677aeSAaron LI struct ieee80211_radiotap_header {
2330*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	it_version;	/* Version 0. Only increases
2331411677aeSAaron LI 					 * for drastic changes,
2332411677aeSAaron LI 					 * introduction of compatible
2333411677aeSAaron LI 					 * new fields does not count.
2334411677aeSAaron LI 					 */
2335*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	it_pad;
2336*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	it_len;		/* length of the whole
2337411677aeSAaron LI 					 * header in bytes, including
2338411677aeSAaron LI 					 * it_version, it_pad,
2339411677aeSAaron LI 					 * it_len, and data fields.
2340411677aeSAaron LI 					 */
2341*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	it_present;	/* A bitmap telling which
2342411677aeSAaron LI 					 * fields are present. Set bit 31
2343411677aeSAaron LI 					 * (0x80000000) to extend the
2344411677aeSAaron LI 					 * bitmap by another 32 bits.
2345411677aeSAaron LI 					 * Additional extensions are made
2346411677aeSAaron LI 					 * by setting bit 31.
2347411677aeSAaron LI 					 */
2348411677aeSAaron LI };
2349411677aeSAaron LI 
2350411677aeSAaron LI /* Name                                 Data type       Units
2351411677aeSAaron LI  * ----                                 ---------       -----
2352411677aeSAaron LI  *
2353411677aeSAaron LI  * IEEE80211_RADIOTAP_TSFT              uint64_t       microseconds
2354411677aeSAaron LI  *
2355411677aeSAaron LI  *      Value in microseconds of the MAC's 64-bit 802.11 Time
2356411677aeSAaron LI  *      Synchronization Function timer when the first bit of the
2357411677aeSAaron LI  *      MPDU arrived at the MAC. For received frames, only.
2358411677aeSAaron LI  *
2359411677aeSAaron LI  * IEEE80211_RADIOTAP_CHANNEL           2 x uint16_t   MHz, bitmap
2360411677aeSAaron LI  *
2361411677aeSAaron LI  *      Tx/Rx frequency in MHz, followed by flags (see below).
2362411677aeSAaron LI  *	Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
2363411677aeSAaron LI  *	represent an HT channel as there is not enough room in
2364411677aeSAaron LI  *	the flags word.
2365411677aeSAaron LI  *
2366411677aeSAaron LI  * IEEE80211_RADIOTAP_FHSS              uint16_t       see below
2367411677aeSAaron LI  *
2368411677aeSAaron LI  *      For frequency-hopping radios, the hop set (first byte)
2369411677aeSAaron LI  *      and pattern (second byte).
2370411677aeSAaron LI  *
2371411677aeSAaron LI  * IEEE80211_RADIOTAP_RATE              uint8_t        500kb/s or index
2372411677aeSAaron LI  *
2373411677aeSAaron LI  *      Tx/Rx data rate.  If bit 0x80 is set then it represents an
2374411677aeSAaron LI  *	an MCS index and not an IEEE rate.
2375411677aeSAaron LI  *
2376411677aeSAaron LI  * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t         decibels from
2377411677aeSAaron LI  *                                                     one milliwatt (dBm)
2378411677aeSAaron LI  *
2379411677aeSAaron LI  *      RF signal power at the antenna, decibel difference from
2380411677aeSAaron LI  *      one milliwatt.
2381411677aeSAaron LI  *
2382411677aeSAaron LI  * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t         decibels from
2383411677aeSAaron LI  *                                                     one milliwatt (dBm)
2384411677aeSAaron LI  *
2385411677aeSAaron LI  *      RF noise power at the antenna, decibel difference from one
2386411677aeSAaron LI  *      milliwatt.
2387411677aeSAaron LI  *
2388411677aeSAaron LI  * IEEE80211_RADIOTAP_DB_ANTSIGNAL      uint8_t        decibel (dB)
2389411677aeSAaron LI  *
2390411677aeSAaron LI  *      RF signal power at the antenna, decibel difference from an
2391411677aeSAaron LI  *      arbitrary, fixed reference.
2392411677aeSAaron LI  *
2393411677aeSAaron LI  * IEEE80211_RADIOTAP_DB_ANTNOISE       uint8_t        decibel (dB)
2394411677aeSAaron LI  *
2395411677aeSAaron LI  *      RF noise power at the antenna, decibel difference from an
2396411677aeSAaron LI  *      arbitrary, fixed reference point.
2397411677aeSAaron LI  *
2398411677aeSAaron LI  * IEEE80211_RADIOTAP_LOCK_QUALITY      uint16_t       unitless
2399411677aeSAaron LI  *
2400411677aeSAaron LI  *      Quality of Barker code lock. Unitless. Monotonically
2401411677aeSAaron LI  *      nondecreasing with "better" lock strength. Called "Signal
2402411677aeSAaron LI  *      Quality" in datasheets.  (Is there a standard way to measure
2403411677aeSAaron LI  *      this?)
2404411677aeSAaron LI  *
2405411677aeSAaron LI  * IEEE80211_RADIOTAP_TX_ATTENUATION    uint16_t       unitless
2406411677aeSAaron LI  *
2407411677aeSAaron LI  *      Transmit power expressed as unitless distance from max
2408411677aeSAaron LI  *      power set at factory calibration.  0 is max power.
2409411677aeSAaron LI  *      Monotonically nondecreasing with lower power levels.
2410411677aeSAaron LI  *
2411411677aeSAaron LI  * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t       decibels (dB)
2412411677aeSAaron LI  *
2413411677aeSAaron LI  *      Transmit power expressed as decibel distance from max power
2414411677aeSAaron LI  *      set at factory calibration.  0 is max power.  Monotonically
2415411677aeSAaron LI  *      nondecreasing with lower power levels.
2416411677aeSAaron LI  *
2417411677aeSAaron LI  * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t         decibels from
2418411677aeSAaron LI  *                                                     one milliwatt (dBm)
2419411677aeSAaron LI  *
2420411677aeSAaron LI  *      Transmit power expressed as dBm (decibels from a 1 milliwatt
2421411677aeSAaron LI  *      reference). This is the absolute power level measured at
2422411677aeSAaron LI  *      the antenna port.
2423411677aeSAaron LI  *
2424411677aeSAaron LI  * IEEE80211_RADIOTAP_FLAGS             uint8_t        bitmap
2425411677aeSAaron LI  *
2426411677aeSAaron LI  *      Properties of transmitted and received frames. See flags
2427411677aeSAaron LI  *      defined below.
2428411677aeSAaron LI  *
2429411677aeSAaron LI  * IEEE80211_RADIOTAP_ANTENNA           uint8_t        antenna index
2430411677aeSAaron LI  *
2431411677aeSAaron LI  *      Unitless indication of the Rx/Tx antenna for this packet.
2432411677aeSAaron LI  *      The first antenna is antenna 0.
2433411677aeSAaron LI  *
2434411677aeSAaron LI  * IEEE80211_RADIOTAP_RX_FLAGS          uint16_t       bitmap
2435411677aeSAaron LI  *
2436411677aeSAaron LI  *     Properties of received frames. See flags defined below.
2437411677aeSAaron LI  *
2438411677aeSAaron LI  * IEEE80211_RADIOTAP_XCHANNEL          uint32_t       bitmap
2439411677aeSAaron LI  *					uint16_t       MHz
2440411677aeSAaron LI  *					uint8_t        channel number
2441411677aeSAaron LI  *					uint8_t        .5 dBm
2442411677aeSAaron LI  *
2443411677aeSAaron LI  *	Extended channel specification: flags (see below) followed by
2444411677aeSAaron LI  *	frequency in MHz, the corresponding IEEE channel number, and
2445411677aeSAaron LI  *	finally the maximum regulatory transmit power cap in .5 dBm
2446411677aeSAaron LI  *	units.  This property supersedes IEEE80211_RADIOTAP_CHANNEL
2447411677aeSAaron LI  *	and only one of the two should be present.
2448411677aeSAaron LI  *
2449411677aeSAaron LI  * IEEE80211_RADIOTAP_MCS		uint8_t        known
2450411677aeSAaron LI  *					uint8_t        flags
2451411677aeSAaron LI  *					uint8_t        mcs
2452411677aeSAaron LI  *
2453411677aeSAaron LI  *	Bitset indicating which fields have known values, followed
2454411677aeSAaron LI  *	by bitset of flag values, followed by the MCS rate index as
2455411677aeSAaron LI  *	in IEEE 802.11n.
2456411677aeSAaron LI  *
2457411677aeSAaron LI  *
2458411677aeSAaron LI  * IEEE80211_RADIOTAP_AMPDU_STATUS	u32, u16, u8, u8	unitless
2459411677aeSAaron LI  *
2460411677aeSAaron LI  *	Contains the AMPDU information for the subframe.
2461411677aeSAaron LI  *
2462411677aeSAaron LI  * IEEE80211_RADIOTAP_VHT	u16, u8, u8, u8[4], u8, u8, u16
2463411677aeSAaron LI  *
2464411677aeSAaron LI  *	Contains VHT information about this frame.
2465411677aeSAaron LI  *
2466411677aeSAaron LI  * IEEE80211_RADIOTAP_VENDOR_NAMESPACE
2467411677aeSAaron LI  *					uint8_t  OUI[3]
2468411677aeSAaron LI  *                                      uint8_t        subspace
2469411677aeSAaron LI  *                                      uint16_t       length
2470411677aeSAaron LI  *
2471411677aeSAaron LI  *     The Vendor Namespace Field contains three sub-fields. The first
2472411677aeSAaron LI  *     sub-field is 3 bytes long. It contains the vendor's IEEE 802
2473411677aeSAaron LI  *     Organizationally Unique Identifier (OUI). The fourth byte is a
2474411677aeSAaron LI  *     vendor-specific "namespace selector."
2475411677aeSAaron LI  *
2476411677aeSAaron LI  */
2477411677aeSAaron LI enum ieee80211_radiotap_type {
2478411677aeSAaron LI 	IEEE80211_RADIOTAP_TSFT = 0,
2479411677aeSAaron LI 	IEEE80211_RADIOTAP_FLAGS = 1,
2480411677aeSAaron LI 	IEEE80211_RADIOTAP_RATE = 2,
2481411677aeSAaron LI 	IEEE80211_RADIOTAP_CHANNEL = 3,
2482411677aeSAaron LI 	IEEE80211_RADIOTAP_FHSS = 4,
2483411677aeSAaron LI 	IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
2484411677aeSAaron LI 	IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
2485411677aeSAaron LI 	IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
2486411677aeSAaron LI 	IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
2487411677aeSAaron LI 	IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
2488411677aeSAaron LI 	IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
2489411677aeSAaron LI 	IEEE80211_RADIOTAP_ANTENNA = 11,
2490411677aeSAaron LI 	IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
2491411677aeSAaron LI 	IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
2492411677aeSAaron LI 	IEEE80211_RADIOTAP_RX_FLAGS = 14,
2493411677aeSAaron LI 	/* NB: gap for netbsd definitions */
2494411677aeSAaron LI 	IEEE80211_RADIOTAP_XCHANNEL = 18,
2495411677aeSAaron LI 	IEEE80211_RADIOTAP_MCS = 19,
2496411677aeSAaron LI 	IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
2497411677aeSAaron LI 	IEEE80211_RADIOTAP_VHT = 21,
2498411677aeSAaron LI 	IEEE80211_RADIOTAP_NAMESPACE = 29,
2499411677aeSAaron LI 	IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
2500411677aeSAaron LI 	IEEE80211_RADIOTAP_EXT = 31
2501411677aeSAaron LI };
2502411677aeSAaron LI 
2503411677aeSAaron LI /* channel attributes */
2504411677aeSAaron LI #define	IEEE80211_CHAN_TURBO	0x00010	/* Turbo channel */
2505411677aeSAaron LI #define	IEEE80211_CHAN_CCK	0x00020	/* CCK channel */
2506411677aeSAaron LI #define	IEEE80211_CHAN_OFDM	0x00040	/* OFDM channel */
2507411677aeSAaron LI #define	IEEE80211_CHAN_2GHZ	0x00080	/* 2 GHz spectrum channel. */
2508411677aeSAaron LI #define	IEEE80211_CHAN_5GHZ	0x00100	/* 5 GHz spectrum channel */
2509411677aeSAaron LI #define	IEEE80211_CHAN_PASSIVE	0x00200	/* Only passive scan allowed */
2510411677aeSAaron LI #define	IEEE80211_CHAN_DYN	0x00400	/* Dynamic CCK-OFDM channel */
2511411677aeSAaron LI #define	IEEE80211_CHAN_GFSK	0x00800	/* GFSK channel (FHSS PHY) */
2512411677aeSAaron LI #define	IEEE80211_CHAN_GSM	0x01000	/* 900 MHz spectrum channel */
2513411677aeSAaron LI #define	IEEE80211_CHAN_STURBO	0x02000	/* 11a static turbo channel only */
2514411677aeSAaron LI #define	IEEE80211_CHAN_HALF	0x04000	/* Half rate channel */
2515411677aeSAaron LI #define	IEEE80211_CHAN_QUARTER	0x08000	/* Quarter rate channel */
2516411677aeSAaron LI #define	IEEE80211_CHAN_HT20	0x10000	/* HT 20 channel */
2517411677aeSAaron LI #define	IEEE80211_CHAN_HT40U	0x20000	/* HT 40 channel w/ ext above */
2518411677aeSAaron LI #define	IEEE80211_CHAN_HT40D	0x40000	/* HT 40 channel w/ ext below */
2519411677aeSAaron LI 
2520411677aeSAaron LI /* Useful combinations of channel characteristics, borrowed from Ethereal */
2521411677aeSAaron LI #define IEEE80211_CHAN_A \
2522411677aeSAaron LI 	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2523411677aeSAaron LI #define IEEE80211_CHAN_B \
2524411677aeSAaron LI 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2525411677aeSAaron LI #define IEEE80211_CHAN_G \
2526411677aeSAaron LI 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2527411677aeSAaron LI #define IEEE80211_CHAN_TA \
2528411677aeSAaron LI 	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
2529411677aeSAaron LI #define IEEE80211_CHAN_TG \
2530411677aeSAaron LI 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN  | IEEE80211_CHAN_TURBO)
2531411677aeSAaron LI 
2532411677aeSAaron LI 
2533411677aeSAaron LI /* For IEEE80211_RADIOTAP_FLAGS */
2534411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
2535411677aeSAaron LI 						 * during CFP
2536411677aeSAaron LI 						 */
2537411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_SHORTPRE	0x02	/* sent/received
2538411677aeSAaron LI 						 * with short
2539411677aeSAaron LI 						 * preamble
2540411677aeSAaron LI 						 */
2541411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_WEP	0x04	/* sent/received
2542411677aeSAaron LI 						 * with WEP encryption
2543411677aeSAaron LI 						 */
2544411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_FRAG	0x08	/* sent/received
2545411677aeSAaron LI 						 * with fragmentation
2546411677aeSAaron LI 						 */
2547411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_FCS	0x10	/* frame includes FCS */
2548411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_DATAPAD	0x20	/* frame has padding between
2549411677aeSAaron LI 						 * 802.11 header and payload
2550411677aeSAaron LI 						 * (to 32-bit boundary)
2551411677aeSAaron LI 						 */
2552411677aeSAaron LI #define	IEEE80211_RADIOTAP_F_BADFCS	0x40	/* does not pass FCS check */
2553411677aeSAaron LI 
2554411677aeSAaron LI /* For IEEE80211_RADIOTAP_RX_FLAGS */
2555411677aeSAaron LI #define IEEE80211_RADIOTAP_F_RX_BADFCS	0x0001	/* frame failed crc check */
2556411677aeSAaron LI #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC	0x0002	/* frame failed PLCP CRC check */
2557411677aeSAaron LI 
2558411677aeSAaron LI /* For IEEE80211_RADIOTAP_MCS known */
2559411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN		0x01
2560411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN		0x02	/* MCS index field */
2561411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN	0x04
2562411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN		0x08
2563411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN		0x10
2564411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN		0x20
2565411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN		0x40
2566411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1		0x80
2567411677aeSAaron LI 
2568411677aeSAaron LI /* For IEEE80211_RADIOTAP_MCS flags */
2569411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK	0x03
2570411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20	0
2571411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40	1
2572411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L	2
2573411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U	3
2574411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_SHORT_GI		0x04 /* short guard interval */
2575411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD	0x08
2576411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_FEC_LDPC		0x10
2577411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_MASK	0x60
2578411677aeSAaron LI #define		IEEE80211_RADIOTAP_MCS_STBC_1	1
2579411677aeSAaron LI #define		IEEE80211_RADIOTAP_MCS_STBC_2	2
2580411677aeSAaron LI #define		IEEE80211_RADIOTAP_MCS_STBC_3	3
2581411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT	5
2582411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0	0x80
2583411677aeSAaron LI 
2584411677aeSAaron LI /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
2585411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN		0x0001
2586411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN		0x0002
2587411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN		0x0004
2588411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_IS_LAST		0x0008
2589411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR		0x0010
2590411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN	0x0020
2591411677aeSAaron LI 
2592411677aeSAaron LI /* For IEEE80211_RADIOTAP_VHT known */
2593411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN			0x0001
2594411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN			0x0002
2595411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN		0x0004
2596411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN		0x0008
2597411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN	0x0010
2598411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN			0x0020
2599411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN			0x0040
2600411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN			0x0080
2601411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN		0x0100
2602411677aeSAaron LI 
2603411677aeSAaron LI /* For IEEE80211_RADIOTAP_VHT flags */
2604411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_STBC			0x01
2605411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA		0x02
2606411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_SHORT_GI			0x04
2607411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9		0x08
2608411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM	0x10
2609411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BEAMFORMED		0x20
2610411677aeSAaron LI 
2611411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK	0x1f
2612411677aeSAaron LI 
2613411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_NSS_MASK		0x0f
2614411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_MCS_MASK		0xf0
2615411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT	4
2616411677aeSAaron LI 
2617411677aeSAaron LI #define IEEE80211_RADIOTAP_CODING_LDPC_USERn			0x01
2618411677aeSAaron LI 
261927bfbee1SPeter Avalos #define	IEEE80211_CHAN_FHSS \
262027bfbee1SPeter Avalos 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
262127bfbee1SPeter Avalos #define	IEEE80211_CHAN_A \
262227bfbee1SPeter Avalos 	(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
262327bfbee1SPeter Avalos #define	IEEE80211_CHAN_B \
262427bfbee1SPeter Avalos 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
262527bfbee1SPeter Avalos #define	IEEE80211_CHAN_PUREG \
262627bfbee1SPeter Avalos 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
262727bfbee1SPeter Avalos #define	IEEE80211_CHAN_G \
262827bfbee1SPeter Avalos 	(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
262927bfbee1SPeter Avalos 
263027bfbee1SPeter Avalos #define	IS_CHAN_FHSS(flags) \
263127bfbee1SPeter Avalos 	((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
263227bfbee1SPeter Avalos #define	IS_CHAN_A(flags) \
263327bfbee1SPeter Avalos 	((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
263427bfbee1SPeter Avalos #define	IS_CHAN_B(flags) \
263527bfbee1SPeter Avalos 	((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
263627bfbee1SPeter Avalos #define	IS_CHAN_PUREG(flags) \
263727bfbee1SPeter Avalos 	((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
263827bfbee1SPeter Avalos #define	IS_CHAN_G(flags) \
263927bfbee1SPeter Avalos 	((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
264027bfbee1SPeter Avalos #define	IS_CHAN_ANYG(flags) \
264127bfbee1SPeter Avalos 	(IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
264227bfbee1SPeter Avalos 
264327bfbee1SPeter Avalos static void
print_chaninfo(netdissect_options * ndo,uint16_t freq,uint32_t flags,uint32_t presentflags)2644411677aeSAaron LI print_chaninfo(netdissect_options *ndo,
2645*ed775ee7SAntonio Huete Jimenez 	       uint16_t freq, uint32_t flags, uint32_t presentflags)
264627bfbee1SPeter Avalos {
2647*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%u MHz", freq);
2648411677aeSAaron LI 	if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
2649411677aeSAaron LI 		/*
2650411677aeSAaron LI 		 * We have the MCS field, so this is 11n, regardless
2651411677aeSAaron LI 		 * of what the channel flags say.
2652411677aeSAaron LI 		 */
2653*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" 11n");
2654411677aeSAaron LI 	} else {
265527bfbee1SPeter Avalos 		if (IS_CHAN_FHSS(flags))
2656*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" FHSS");
265727bfbee1SPeter Avalos 		if (IS_CHAN_A(flags)) {
265827bfbee1SPeter Avalos 			if (flags & IEEE80211_CHAN_HALF)
2659*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" 11a/10Mhz");
266027bfbee1SPeter Avalos 			else if (flags & IEEE80211_CHAN_QUARTER)
2661*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" 11a/5Mhz");
266227bfbee1SPeter Avalos 			else
2663*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" 11a");
266427bfbee1SPeter Avalos 		}
266527bfbee1SPeter Avalos 		if (IS_CHAN_ANYG(flags)) {
266627bfbee1SPeter Avalos 			if (flags & IEEE80211_CHAN_HALF)
2667*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" 11g/10Mhz");
266827bfbee1SPeter Avalos 			else if (flags & IEEE80211_CHAN_QUARTER)
2669*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" 11g/5Mhz");
267027bfbee1SPeter Avalos 			else
2671*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" 11g");
267227bfbee1SPeter Avalos 		} else if (IS_CHAN_B(flags))
2673*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" 11b");
267427bfbee1SPeter Avalos 		if (flags & IEEE80211_CHAN_TURBO)
2675*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" Turbo");
2676411677aeSAaron LI 	}
2677411677aeSAaron LI 	/*
2678411677aeSAaron LI 	 * These apply to 11n.
2679411677aeSAaron LI 	 */
268027bfbee1SPeter Avalos 	if (flags & IEEE80211_CHAN_HT20)
2681*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ht/20");
268227bfbee1SPeter Avalos 	else if (flags & IEEE80211_CHAN_HT40D)
2683*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ht/40-");
268427bfbee1SPeter Avalos 	else if (flags & IEEE80211_CHAN_HT40U)
2685*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" ht/40+");
2686*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" ");
268741c99275SPeter Avalos }
268841c99275SPeter Avalos 
268941c99275SPeter Avalos static int
print_radiotap_field(netdissect_options * ndo,struct cpack_state * s,uint32_t bit,uint8_t * flagsp,uint32_t presentflags)2690411677aeSAaron LI print_radiotap_field(netdissect_options *ndo,
2691411677aeSAaron LI 		     struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
2692411677aeSAaron LI 		     uint32_t presentflags)
269341c99275SPeter Avalos {
2694411677aeSAaron LI 	u_int i;
269541c99275SPeter Avalos 	int rc;
269641c99275SPeter Avalos 
269741c99275SPeter Avalos 	switch (bit) {
269827bfbee1SPeter Avalos 
2699411677aeSAaron LI 	case IEEE80211_RADIOTAP_TSFT: {
2700411677aeSAaron LI 		uint64_t tsft;
270127bfbee1SPeter Avalos 
2702*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint64(ndo, s, &tsft);
2703411677aeSAaron LI 		if (rc != 0)
2704411677aeSAaron LI 			goto trunc;
2705*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%" PRIu64 "us tsft ", tsft);
270627bfbee1SPeter Avalos 		break;
270727bfbee1SPeter Avalos 		}
270827bfbee1SPeter Avalos 
2709411677aeSAaron LI 	case IEEE80211_RADIOTAP_FLAGS: {
2710411677aeSAaron LI 		uint8_t flagsval;
271127bfbee1SPeter Avalos 
2712*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &flagsval);
2713411677aeSAaron LI 		if (rc != 0)
2714411677aeSAaron LI 			goto trunc;
2715411677aeSAaron LI 		*flagsp = flagsval;
2716411677aeSAaron LI 		if (flagsval & IEEE80211_RADIOTAP_F_CFP)
2717*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("cfp ");
2718411677aeSAaron LI 		if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
2719*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("short preamble ");
2720411677aeSAaron LI 		if (flagsval & IEEE80211_RADIOTAP_F_WEP)
2721*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("wep ");
2722411677aeSAaron LI 		if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
2723*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("fragmented ");
2724411677aeSAaron LI 		if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
2725*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("bad-fcs ");
272627bfbee1SPeter Avalos 		break;
272727bfbee1SPeter Avalos 		}
272841c99275SPeter Avalos 
2729411677aeSAaron LI 	case IEEE80211_RADIOTAP_RATE: {
2730411677aeSAaron LI 		uint8_t rate;
273141c99275SPeter Avalos 
2732*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &rate);
2733411677aeSAaron LI 		if (rc != 0)
2734411677aeSAaron LI 			goto trunc;
273527bfbee1SPeter Avalos 		/*
273627bfbee1SPeter Avalos 		 * XXX On FreeBSD rate & 0x80 means we have an MCS. On
273727bfbee1SPeter Avalos 		 * Linux and AirPcap it does not.  (What about
2738*ed775ee7SAntonio Huete Jimenez 		 * macOS, NetBSD, OpenBSD, and DragonFly BSD?)
273927bfbee1SPeter Avalos 		 *
274027bfbee1SPeter Avalos 		 * This is an issue either for proprietary extensions
274127bfbee1SPeter Avalos 		 * to 11a or 11g, which do exist, or for 11n
274227bfbee1SPeter Avalos 		 * implementations that stuff a rate value into
274327bfbee1SPeter Avalos 		 * this field, which also appear to exist.
274427bfbee1SPeter Avalos 		 *
274527bfbee1SPeter Avalos 		 * We currently handle that by assuming that
274627bfbee1SPeter Avalos 		 * if the 0x80 bit is set *and* the remaining
274727bfbee1SPeter Avalos 		 * bits have a value between 0 and 15 it's
274827bfbee1SPeter Avalos 		 * an MCS value, otherwise it's a rate.  If
274927bfbee1SPeter Avalos 		 * there are cases where systems that use
275027bfbee1SPeter Avalos 		 * "0x80 + MCS index" for MCS indices > 15,
275127bfbee1SPeter Avalos 		 * or stuff a rate value here between 64 and
275227bfbee1SPeter Avalos 		 * 71.5 Mb/s in here, we'll need a preference
275327bfbee1SPeter Avalos 		 * setting.  Such rates do exist, e.g. 11n
275427bfbee1SPeter Avalos 		 * MCS 7 at 20 MHz with a long guard interval.
275527bfbee1SPeter Avalos 		 */
2756411677aeSAaron LI 		if (rate >= 0x80 && rate <= 0x8f) {
275727bfbee1SPeter Avalos 			/*
275827bfbee1SPeter Avalos 			 * XXX - we don't know the channel width
275927bfbee1SPeter Avalos 			 * or guard interval length, so we can't
276027bfbee1SPeter Avalos 			 * convert this to a data rate.
276127bfbee1SPeter Avalos 			 *
276227bfbee1SPeter Avalos 			 * If you want us to show a data rate,
276327bfbee1SPeter Avalos 			 * use the MCS field, not the Rate field;
276427bfbee1SPeter Avalos 			 * the MCS field includes not only the
276527bfbee1SPeter Avalos 			 * MCS index, it also includes bandwidth
276627bfbee1SPeter Avalos 			 * and guard interval information.
276727bfbee1SPeter Avalos 			 *
276827bfbee1SPeter Avalos 			 * XXX - can we get the channel width
276927bfbee1SPeter Avalos 			 * from XChannel and the guard interval
277027bfbee1SPeter Avalos 			 * information from Flags, at least on
277127bfbee1SPeter Avalos 			 * FreeBSD?
277227bfbee1SPeter Avalos 			 */
2773*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("MCS %u ", rate & 0x7f);
277427bfbee1SPeter Avalos 		} else
2775*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%2.1f Mb/s ", .5 * rate);
277641c99275SPeter Avalos 		break;
2777411677aeSAaron LI 		}
2778411677aeSAaron LI 
2779411677aeSAaron LI 	case IEEE80211_RADIOTAP_CHANNEL: {
2780411677aeSAaron LI 		uint16_t frequency;
2781411677aeSAaron LI 		uint16_t flags;
2782411677aeSAaron LI 
2783*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &frequency);
2784411677aeSAaron LI 		if (rc != 0)
2785411677aeSAaron LI 			goto trunc;
2786*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &flags);
2787411677aeSAaron LI 		if (rc != 0)
2788411677aeSAaron LI 			goto trunc;
2789411677aeSAaron LI 		/*
2790411677aeSAaron LI 		 * If CHANNEL and XCHANNEL are both present, skip
2791411677aeSAaron LI 		 * CHANNEL.
2792411677aeSAaron LI 		 */
2793411677aeSAaron LI 		if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
279441c99275SPeter Avalos 			break;
2795411677aeSAaron LI 		print_chaninfo(ndo, frequency, flags, presentflags);
279641c99275SPeter Avalos 		break;
2797411677aeSAaron LI 		}
2798411677aeSAaron LI 
2799411677aeSAaron LI 	case IEEE80211_RADIOTAP_FHSS: {
2800411677aeSAaron LI 		uint8_t hopset;
2801411677aeSAaron LI 		uint8_t hoppat;
2802411677aeSAaron LI 
2803*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &hopset);
2804411677aeSAaron LI 		if (rc != 0)
2805411677aeSAaron LI 			goto trunc;
2806*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &hoppat);
2807411677aeSAaron LI 		if (rc != 0)
2808411677aeSAaron LI 			goto trunc;
2809*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
281041c99275SPeter Avalos 		break;
2811411677aeSAaron LI 		}
2812411677aeSAaron LI 
2813411677aeSAaron LI 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
2814411677aeSAaron LI 		int8_t dbm_antsignal;
2815411677aeSAaron LI 
2816*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
2817411677aeSAaron LI 		if (rc != 0)
2818411677aeSAaron LI 			goto trunc;
2819*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%ddBm signal ", dbm_antsignal);
282041c99275SPeter Avalos 		break;
2821411677aeSAaron LI 		}
2822411677aeSAaron LI 
2823411677aeSAaron LI 	case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
2824411677aeSAaron LI 		int8_t dbm_antnoise;
2825411677aeSAaron LI 
2826*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
2827411677aeSAaron LI 		if (rc != 0)
2828411677aeSAaron LI 			goto trunc;
2829*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%ddBm noise ", dbm_antnoise);
283041c99275SPeter Avalos 		break;
2831411677aeSAaron LI 		}
2832411677aeSAaron LI 
2833411677aeSAaron LI 	case IEEE80211_RADIOTAP_LOCK_QUALITY: {
2834411677aeSAaron LI 		uint16_t lock_quality;
2835411677aeSAaron LI 
2836*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &lock_quality);
2837411677aeSAaron LI 		if (rc != 0)
2838411677aeSAaron LI 			goto trunc;
2839*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%u sq ", lock_quality);
284041c99275SPeter Avalos 		break;
2841411677aeSAaron LI 		}
2842411677aeSAaron LI 
2843411677aeSAaron LI 	case IEEE80211_RADIOTAP_TX_ATTENUATION: {
2844*ed775ee7SAntonio Huete Jimenez 		int16_t tx_attenuation;
2845411677aeSAaron LI 
2846*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_int16(ndo, s, &tx_attenuation);
2847411677aeSAaron LI 		if (rc != 0)
2848411677aeSAaron LI 			goto trunc;
2849*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%d tx power ", -tx_attenuation);
285041c99275SPeter Avalos 		break;
2851411677aeSAaron LI 		}
2852411677aeSAaron LI 
2853411677aeSAaron LI 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
2854*ed775ee7SAntonio Huete Jimenez 		int8_t db_tx_attenuation;
2855411677aeSAaron LI 
2856*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
2857411677aeSAaron LI 		if (rc != 0)
2858411677aeSAaron LI 			goto trunc;
2859*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
286041c99275SPeter Avalos 		break;
2861411677aeSAaron LI 		}
2862411677aeSAaron LI 
2863411677aeSAaron LI 	case IEEE80211_RADIOTAP_DBM_TX_POWER: {
2864411677aeSAaron LI 		int8_t dbm_tx_power;
2865411677aeSAaron LI 
2866*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
2867411677aeSAaron LI 		if (rc != 0)
2868411677aeSAaron LI 			goto trunc;
2869*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%ddBm tx power ", dbm_tx_power);
287041c99275SPeter Avalos 		break;
2871411677aeSAaron LI 		}
2872411677aeSAaron LI 
2873411677aeSAaron LI 	case IEEE80211_RADIOTAP_ANTENNA: {
2874411677aeSAaron LI 		uint8_t antenna;
2875411677aeSAaron LI 
2876*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &antenna);
2877411677aeSAaron LI 		if (rc != 0)
2878411677aeSAaron LI 			goto trunc;
2879*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("antenna %u ", antenna);
288041c99275SPeter Avalos 		break;
2881411677aeSAaron LI 		}
2882411677aeSAaron LI 
2883411677aeSAaron LI 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
2884411677aeSAaron LI 		uint8_t db_antsignal;
2885411677aeSAaron LI 
2886*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &db_antsignal);
2887411677aeSAaron LI 		if (rc != 0)
2888411677aeSAaron LI 			goto trunc;
2889*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%udB signal ", db_antsignal);
289041c99275SPeter Avalos 		break;
2891411677aeSAaron LI 		}
2892411677aeSAaron LI 
2893411677aeSAaron LI 	case IEEE80211_RADIOTAP_DB_ANTNOISE: {
2894411677aeSAaron LI 		uint8_t db_antnoise;
2895411677aeSAaron LI 
2896*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &db_antnoise);
2897411677aeSAaron LI 		if (rc != 0)
2898411677aeSAaron LI 			goto trunc;
2899*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%udB noise ", db_antnoise);
2900411677aeSAaron LI 		break;
2901411677aeSAaron LI 		}
2902411677aeSAaron LI 
2903411677aeSAaron LI 	case IEEE80211_RADIOTAP_RX_FLAGS: {
2904411677aeSAaron LI 		uint16_t rx_flags;
2905411677aeSAaron LI 
2906*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &rx_flags);
2907411677aeSAaron LI 		if (rc != 0)
2908411677aeSAaron LI 			goto trunc;
290927bfbee1SPeter Avalos 		/* Do nothing for now */
291027bfbee1SPeter Avalos 		break;
2911411677aeSAaron LI 		}
2912411677aeSAaron LI 
2913411677aeSAaron LI 	case IEEE80211_RADIOTAP_XCHANNEL: {
2914411677aeSAaron LI 		uint32_t flags;
2915411677aeSAaron LI 		uint16_t frequency;
2916411677aeSAaron LI 		uint8_t channel;
2917411677aeSAaron LI 		uint8_t maxpower;
2918411677aeSAaron LI 
2919*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint32(ndo, s, &flags);
2920411677aeSAaron LI 		if (rc != 0)
2921411677aeSAaron LI 			goto trunc;
2922*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &frequency);
2923411677aeSAaron LI 		if (rc != 0)
2924411677aeSAaron LI 			goto trunc;
2925*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &channel);
2926411677aeSAaron LI 		if (rc != 0)
2927411677aeSAaron LI 			goto trunc;
2928*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &maxpower);
2929411677aeSAaron LI 		if (rc != 0)
2930411677aeSAaron LI 			goto trunc;
2931411677aeSAaron LI 		print_chaninfo(ndo, frequency, flags, presentflags);
293227bfbee1SPeter Avalos 		break;
2933411677aeSAaron LI 		}
2934411677aeSAaron LI 
293527bfbee1SPeter Avalos 	case IEEE80211_RADIOTAP_MCS: {
2936411677aeSAaron LI 		uint8_t known;
2937411677aeSAaron LI 		uint8_t flags;
2938411677aeSAaron LI 		uint8_t mcs_index;
2939411677aeSAaron LI 		static const char *ht_bandwidth[4] = {
294027bfbee1SPeter Avalos 			"20 MHz",
294127bfbee1SPeter Avalos 			"40 MHz",
294227bfbee1SPeter Avalos 			"20 MHz (L)",
294327bfbee1SPeter Avalos 			"20 MHz (U)"
294427bfbee1SPeter Avalos 		};
294527bfbee1SPeter Avalos 		float htrate;
294627bfbee1SPeter Avalos 
2947*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &known);
2948411677aeSAaron LI 		if (rc != 0)
2949411677aeSAaron LI 			goto trunc;
2950*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &flags);
2951411677aeSAaron LI 		if (rc != 0)
2952411677aeSAaron LI 			goto trunc;
2953*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &mcs_index);
2954411677aeSAaron LI 		if (rc != 0)
2955411677aeSAaron LI 			goto trunc;
2956411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
295727bfbee1SPeter Avalos 			/*
295827bfbee1SPeter Avalos 			 * We know the MCS index.
295927bfbee1SPeter Avalos 			 */
2960411677aeSAaron LI 			if (mcs_index <= MAX_MCS_INDEX) {
296127bfbee1SPeter Avalos 				/*
296227bfbee1SPeter Avalos 				 * And it's in-range.
296327bfbee1SPeter Avalos 				 */
2964411677aeSAaron LI 				if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
296527bfbee1SPeter Avalos 					/*
296627bfbee1SPeter Avalos 					 * And we know both the bandwidth and
296727bfbee1SPeter Avalos 					 * the guard interval, so we can look
296827bfbee1SPeter Avalos 					 * up the rate.
296927bfbee1SPeter Avalos 					 */
297027bfbee1SPeter Avalos 					htrate =
2971*ed775ee7SAntonio Huete Jimenez 						ieee80211_float_htrates
2972*ed775ee7SAntonio Huete Jimenez 							[mcs_index]
2973*ed775ee7SAntonio Huete Jimenez 							[((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
2974411677aeSAaron LI 							[((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
297527bfbee1SPeter Avalos 				} else {
297627bfbee1SPeter Avalos 					/*
297727bfbee1SPeter Avalos 					 * We don't know both the bandwidth
297827bfbee1SPeter Avalos 					 * and the guard interval, so we can
297927bfbee1SPeter Avalos 					 * only report the MCS index.
298027bfbee1SPeter Avalos 					 */
298127bfbee1SPeter Avalos 					htrate = 0.0;
298227bfbee1SPeter Avalos 				}
298327bfbee1SPeter Avalos 			} else {
298427bfbee1SPeter Avalos 				/*
298527bfbee1SPeter Avalos 				 * The MCS value is out of range.
298627bfbee1SPeter Avalos 				 */
298727bfbee1SPeter Avalos 				htrate = 0.0;
298827bfbee1SPeter Avalos 			}
298927bfbee1SPeter Avalos 			if (htrate != 0.0) {
299027bfbee1SPeter Avalos 				/*
299127bfbee1SPeter Avalos 				 * We have the rate.
299227bfbee1SPeter Avalos 				 * Print it.
299327bfbee1SPeter Avalos 				 */
2994*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
299527bfbee1SPeter Avalos 			} else {
299627bfbee1SPeter Avalos 				/*
299727bfbee1SPeter Avalos 				 * We at least have the MCS index.
299827bfbee1SPeter Avalos 				 * Print it.
299927bfbee1SPeter Avalos 				 */
3000*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("MCS %u ", mcs_index);
300127bfbee1SPeter Avalos 			}
300227bfbee1SPeter Avalos 		}
3003411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
3004*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s ",
3005*ed775ee7SAntonio Huete Jimenez 				ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
300627bfbee1SPeter Avalos 		}
3007411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
3008*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s GI ",
3009411677aeSAaron LI 				(flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
3010*ed775ee7SAntonio Huete Jimenez 				"short" : "long");
301127bfbee1SPeter Avalos 		}
3012411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
3013*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s ",
3014411677aeSAaron LI 				(flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
3015*ed775ee7SAntonio Huete Jimenez 				"greenfield" : "mixed");
301627bfbee1SPeter Avalos 		}
3017411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
3018*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s FEC ",
3019411677aeSAaron LI 				(flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
3020*ed775ee7SAntonio Huete Jimenez 				"LDPC" : "BCC");
3021411677aeSAaron LI 		}
3022411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
3023*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("RX-STBC%u ",
3024*ed775ee7SAntonio Huete Jimenez 				(flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
302527bfbee1SPeter Avalos 		}
302627bfbee1SPeter Avalos 		break;
302727bfbee1SPeter Avalos 		}
3028411677aeSAaron LI 
3029411677aeSAaron LI 	case IEEE80211_RADIOTAP_AMPDU_STATUS: {
3030411677aeSAaron LI 		uint32_t reference_num;
3031411677aeSAaron LI 		uint16_t flags;
3032411677aeSAaron LI 		uint8_t delim_crc;
3033411677aeSAaron LI 		uint8_t reserved;
3034411677aeSAaron LI 
3035*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint32(ndo, s, &reference_num);
3036411677aeSAaron LI 		if (rc != 0)
3037411677aeSAaron LI 			goto trunc;
3038*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &flags);
3039411677aeSAaron LI 		if (rc != 0)
3040411677aeSAaron LI 			goto trunc;
3041*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &delim_crc);
3042411677aeSAaron LI 		if (rc != 0)
3043411677aeSAaron LI 			goto trunc;
3044*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &reserved);
3045411677aeSAaron LI 		if (rc != 0)
3046411677aeSAaron LI 			goto trunc;
3047411677aeSAaron LI 		/* Do nothing for now */
3048411677aeSAaron LI 		break;
304941c99275SPeter Avalos 		}
305041c99275SPeter Avalos 
3051411677aeSAaron LI 	case IEEE80211_RADIOTAP_VHT: {
3052411677aeSAaron LI 		uint16_t known;
3053411677aeSAaron LI 		uint8_t flags;
3054411677aeSAaron LI 		uint8_t bandwidth;
3055411677aeSAaron LI 		uint8_t mcs_nss[4];
3056411677aeSAaron LI 		uint8_t coding;
3057411677aeSAaron LI 		uint8_t group_id;
3058411677aeSAaron LI 		uint16_t partial_aid;
3059411677aeSAaron LI 		static const char *vht_bandwidth[32] = {
3060411677aeSAaron LI 			"20 MHz",
3061411677aeSAaron LI 			"40 MHz",
3062411677aeSAaron LI 			"20 MHz (L)",
3063411677aeSAaron LI 			"20 MHz (U)",
3064411677aeSAaron LI 			"80 MHz",
3065411677aeSAaron LI 			"80 MHz (L)",
3066411677aeSAaron LI 			"80 MHz (U)",
3067411677aeSAaron LI 			"80 MHz (LL)",
3068411677aeSAaron LI 			"80 MHz (LU)",
3069411677aeSAaron LI 			"80 MHz (UL)",
3070411677aeSAaron LI 			"80 MHz (UU)",
3071411677aeSAaron LI 			"160 MHz",
3072411677aeSAaron LI 			"160 MHz (L)",
3073411677aeSAaron LI 			"160 MHz (U)",
3074411677aeSAaron LI 			"160 MHz (LL)",
3075411677aeSAaron LI 			"160 MHz (LU)",
3076411677aeSAaron LI 			"160 MHz (UL)",
3077411677aeSAaron LI 			"160 MHz (UU)",
3078411677aeSAaron LI 			"160 MHz (LLL)",
3079411677aeSAaron LI 			"160 MHz (LLU)",
3080411677aeSAaron LI 			"160 MHz (LUL)",
3081411677aeSAaron LI 			"160 MHz (UUU)",
3082411677aeSAaron LI 			"160 MHz (ULL)",
3083411677aeSAaron LI 			"160 MHz (ULU)",
3084411677aeSAaron LI 			"160 MHz (UUL)",
3085411677aeSAaron LI 			"160 MHz (UUU)",
3086411677aeSAaron LI 			"unknown (26)",
3087411677aeSAaron LI 			"unknown (27)",
3088411677aeSAaron LI 			"unknown (28)",
3089411677aeSAaron LI 			"unknown (29)",
3090411677aeSAaron LI 			"unknown (30)",
3091411677aeSAaron LI 			"unknown (31)"
3092411677aeSAaron LI 		};
3093411677aeSAaron LI 
3094*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &known);
3095411677aeSAaron LI 		if (rc != 0)
3096411677aeSAaron LI 			goto trunc;
3097*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &flags);
3098411677aeSAaron LI 		if (rc != 0)
3099411677aeSAaron LI 			goto trunc;
3100*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &bandwidth);
3101411677aeSAaron LI 		if (rc != 0)
3102411677aeSAaron LI 			goto trunc;
3103411677aeSAaron LI 		for (i = 0; i < 4; i++) {
3104*ed775ee7SAntonio Huete Jimenez 			rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
3105411677aeSAaron LI 			if (rc != 0)
3106411677aeSAaron LI 				goto trunc;
3107411677aeSAaron LI 		}
3108*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &coding);
3109411677aeSAaron LI 		if (rc != 0)
3110411677aeSAaron LI 			goto trunc;
3111*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint8(ndo, s, &group_id);
3112411677aeSAaron LI 		if (rc != 0)
3113411677aeSAaron LI 			goto trunc;
3114*ed775ee7SAntonio Huete Jimenez 		rc = nd_cpack_uint16(ndo, s, &partial_aid);
3115411677aeSAaron LI 		if (rc != 0)
3116411677aeSAaron LI 			goto trunc;
3117411677aeSAaron LI 		for (i = 0; i < 4; i++) {
3118411677aeSAaron LI 			u_int nss, mcs;
3119411677aeSAaron LI 			nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
3120411677aeSAaron LI 			mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
3121411677aeSAaron LI 
3122411677aeSAaron LI 			if (nss == 0)
3123411677aeSAaron LI 				continue;
3124411677aeSAaron LI 
3125*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("User %u MCS %u ", i, mcs);
3126*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s FEC ",
3127411677aeSAaron LI 				(coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
3128*ed775ee7SAntonio Huete Jimenez 				"LDPC" : "BCC");
3129411677aeSAaron LI 		}
3130411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
3131*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s ",
3132*ed775ee7SAntonio Huete Jimenez 				vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
3133411677aeSAaron LI 		}
3134411677aeSAaron LI 		if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
3135*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s GI ",
3136411677aeSAaron LI 				(flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
3137*ed775ee7SAntonio Huete Jimenez 				"short" : "long");
3138411677aeSAaron LI 		}
3139411677aeSAaron LI 		break;
3140411677aeSAaron LI 		}
3141411677aeSAaron LI 
3142411677aeSAaron LI 	default:
3143411677aeSAaron LI 		/* this bit indicates a field whose
3144411677aeSAaron LI 		 * size we do not know, so we cannot
3145411677aeSAaron LI 		 * proceed.  Just print the bit number.
3146411677aeSAaron LI 		 */
3147*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[bit %u] ", bit);
3148411677aeSAaron LI 		return -1;
3149411677aeSAaron LI 	}
3150411677aeSAaron LI 
3151411677aeSAaron LI 	return 0;
3152411677aeSAaron LI 
3153411677aeSAaron LI trunc:
3154*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
3155411677aeSAaron LI 	return rc;
3156411677aeSAaron LI }
3157411677aeSAaron LI 
3158411677aeSAaron LI 
3159411677aeSAaron LI static int
print_in_radiotap_namespace(netdissect_options * ndo,struct cpack_state * s,uint8_t * flags,uint32_t presentflags,int bit0)3160411677aeSAaron LI print_in_radiotap_namespace(netdissect_options *ndo,
3161411677aeSAaron LI 			    struct cpack_state *s, uint8_t *flags,
3162411677aeSAaron LI 			    uint32_t presentflags, int bit0)
316341c99275SPeter Avalos {
316441c99275SPeter Avalos #define	BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
316541c99275SPeter Avalos #define	BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
316641c99275SPeter Avalos #define	BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
316741c99275SPeter Avalos #define	BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
316841c99275SPeter Avalos #define	BITNO_2(x) (((x) & 2) ? 1 : 0)
3169411677aeSAaron LI 	uint32_t present, next_present;
3170411677aeSAaron LI 	int bitno;
3171411677aeSAaron LI 	enum ieee80211_radiotap_type bit;
3172411677aeSAaron LI 	int rc;
3173411677aeSAaron LI 
3174411677aeSAaron LI 	for (present = presentflags; present; present = next_present) {
3175411677aeSAaron LI 		/*
3176411677aeSAaron LI 		 * Clear the least significant bit that is set.
3177411677aeSAaron LI 		 */
3178411677aeSAaron LI 		next_present = present & (present - 1);
3179411677aeSAaron LI 
3180411677aeSAaron LI 		/*
3181411677aeSAaron LI 		 * Get the bit number, within this presence word,
3182411677aeSAaron LI 		 * of the remaining least significant bit that
3183411677aeSAaron LI 		 * is set.
3184411677aeSAaron LI 		 */
3185411677aeSAaron LI 		bitno = BITNO_32(present ^ next_present);
3186411677aeSAaron LI 
3187411677aeSAaron LI 		/*
3188411677aeSAaron LI 		 * Stop if this is one of the "same meaning
3189411677aeSAaron LI 		 * in all presence flags" bits.
3190411677aeSAaron LI 		 */
3191411677aeSAaron LI 		if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
3192411677aeSAaron LI 			break;
3193411677aeSAaron LI 
3194411677aeSAaron LI 		/*
3195411677aeSAaron LI 		 * Get the radiotap bit number of that bit.
3196411677aeSAaron LI 		 */
3197411677aeSAaron LI 		bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
3198411677aeSAaron LI 
3199411677aeSAaron LI 		rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
3200411677aeSAaron LI 		if (rc != 0)
3201411677aeSAaron LI 			return rc;
3202411677aeSAaron LI 	}
3203411677aeSAaron LI 
3204411677aeSAaron LI 	return 0;
3205411677aeSAaron LI }
3206411677aeSAaron LI 
3207411677aeSAaron LI u_int
ieee802_11_radio_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3208411677aeSAaron LI ieee802_11_radio_print(netdissect_options *ndo,
3209411677aeSAaron LI 		       const u_char *p, u_int length, u_int caplen)
3210411677aeSAaron LI {
321127bfbee1SPeter Avalos #define	BIT(n)	(1U << n)
321241c99275SPeter Avalos #define	IS_EXTENDED(__p)	\
3213*ed775ee7SAntonio Huete Jimenez 	    (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
321441c99275SPeter Avalos 
321541c99275SPeter Avalos 	struct cpack_state cpacker;
3216411677aeSAaron LI 	const struct ieee80211_radiotap_header *hdr;
3217411677aeSAaron LI 	uint32_t presentflags;
3218*ed775ee7SAntonio Huete Jimenez 	const nd_uint32_t *presentp, *last_presentp;
3219411677aeSAaron LI 	int vendor_namespace;
3220411677aeSAaron LI 	uint8_t vendor_oui[3];
3221411677aeSAaron LI 	uint8_t vendor_subnamespace;
3222411677aeSAaron LI 	uint16_t skip_length;
322341c99275SPeter Avalos 	int bit0;
322441c99275SPeter Avalos 	u_int len;
3225411677aeSAaron LI 	uint8_t flags;
322641c99275SPeter Avalos 	int pad;
322727bfbee1SPeter Avalos 	u_int fcslen;
322841c99275SPeter Avalos 
3229*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "802.11_radio";
323041c99275SPeter Avalos 	if (caplen < sizeof(*hdr)) {
3231*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
323241c99275SPeter Avalos 		return caplen;
323341c99275SPeter Avalos 	}
323441c99275SPeter Avalos 
3235411677aeSAaron LI 	hdr = (const struct ieee80211_radiotap_header *)p;
323641c99275SPeter Avalos 
3237*ed775ee7SAntonio Huete Jimenez 	len = GET_LE_U_2(hdr->it_len);
3238411677aeSAaron LI 	if (len < sizeof(*hdr)) {
3239411677aeSAaron LI 		/*
3240411677aeSAaron LI 		 * The length is the length of the entire header, so
3241411677aeSAaron LI 		 * it must be as large as the fixed-length part of
3242411677aeSAaron LI 		 * the header.
3243411677aeSAaron LI 		 */
3244*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
324541c99275SPeter Avalos 		return caplen;
324641c99275SPeter Avalos 	}
3247411677aeSAaron LI 
3248411677aeSAaron LI 	/*
3249411677aeSAaron LI 	 * If we don't have the entire radiotap header, just give up.
3250411677aeSAaron LI 	 */
3251411677aeSAaron LI 	if (caplen < len) {
3252*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
3253411677aeSAaron LI 		return caplen;
3254411677aeSAaron LI 	}
3255*ed775ee7SAntonio Huete Jimenez 	nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
3256*ed775ee7SAntonio Huete Jimenez 	nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
325741c99275SPeter Avalos 	for (last_presentp = &hdr->it_present;
3258411677aeSAaron LI 	     (const u_char*)(last_presentp + 1) <= p + len &&
3259411677aeSAaron LI 	     IS_EXTENDED(last_presentp);
3260411677aeSAaron LI 	     last_presentp++)
3261*ed775ee7SAntonio Huete Jimenez 	  nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
326241c99275SPeter Avalos 
326341c99275SPeter Avalos 	/* are there more bitmap extensions than bytes in header? */
3264411677aeSAaron LI 	if ((const u_char*)(last_presentp + 1) > p + len) {
3265*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
326641c99275SPeter Avalos 		return caplen;
326741c99275SPeter Avalos 	}
326841c99275SPeter Avalos 
3269411677aeSAaron LI 	/*
3270411677aeSAaron LI 	 * Start out at the beginning of the default radiotap namespace.
3271411677aeSAaron LI 	 */
3272411677aeSAaron LI 	bit0 = 0;
3273411677aeSAaron LI 	vendor_namespace = 0;
3274411677aeSAaron LI 	memset(vendor_oui, 0, 3);
3275411677aeSAaron LI 	vendor_subnamespace = 0;
3276411677aeSAaron LI 	skip_length = 0;
327727bfbee1SPeter Avalos 	/* Assume no flags */
327827bfbee1SPeter Avalos 	flags = 0;
327941c99275SPeter Avalos 	/* Assume no Atheros padding between 802.11 header and body */
328041c99275SPeter Avalos 	pad = 0;
328127bfbee1SPeter Avalos 	/* Assume no FCS at end of frame */
328227bfbee1SPeter Avalos 	fcslen = 0;
3283411677aeSAaron LI 	for (presentp = &hdr->it_present; presentp <= last_presentp;
3284411677aeSAaron LI 	    presentp++) {
3285*ed775ee7SAntonio Huete Jimenez 		presentflags = GET_LE_U_4(presentp);
328627bfbee1SPeter Avalos 
3287411677aeSAaron LI 		/*
3288411677aeSAaron LI 		 * If this is a vendor namespace, we don't handle it.
3289411677aeSAaron LI 		 */
3290411677aeSAaron LI 		if (vendor_namespace) {
3291411677aeSAaron LI 			/*
3292411677aeSAaron LI 			 * Skip past the stuff we don't understand.
3293411677aeSAaron LI 			 * If we add support for any vendor namespaces,
3294411677aeSAaron LI 			 * it'd be added here; use vendor_oui and
3295411677aeSAaron LI 			 * vendor_subnamespace to interpret the fields.
3296411677aeSAaron LI 			 */
3297*ed775ee7SAntonio Huete Jimenez 			if (nd_cpack_advance(&cpacker, skip_length) != 0) {
3298411677aeSAaron LI 				/*
3299411677aeSAaron LI 				 * Ran out of space in the packet.
3300411677aeSAaron LI 				 */
3301411677aeSAaron LI 				break;
3302411677aeSAaron LI 			}
330327bfbee1SPeter Avalos 
3304411677aeSAaron LI 			/*
3305411677aeSAaron LI 			 * We've skipped it all; nothing more to
3306411677aeSAaron LI 			 * skip.
3307411677aeSAaron LI 			 */
3308411677aeSAaron LI 			skip_length = 0;
3309411677aeSAaron LI 		} else {
3310411677aeSAaron LI 			if (print_in_radiotap_namespace(ndo, &cpacker,
3311411677aeSAaron LI 			    &flags, presentflags, bit0) != 0) {
3312411677aeSAaron LI 				/*
3313411677aeSAaron LI 				 * Fatal error - can't process anything
3314411677aeSAaron LI 				 * more in the radiotap header.
3315411677aeSAaron LI 				 */
3316411677aeSAaron LI 				break;
331741c99275SPeter Avalos 			}
331841c99275SPeter Avalos 		}
331927bfbee1SPeter Avalos 
3320411677aeSAaron LI 		/*
3321411677aeSAaron LI 		 * Handle the namespace switch bits; we've already handled
3322411677aeSAaron LI 		 * the extension bit in all but the last word above.
3323411677aeSAaron LI 		 */
3324411677aeSAaron LI 		switch (presentflags &
3325411677aeSAaron LI 		    (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
3326411677aeSAaron LI 
3327411677aeSAaron LI 		case 0:
3328411677aeSAaron LI 			/*
3329411677aeSAaron LI 			 * We're not changing namespaces.
3330411677aeSAaron LI 			 * advance to the next 32 bits in the current
3331411677aeSAaron LI 			 * namespace.
3332411677aeSAaron LI 			 */
3333411677aeSAaron LI 			bit0 += 32;
3334411677aeSAaron LI 			break;
3335411677aeSAaron LI 
3336411677aeSAaron LI 		case BIT(IEEE80211_RADIOTAP_NAMESPACE):
3337411677aeSAaron LI 			/*
3338411677aeSAaron LI 			 * We're switching to the radiotap namespace.
3339411677aeSAaron LI 			 * Reset the presence-bitmap index to 0, and
3340411677aeSAaron LI 			 * reset the namespace to the default radiotap
3341411677aeSAaron LI 			 * namespace.
3342411677aeSAaron LI 			 */
3343411677aeSAaron LI 			bit0 = 0;
3344411677aeSAaron LI 			vendor_namespace = 0;
3345411677aeSAaron LI 			memset(vendor_oui, 0, 3);
3346411677aeSAaron LI 			vendor_subnamespace = 0;
3347411677aeSAaron LI 			skip_length = 0;
3348411677aeSAaron LI 			break;
3349411677aeSAaron LI 
3350411677aeSAaron LI 		case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
3351411677aeSAaron LI 			/*
3352411677aeSAaron LI 			 * We're switching to a vendor namespace.
3353411677aeSAaron LI 			 * Reset the presence-bitmap index to 0,
3354411677aeSAaron LI 			 * note that we're in a vendor namespace,
3355411677aeSAaron LI 			 * and fetch the fields of the Vendor Namespace
3356411677aeSAaron LI 			 * item.
3357411677aeSAaron LI 			 */
3358411677aeSAaron LI 			bit0 = 0;
3359411677aeSAaron LI 			vendor_namespace = 1;
3360*ed775ee7SAntonio Huete Jimenez 			if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
3361*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
3362411677aeSAaron LI 				break;
3363411677aeSAaron LI 			}
3364*ed775ee7SAntonio Huete Jimenez 			if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
3365*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
3366411677aeSAaron LI 				break;
3367411677aeSAaron LI 			}
3368*ed775ee7SAntonio Huete Jimenez 			if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
3369*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
3370411677aeSAaron LI 				break;
3371411677aeSAaron LI 			}
3372*ed775ee7SAntonio Huete Jimenez 			if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
3373*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
3374411677aeSAaron LI 				break;
3375411677aeSAaron LI 			}
3376*ed775ee7SAntonio Huete Jimenez 			if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
3377*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
3378411677aeSAaron LI 				break;
3379411677aeSAaron LI 			}
3380*ed775ee7SAntonio Huete Jimenez 			if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
3381*ed775ee7SAntonio Huete Jimenez 				nd_print_trunc(ndo);
3382411677aeSAaron LI 				break;
3383411677aeSAaron LI 			}
3384411677aeSAaron LI 			break;
3385411677aeSAaron LI 
3386411677aeSAaron LI 		default:
3387411677aeSAaron LI 			/*
3388411677aeSAaron LI 			 * Illegal combination.  The behavior in this
3389411677aeSAaron LI 			 * case is undefined by the radiotap spec; we
3390411677aeSAaron LI 			 * just ignore both bits.
3391411677aeSAaron LI 			 */
3392411677aeSAaron LI 			break;
3393411677aeSAaron LI 		}
3394411677aeSAaron LI 	}
3395411677aeSAaron LI 
339627bfbee1SPeter Avalos 	if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
339727bfbee1SPeter Avalos 		pad = 1;	/* Atheros padding */
339827bfbee1SPeter Avalos 	if (flags & IEEE80211_RADIOTAP_F_FCS)
339927bfbee1SPeter Avalos 		fcslen = 4;	/* FCS at end of packet */
3400411677aeSAaron LI 	return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
340127bfbee1SPeter Avalos 	    fcslen);
340241c99275SPeter Avalos #undef BITNO_32
340341c99275SPeter Avalos #undef BITNO_16
340441c99275SPeter Avalos #undef BITNO_8
340541c99275SPeter Avalos #undef BITNO_4
340641c99275SPeter Avalos #undef BITNO_2
340741c99275SPeter Avalos #undef BIT
340841c99275SPeter Avalos }
340941c99275SPeter Avalos 
341041c99275SPeter Avalos static u_int
ieee802_11_radio_avs_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3411*ed775ee7SAntonio Huete Jimenez ieee802_11_radio_avs_print(netdissect_options *ndo,
3412411677aeSAaron LI 			   const u_char *p, u_int length, u_int caplen)
341341c99275SPeter Avalos {
3414411677aeSAaron LI 	uint32_t caphdr_len;
341541c99275SPeter Avalos 
3416*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "802.11_radio_avs";
3417ea7b4bf5SPeter Avalos 	if (caplen < 8) {
3418*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
3419ea7b4bf5SPeter Avalos 		return caplen;
3420ea7b4bf5SPeter Avalos 	}
3421ea7b4bf5SPeter Avalos 
3422*ed775ee7SAntonio Huete Jimenez 	caphdr_len = GET_BE_U_4(p + 4);
342341c99275SPeter Avalos 	if (caphdr_len < 8) {
342441c99275SPeter Avalos 		/*
342541c99275SPeter Avalos 		 * Yow!  The capture header length is claimed not
342641c99275SPeter Avalos 		 * to be large enough to include even the version
342741c99275SPeter Avalos 		 * cookie or capture header length!
342841c99275SPeter Avalos 		 */
3429*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
343041c99275SPeter Avalos 		return caplen;
343141c99275SPeter Avalos 	}
343241c99275SPeter Avalos 
343341c99275SPeter Avalos 	if (caplen < caphdr_len) {
3434*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
343541c99275SPeter Avalos 		return caplen;
343641c99275SPeter Avalos 	}
343741c99275SPeter Avalos 
3438411677aeSAaron LI 	return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
343927bfbee1SPeter Avalos 	    length - caphdr_len, caplen - caphdr_len, 0, 0);
344041c99275SPeter Avalos }
344141c99275SPeter Avalos 
344241c99275SPeter Avalos #define PRISM_HDR_LEN		144
344341c99275SPeter Avalos 
3444ea7b4bf5SPeter Avalos #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
344541c99275SPeter Avalos #define WLANCAP_MAGIC_COOKIE_V1	0x80211001
3446ea7b4bf5SPeter Avalos #define WLANCAP_MAGIC_COOKIE_V2	0x80211002
344741c99275SPeter Avalos 
344841c99275SPeter Avalos /*
344941c99275SPeter Avalos  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
345041c99275SPeter Avalos  * containing information such as radio information, which we
345141c99275SPeter Avalos  * currently ignore.
345241c99275SPeter Avalos  *
3453ea7b4bf5SPeter Avalos  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
3454ea7b4bf5SPeter Avalos  * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
3455ea7b4bf5SPeter Avalos  * (currently, on Linux, there's no ARPHRD_ type for
3456ea7b4bf5SPeter Avalos  * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
3457ea7b4bf5SPeter Avalos  * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
3458ea7b4bf5SPeter Avalos  * the AVS header, and the first 4 bytes of the header are used to
3459ea7b4bf5SPeter Avalos  * indicate whether it's a Prism header or an AVS header).
346041c99275SPeter Avalos  */
3461*ed775ee7SAntonio Huete Jimenez void
prism_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3462411677aeSAaron LI prism_if_print(netdissect_options *ndo,
3463411677aeSAaron LI 	       const struct pcap_pkthdr *h, const u_char *p)
346441c99275SPeter Avalos {
346541c99275SPeter Avalos 	u_int caplen = h->caplen;
346641c99275SPeter Avalos 	u_int length = h->len;
3467411677aeSAaron LI 	uint32_t msgcode;
346841c99275SPeter Avalos 
3469*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "prism";
347041c99275SPeter Avalos 	if (caplen < 4) {
3471*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
3472*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += caplen;
3473*ed775ee7SAntonio Huete Jimenez 		return;
347441c99275SPeter Avalos 	}
347541c99275SPeter Avalos 
3476*ed775ee7SAntonio Huete Jimenez 	msgcode = GET_BE_U_4(p);
3477ea7b4bf5SPeter Avalos 	if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
3478*ed775ee7SAntonio Huete Jimenez 	    msgcode == WLANCAP_MAGIC_COOKIE_V2) {
3479*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
3480*ed775ee7SAntonio Huete Jimenez 		return;
3481*ed775ee7SAntonio Huete Jimenez 	}
348241c99275SPeter Avalos 
348341c99275SPeter Avalos 	if (caplen < PRISM_HDR_LEN) {
3484*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
3485*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += caplen;
3486*ed775ee7SAntonio Huete Jimenez 		return;
348741c99275SPeter Avalos 	}
348841c99275SPeter Avalos 
3489*ed775ee7SAntonio Huete Jimenez 	p += PRISM_HDR_LEN;
3490*ed775ee7SAntonio Huete Jimenez 	length -= PRISM_HDR_LEN;
3491*ed775ee7SAntonio Huete Jimenez 	caplen -= PRISM_HDR_LEN;
3492*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
3493*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
349441c99275SPeter Avalos }
349541c99275SPeter Avalos 
349641c99275SPeter Avalos /*
349741c99275SPeter Avalos  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
3498ea7b4bf5SPeter Avalos  * header, containing information such as radio information.
349941c99275SPeter Avalos  */
3500*ed775ee7SAntonio Huete Jimenez void
ieee802_11_radio_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3501411677aeSAaron LI ieee802_11_radio_if_print(netdissect_options *ndo,
3502411677aeSAaron LI 			  const struct pcap_pkthdr *h, const u_char *p)
350341c99275SPeter Avalos {
3504*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "802.11_radio";
3505*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
350641c99275SPeter Avalos }
350741c99275SPeter Avalos 
3508ea7b4bf5SPeter Avalos /*
3509ea7b4bf5SPeter Avalos  * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
3510ea7b4bf5SPeter Avalos  * extra header, containing information such as radio information,
3511ea7b4bf5SPeter Avalos  * which we currently ignore.
3512ea7b4bf5SPeter Avalos  */
3513*ed775ee7SAntonio Huete Jimenez void
ieee802_11_radio_avs_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3514411677aeSAaron LI ieee802_11_radio_avs_if_print(netdissect_options *ndo,
3515411677aeSAaron LI 			      const struct pcap_pkthdr *h, const u_char *p)
3516ea7b4bf5SPeter Avalos {
3517*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "802.11_radio_avs";
3518*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
351941c99275SPeter Avalos }
3520