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