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