xref: /openbsd/usr.sbin/tcpdump/print-802_11.c (revision 958b7e45)
1*958b7e45Ssthen /*	$OpenBSD: print-802_11.c,v 1.20 2015/07/16 23:34:54 sthen Exp $	*/
212a08440Sreyk 
312a08440Sreyk /*
42c56d0d6Sreyk  * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org>
512a08440Sreyk  *
612a08440Sreyk  * Permission to use, copy, modify, and distribute this software for any
712a08440Sreyk  * purpose with or without fee is hereby granted, provided that the above
812a08440Sreyk  * copyright notice and this permission notice appear in all copies.
912a08440Sreyk  *
1012a08440Sreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1112a08440Sreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1212a08440Sreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1312a08440Sreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1412a08440Sreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1512a08440Sreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1612a08440Sreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1712a08440Sreyk  */
1812a08440Sreyk 
1912a08440Sreyk #include <sys/time.h>
2012a08440Sreyk #include <sys/socket.h>
2112a08440Sreyk #include <sys/file.h>
2212a08440Sreyk #include <sys/ioctl.h>
2312a08440Sreyk 
2412a08440Sreyk #include <net/if.h>
2512a08440Sreyk 
2612a08440Sreyk #include <netinet/in.h>
2712a08440Sreyk #include <netinet/if_ether.h>
2812a08440Sreyk 
2912a08440Sreyk #include <net80211/ieee80211.h>
3012a08440Sreyk #include <net80211/ieee80211_radiotap.h>
3112a08440Sreyk 
3212a08440Sreyk #include <pcap.h>
3312a08440Sreyk #include <stdio.h>
3412a08440Sreyk #include <string.h>
3512a08440Sreyk 
3612a08440Sreyk #include "addrtoname.h"
3712a08440Sreyk #include "interface.h"
3812a08440Sreyk 
3912a08440Sreyk const char *ieee80211_mgt_subtype_name[] = {
4012a08440Sreyk 	"association request",
4112a08440Sreyk 	"association response",
4212a08440Sreyk 	"reassociation request",
4312a08440Sreyk 	"reassociation response",
4412a08440Sreyk 	"probe request",
4512a08440Sreyk 	"probe response",
4612a08440Sreyk 	"reserved#6",
4712a08440Sreyk 	"reserved#7",
4812a08440Sreyk 	"beacon",
4912a08440Sreyk 	"atim",
5012a08440Sreyk 	"disassociation",
5112a08440Sreyk 	"authentication",
5212a08440Sreyk 	"deauthentication",
53ab7e388eSclaudio 	"action",
54ab7e388eSclaudio 	"action noack",
5512a08440Sreyk 	"reserved#15"
5612a08440Sreyk };
5712a08440Sreyk 
58ab7e388eSclaudio const char *ieee80211_data_subtype_name[] = {
59ab7e388eSclaudio 	"data",
60ab7e388eSclaudio 	"data cf ack",
61ab7e388eSclaudio 	"data cf poll",
62ab7e388eSclaudio 	"data cf poll ack",
63ab7e388eSclaudio 	"no-data",
64ab7e388eSclaudio 	"no-data cf poll",
65ab7e388eSclaudio 	"no-data cf ack",
66ab7e388eSclaudio 	"no-data cf poll ack",
67ab7e388eSclaudio 	"QoS data",
68ab7e388eSclaudio 	"QoS data cf ack",
69ab7e388eSclaudio 	"QoS data cf poll",
70ab7e388eSclaudio 	"QoS data cf poll ack",
71ab7e388eSclaudio 	"QoS no-data",
72ab7e388eSclaudio 	"QoS no-data cf poll",
73ab7e388eSclaudio 	"QoS no-data cf ack",
74ab7e388eSclaudio 	"QoS no-data cf poll ack"
75ab7e388eSclaudio };
76ab7e388eSclaudio 
7712a08440Sreyk int	 ieee80211_hdr(struct ieee80211_frame *);
78b72abdefSreyk int	 ieee80211_data(struct ieee80211_frame *, u_int);
7912a08440Sreyk void	 ieee80211_print_element(u_int8_t *, u_int);
8012a08440Sreyk void	 ieee80211_print_essid(u_int8_t *, u_int);
811e3bf20aSstsp void	 ieee80211_print_htcaps(u_int8_t *, u_int);
8212a08440Sreyk int	 ieee80211_elements(struct ieee80211_frame *, u_int);
8312a08440Sreyk int	 ieee80211_frame(struct ieee80211_frame *, u_int);
8412a08440Sreyk int	 ieee80211_print(struct ieee80211_frame *, u_int);
8512a08440Sreyk u_int	 ieee80211_any2ieee(u_int, u_int);
8618786664Sclaudio void	 ieee80211_reason(u_int16_t);
8712a08440Sreyk 
8812a08440Sreyk #define TCARR(a)	TCHECK2(*a, sizeof(a))
8912a08440Sreyk 
90c79cf170Sreyk int ieee80211_encap = 0;
91c79cf170Sreyk 
9212a08440Sreyk int
9312a08440Sreyk ieee80211_hdr(struct ieee80211_frame *wh)
9412a08440Sreyk {
9512a08440Sreyk 	struct ieee80211_frame_addr4 *w4;
9612a08440Sreyk 
9712a08440Sreyk 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
9812a08440Sreyk 	case IEEE80211_FC1_DIR_NODS:
9912a08440Sreyk 		TCARR(wh->i_addr2);
10012a08440Sreyk 		printf("%s", etheraddr_string(wh->i_addr2));
10112a08440Sreyk 		TCARR(wh->i_addr1);
10212a08440Sreyk 		printf(" > %s", etheraddr_string(wh->i_addr1));
10312a08440Sreyk 		TCARR(wh->i_addr3);
10412a08440Sreyk 		printf(", bssid %s", etheraddr_string(wh->i_addr3));
10512a08440Sreyk 		break;
10612a08440Sreyk 	case IEEE80211_FC1_DIR_TODS:
10712a08440Sreyk 		TCARR(wh->i_addr2);
10812a08440Sreyk 		printf("%s", etheraddr_string(wh->i_addr2));
10912a08440Sreyk 		TCARR(wh->i_addr3);
11012a08440Sreyk 		printf(" > %s", etheraddr_string(wh->i_addr3));
11112a08440Sreyk 		TCARR(wh->i_addr1);
11212a08440Sreyk 		printf(", bssid %s, > DS", etheraddr_string(wh->i_addr1));
11312a08440Sreyk 		break;
11412a08440Sreyk 	case IEEE80211_FC1_DIR_FROMDS:
11512a08440Sreyk 		TCARR(wh->i_addr3);
11612a08440Sreyk 		printf("%s", etheraddr_string(wh->i_addr3));
11712a08440Sreyk 		TCARR(wh->i_addr1);
11812a08440Sreyk 		printf(" > %s", etheraddr_string(wh->i_addr1));
11912a08440Sreyk 		TCARR(wh->i_addr2);
12012a08440Sreyk 		printf(", bssid %s, DS >", etheraddr_string(wh->i_addr2));
12112a08440Sreyk 		break;
12212a08440Sreyk 	case IEEE80211_FC1_DIR_DSTODS:
12312a08440Sreyk 		w4 = (struct ieee80211_frame_addr4 *) wh;
12412a08440Sreyk 		TCARR(w4->i_addr4);
12512a08440Sreyk 		printf("%s", etheraddr_string(w4->i_addr4));
12612a08440Sreyk 		TCARR(w4->i_addr3);
12712a08440Sreyk 		printf(" > %s", etheraddr_string(w4->i_addr3));
12812a08440Sreyk 		TCARR(w4->i_addr2);
12912a08440Sreyk 		printf(", bssid %s", etheraddr_string(w4->i_addr2));
13012a08440Sreyk 		TCARR(w4->i_addr1);
13112a08440Sreyk 		printf(" > %s, DS > DS", etheraddr_string(w4->i_addr1));
13212a08440Sreyk 		break;
13312a08440Sreyk 	}
13412a08440Sreyk 	if (vflag) {
135cce1ba42Sclaudio 		u_int16_t seq;
13612a08440Sreyk 		TCARR(wh->i_seq);
137cce1ba42Sclaudio 		bcopy(wh->i_seq, &seq, sizeof(u_int16_t));
138cce1ba42Sclaudio 		printf(" (seq %u): ", letoh16(seq));
13912a08440Sreyk 	} else
14012a08440Sreyk 		printf(": ");
14112a08440Sreyk 
14212a08440Sreyk 	return (0);
14312a08440Sreyk 
14412a08440Sreyk  trunc:
14512a08440Sreyk 	/* Truncated elements in frame */
14612a08440Sreyk 	return (1);
14712a08440Sreyk }
14812a08440Sreyk 
149b72abdefSreyk int
150b72abdefSreyk ieee80211_data(struct ieee80211_frame *wh, u_int len)
151b72abdefSreyk {
152b72abdefSreyk 	u_int8_t *t = (u_int8_t *)wh;
153d49cb46eScanacar 	struct ieee80211_frame_addr4 *w4;
154b72abdefSreyk 	u_int datalen;
15593cbfc44Sstsp 	int data = !(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_NODATA);
156ab7e388eSclaudio 	u_char *esrc = NULL, *edst = NULL;
157b72abdefSreyk 
158d49cb46eScanacar 	TCHECK(*wh);
159b72abdefSreyk 	t += sizeof(struct ieee80211_frame);
160b72abdefSreyk 	datalen = len - sizeof(struct ieee80211_frame);
161b72abdefSreyk 
162b72abdefSreyk 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
163b72abdefSreyk 	case IEEE80211_FC1_DIR_TODS:
164ab7e388eSclaudio 		esrc = wh->i_addr2;
165ab7e388eSclaudio 		edst = wh->i_addr3;
166b72abdefSreyk 		break;
167b72abdefSreyk 	case IEEE80211_FC1_DIR_FROMDS:
168ab7e388eSclaudio 		esrc = wh->i_addr3;
169ab7e388eSclaudio 		edst = wh->i_addr1;
170b72abdefSreyk 		break;
171b72abdefSreyk 	case IEEE80211_FC1_DIR_NODS:
172ab7e388eSclaudio 		esrc = wh->i_addr2;
173ab7e388eSclaudio 		edst = wh->i_addr1;
174d49cb46eScanacar 		break;
175b72abdefSreyk 	case IEEE80211_FC1_DIR_DSTODS:
176d49cb46eScanacar 		w4 = (struct ieee80211_frame_addr4 *) wh;
177d49cb46eScanacar 		TCHECK(*w4);
178d49cb46eScanacar 		t = (u_int8_t *) (w4 + 1);
179d49cb46eScanacar 		datalen = len - sizeof(*w4);
180ab7e388eSclaudio 		esrc = w4->i_addr4;
181ab7e388eSclaudio 		edst = w4->i_addr3;
182b72abdefSreyk 		break;
183b72abdefSreyk 	}
184b72abdefSreyk 
185ab7e388eSclaudio 	if (data && esrc)
186ab7e388eSclaudio 		llc_print(t, datalen, datalen, esrc, edst);
187ab7e388eSclaudio 	else if (eflag && esrc)
188ab7e388eSclaudio 		printf("%s > %s",
189ab7e388eSclaudio 		    etheraddr_string(esrc), etheraddr_string(edst));
190ab7e388eSclaudio 
191b72abdefSreyk 	return (0);
192b72abdefSreyk 
193b72abdefSreyk  trunc:
194b72abdefSreyk 	/* Truncated elements in frame */
195b72abdefSreyk 	return (1);
196b72abdefSreyk }
197b72abdefSreyk 
19812a08440Sreyk /* Caller checks len */
19912a08440Sreyk void
20012a08440Sreyk ieee80211_print_element(u_int8_t *data, u_int len)
20112a08440Sreyk {
20212a08440Sreyk 	u_int8_t *p;
2039cbdb746Sderaadt 	int i;
20412a08440Sreyk 
20512a08440Sreyk 	printf(" 0x");
2069cbdb746Sderaadt 	for (i = 0, p = data; i < len; i++, p++)
20712a08440Sreyk 		printf("%02x", *p);
20812a08440Sreyk }
20912a08440Sreyk 
21012a08440Sreyk /* Caller checks len */
21112a08440Sreyk void
21212a08440Sreyk ieee80211_print_essid(u_int8_t *essid, u_int len)
21312a08440Sreyk {
21412a08440Sreyk 	u_int8_t *p;
2159cbdb746Sderaadt 	int i;
21612a08440Sreyk 
21712a08440Sreyk 	if (len > IEEE80211_NWID_LEN)
21812a08440Sreyk 		len = IEEE80211_NWID_LEN;
21912a08440Sreyk 
22012a08440Sreyk 	/* determine printable or not */
22112a08440Sreyk 	for (i = 0, p = essid; i < len; i++, p++) {
22212a08440Sreyk 		if (*p < ' ' || *p > 0x7e)
22312a08440Sreyk 			break;
22412a08440Sreyk 	}
22512a08440Sreyk 	if (i == len) {
22612a08440Sreyk 		printf(" (");
22712a08440Sreyk 		for (i = 0, p = essid; i < len; i++, p++)
22812a08440Sreyk 			putchar(*p);
22912a08440Sreyk 		putchar(')');
2309cbdb746Sderaadt 	} else
23112a08440Sreyk 		ieee80211_print_element(essid, len);
23212a08440Sreyk }
23312a08440Sreyk 
2341e3bf20aSstsp /* Caller checks len */
2351e3bf20aSstsp void
2361e3bf20aSstsp ieee80211_print_htcaps(u_int8_t *data, u_int len)
2371e3bf20aSstsp {
2381e3bf20aSstsp 	u_int16_t htcaps;
2391e3bf20aSstsp 	int smps, rxstbc;
2401e3bf20aSstsp 
2411e3bf20aSstsp 	if (len < 2) {
2421e3bf20aSstsp 		ieee80211_print_element(data, len);
2431e3bf20aSstsp 		return;
2441e3bf20aSstsp 	}
2451e3bf20aSstsp 
2461e3bf20aSstsp 	htcaps = (data[0]) | (data[1] << 8);
2471e3bf20aSstsp 	printf("=<");
2481e3bf20aSstsp 
2491e3bf20aSstsp 	/* channel width */
2501e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_CBW20_40)
2511e3bf20aSstsp 		printf("20/40MHz");
2521e3bf20aSstsp 	else
2531e3bf20aSstsp 		printf("20MHz");
2541e3bf20aSstsp 
2551e3bf20aSstsp 	/* LDPC coding */
2561e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_LDPC)
2571e3bf20aSstsp 		printf(",LDPC");
2581e3bf20aSstsp 
2591e3bf20aSstsp 	/* spatial multiplexing power save mode */
2601e3bf20aSstsp 	smps = (htcaps & IEEE80211_HTCAP_SMPS_MASK)
2611e3bf20aSstsp 	    >> IEEE80211_HTCAP_SMPS_SHIFT;
2621e3bf20aSstsp 	if (smps == 0)
2631e3bf20aSstsp 		printf(",SMPS static");
2641e3bf20aSstsp 	else if (smps == 1)
2651e3bf20aSstsp 		printf(",SMPS dynamic");
2661e3bf20aSstsp 
2671e3bf20aSstsp 	/* 11n greenfield mode */
2681e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_GF)
2691e3bf20aSstsp 		printf(",greenfield");
2701e3bf20aSstsp 
2711e3bf20aSstsp 	/* short guard interval */
2721e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_SGI20)
2731e3bf20aSstsp 		printf(",SGI@20MHz");
2741e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_SGI40)
2751e3bf20aSstsp 		printf(",SGI@40MHz");
2761e3bf20aSstsp 
2771e3bf20aSstsp 	/* space-time block coding */
2781e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_TXSTBC)
2791e3bf20aSstsp 		printf(",TXSTBC");
2801e3bf20aSstsp 	rxstbc = (htcaps & IEEE80211_HTCAP_RXSTBC_MASK)
2811e3bf20aSstsp 	    >> IEEE80211_HTCAP_RXSTBC_SHIFT;
2821e3bf20aSstsp 	if (rxstbc > 0 && rxstbc < 4)
2831e3bf20aSstsp 		printf(",RXSTBC %d stream", rxstbc);
2841e3bf20aSstsp 
2851e3bf20aSstsp 	/* delayed block-ack */
2861e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_DELAYEDBA)
2871e3bf20aSstsp 		printf(",delayed BA");
2881e3bf20aSstsp 
2891e3bf20aSstsp 	/* max A-MSDU length */
2901e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_AMSDU7935)
2911e3bf20aSstsp 		printf(",A-MSDU 7935");
2921e3bf20aSstsp 	else
2931e3bf20aSstsp 		printf(",A-MSDU 3839");
2941e3bf20aSstsp 
2951e3bf20aSstsp 	/* DSSS/CCK in 40MHz mode */
2961e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_DSSSCCK40)
2971e3bf20aSstsp 		printf(",DSSS/CCK@40MHz");
2981e3bf20aSstsp 
2991e3bf20aSstsp 	/* 40MHz intolerant */
3001e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_40INTOLERANT)
3011e3bf20aSstsp 		printf(",40MHz intolerant");
3021e3bf20aSstsp 
3031e3bf20aSstsp 	/* L-SIG TXOP protection */
3041e3bf20aSstsp 	if (htcaps & IEEE80211_HTCAP_LSIGTXOPPROT)
3051e3bf20aSstsp 		printf(",L-SIG TXOP prot");
3061e3bf20aSstsp 
3071e3bf20aSstsp 	printf(">");
3081e3bf20aSstsp }
3091e3bf20aSstsp 
31012a08440Sreyk int
31112a08440Sreyk ieee80211_elements(struct ieee80211_frame *wh, u_int flen)
31212a08440Sreyk {
31312a08440Sreyk 	u_int8_t *buf, *frm;
314cce1ba42Sclaudio 	u_int64_t tstamp;
315cce1ba42Sclaudio 	u_int16_t bintval, capinfo;
31612a08440Sreyk 	int i;
31712a08440Sreyk 
31812a08440Sreyk 	buf = (u_int8_t *)wh;
31912a08440Sreyk 	frm = (u_int8_t *)&wh[1];
32012a08440Sreyk 
3210a05c5bfSreyk 	TCHECK2(*frm, 8);
322cce1ba42Sclaudio 	bcopy(frm, &tstamp, sizeof(u_int64_t));
32312a08440Sreyk 	frm += 8;
32412a08440Sreyk 
32512a08440Sreyk 	if (vflag > 1)
326cce1ba42Sclaudio 		printf(", timestamp %llu", letoh64(tstamp));
32712a08440Sreyk 
3280a05c5bfSreyk 	TCHECK2(*frm, 2);
329cce1ba42Sclaudio 	bcopy(frm, &bintval, sizeof(u_int16_t));
33012a08440Sreyk 	frm += 2;
33112a08440Sreyk 
33212a08440Sreyk 	if (vflag > 1)
333cce1ba42Sclaudio 		printf(", interval %u", letoh16(bintval));
33412a08440Sreyk 
3350a05c5bfSreyk 	TCHECK2(*frm, 2);
336cce1ba42Sclaudio 	bcopy(frm, &capinfo, sizeof(u_int16_t));
33712a08440Sreyk 	frm += 2;
33812a08440Sreyk 
33912a08440Sreyk 	if (vflag)
340cce1ba42Sclaudio 		printb(", caps", letoh16(capinfo),
34112a08440Sreyk 		    IEEE80211_CAPINFO_BITS);
34212a08440Sreyk 
34312a08440Sreyk 	while (TTEST2(*frm, 2)) {
34412a08440Sreyk 		u_int len = frm[1];
34512a08440Sreyk 		u_int8_t *data = frm + 2;
34612a08440Sreyk 
34712a08440Sreyk 		if (!TTEST2(*data, len))
34812a08440Sreyk 			break;
34912a08440Sreyk 
35012a08440Sreyk #define ELEM_CHECK(l)	if (len != l) break
35112a08440Sreyk 
35212a08440Sreyk 		switch (*frm) {
35312a08440Sreyk 		case IEEE80211_ELEMID_SSID:
35412a08440Sreyk 			printf(", ssid");
35512a08440Sreyk 			ieee80211_print_essid(data, len);
35612a08440Sreyk 			break;
35712a08440Sreyk 		case IEEE80211_ELEMID_RATES:
35812a08440Sreyk 			printf(", rates");
35912a08440Sreyk 			if (!vflag)
36012a08440Sreyk 				break;
36112a08440Sreyk 			for (i = len; i > 0; i--, data++)
36212a08440Sreyk 				printf(" %uM",
36312a08440Sreyk 				    (data[0] & IEEE80211_RATE_VAL) / 2);
36412a08440Sreyk 			break;
36512a08440Sreyk 		case IEEE80211_ELEMID_FHPARMS:
36612a08440Sreyk 			ELEM_CHECK(5);
36712a08440Sreyk 			printf(", fh (dwell %u, chan %u, index %u)",
36812a08440Sreyk 			    (data[1] << 8) | data[0],
36912a08440Sreyk 			    (data[2] - 1) * 80 + data[3],	/* FH_CHAN */
37012a08440Sreyk 			    data[4]);
37112a08440Sreyk 			break;
37212a08440Sreyk 		case IEEE80211_ELEMID_DSPARMS:
37312a08440Sreyk 			ELEM_CHECK(1);
37412a08440Sreyk 			printf(", ds");
37512a08440Sreyk 			if (vflag)
37612a08440Sreyk 				printf(" (chan %u)", data[0]);
37712a08440Sreyk 			break;
37812a08440Sreyk 		case IEEE80211_ELEMID_CFPARMS:
37912a08440Sreyk 			printf(", cf");
38012a08440Sreyk 			if (vflag)
38112a08440Sreyk 				ieee80211_print_element(data, len);
38212a08440Sreyk 			break;
38312a08440Sreyk 		case IEEE80211_ELEMID_TIM:
38412a08440Sreyk 			printf(", tim");
38512a08440Sreyk 			if (vflag)
38612a08440Sreyk 				ieee80211_print_element(data, len);
38712a08440Sreyk 			break;
38812a08440Sreyk 		case IEEE80211_ELEMID_IBSSPARMS:
38912a08440Sreyk 			printf(", ibss");
39012a08440Sreyk 			if (vflag)
39112a08440Sreyk 				ieee80211_print_element(data, len);
39212a08440Sreyk 			break;
39312a08440Sreyk 		case IEEE80211_ELEMID_COUNTRY:
39412a08440Sreyk 			printf(", country");
39512a08440Sreyk 			for (i = len; i > 0; i--, data++)
39612a08440Sreyk 				printf(" %u", data[0]);
39712a08440Sreyk 			break;
39812a08440Sreyk 		case IEEE80211_ELEMID_CHALLENGE:
39912a08440Sreyk 			printf(", challenge");
40012a08440Sreyk 			if (vflag)
40112a08440Sreyk 				ieee80211_print_element(data, len);
40212a08440Sreyk 			break;
403738acb58Ssthen 		case IEEE80211_ELEMID_CSA:
404*958b7e45Ssthen 			ELEM_CHECK(3);
405738acb58Ssthen 			printf(", csa (chan %u count %u%s)", data[1], data[2],
406738acb58Ssthen 			    (data[0] == 1) ? " noTX" : "");
407738acb58Ssthen 			break;
40812a08440Sreyk 		case IEEE80211_ELEMID_ERP:
40912a08440Sreyk 			printf(", erp");
41012a08440Sreyk 			if (vflag)
41112a08440Sreyk 				ieee80211_print_element(data, len);
41212a08440Sreyk 			break;
41312a08440Sreyk 		case IEEE80211_ELEMID_RSN:
41412a08440Sreyk 			printf(", rsn");
41512a08440Sreyk 			if (vflag)
41612a08440Sreyk 				ieee80211_print_element(data, len);
41712a08440Sreyk 			break;
41812a08440Sreyk 		case IEEE80211_ELEMID_XRATES:
41912a08440Sreyk 			printf(", xrates");
42012a08440Sreyk 			if (!vflag)
42112a08440Sreyk 				break;
42212a08440Sreyk 			for (i = len; i > 0; i--, data++)
42312a08440Sreyk 				printf(" %uM",
42412a08440Sreyk 				    (data[0] & IEEE80211_RATE_VAL) / 2);
42512a08440Sreyk 			break;
4268138faddSstsp 		case IEEE80211_ELEMID_TPC_REPORT:
4278138faddSstsp 			printf(", tpcreport");
42812a08440Sreyk 			if (vflag)
42912a08440Sreyk 				ieee80211_print_element(data, len);
43012a08440Sreyk 			break;
4318138faddSstsp 		case IEEE80211_ELEMID_TPC_REQUEST:
4328138faddSstsp 			printf(", tpcrequest");
43312a08440Sreyk 			if (vflag)
43412a08440Sreyk 				ieee80211_print_element(data, len);
43512a08440Sreyk 			break;
4361e3bf20aSstsp 		case IEEE80211_ELEMID_HTCAPS:
4371e3bf20aSstsp 			printf(", htcaps");
4381e3bf20aSstsp 			if (vflag)
4391e3bf20aSstsp 				ieee80211_print_htcaps(data, len);
4401e3bf20aSstsp 			break;
44112a08440Sreyk 		case IEEE80211_ELEMID_VENDOR:
44212a08440Sreyk 			printf(", vendor");
44312a08440Sreyk 			if (vflag)
44412a08440Sreyk 				ieee80211_print_element(data, len);
44512a08440Sreyk 			break;
44612a08440Sreyk 		default:
44712a08440Sreyk 			printf(", %u:%u", (u_int) *frm, len);
44812a08440Sreyk 			if (vflag)
44912a08440Sreyk 				ieee80211_print_element(data, len);
45012a08440Sreyk 			break;
45112a08440Sreyk 		}
45212a08440Sreyk 		frm += len + 2;
45312a08440Sreyk 
45412a08440Sreyk 		if (frm >= snapend)
45512a08440Sreyk 			break;
45612a08440Sreyk 	}
45712a08440Sreyk 
45812a08440Sreyk #undef ELEM_CHECK
45912a08440Sreyk 
46012a08440Sreyk 	return (0);
46112a08440Sreyk 
46212a08440Sreyk  trunc:
46312a08440Sreyk 	/* Truncated elements in frame */
46412a08440Sreyk 	return (1);
46512a08440Sreyk }
46612a08440Sreyk 
46712a08440Sreyk int
46812a08440Sreyk ieee80211_frame(struct ieee80211_frame *wh, u_int len)
46912a08440Sreyk {
47012a08440Sreyk 	u_int8_t subtype, type, *frm;
47112a08440Sreyk 
47212a08440Sreyk 	TCARR(wh->i_fc);
47312a08440Sreyk 
47412a08440Sreyk 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
47512a08440Sreyk 	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
47612a08440Sreyk 
47712a08440Sreyk 	frm = (u_int8_t *)&wh[1];
47812a08440Sreyk 
479ab7e388eSclaudio 	if (vflag)
480ab7e388eSclaudio 		printb(" flags", wh->i_fc[1], IEEE80211_FC1_BITS);
481ab7e388eSclaudio 
48212a08440Sreyk 	switch (type) {
48312a08440Sreyk 	case IEEE80211_FC0_TYPE_DATA:
484ab7e388eSclaudio 		printf(": %s: ", ieee80211_data_subtype_name[
485ab7e388eSclaudio 		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
486b72abdefSreyk 		ieee80211_data(wh, len);
48712a08440Sreyk 		break;
48812a08440Sreyk 	case IEEE80211_FC0_TYPE_MGT:
48912a08440Sreyk 		printf(": %s", ieee80211_mgt_subtype_name[
49012a08440Sreyk 		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
49112a08440Sreyk 		switch (subtype) {
49212a08440Sreyk 		case IEEE80211_FC0_SUBTYPE_BEACON:
49312a08440Sreyk 		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
49412a08440Sreyk 			if (ieee80211_elements(wh, len) != 0)
49512a08440Sreyk 				goto trunc;
49612a08440Sreyk 			break;
49712a08440Sreyk 		case IEEE80211_FC0_SUBTYPE_AUTH:
49812a08440Sreyk 			TCHECK2(*frm, 2);		/* Auth Algorithm */
49912a08440Sreyk 			switch (IEEE80211_AUTH_ALGORITHM(frm)) {
50012a08440Sreyk 			case IEEE80211_AUTH_ALG_OPEN:
50112a08440Sreyk 				TCHECK2(*frm, 4);	/* Auth Transaction */
50212a08440Sreyk 				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
50312a08440Sreyk 				case IEEE80211_AUTH_OPEN_REQUEST:
50412a08440Sreyk 					printf(" request");
50512a08440Sreyk 					break;
50612a08440Sreyk 				case IEEE80211_AUTH_OPEN_RESPONSE:
50712a08440Sreyk 					printf(" response");
50812a08440Sreyk 					break;
50912a08440Sreyk 				}
51012a08440Sreyk 				break;
51112a08440Sreyk 			case IEEE80211_AUTH_ALG_SHARED:
51212a08440Sreyk 				TCHECK2(*frm, 4);	/* Auth Transaction */
51312a08440Sreyk 				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
51412a08440Sreyk 				case IEEE80211_AUTH_SHARED_REQUEST:
51512a08440Sreyk 					printf(" request");
51612a08440Sreyk 					break;
51712a08440Sreyk 				case IEEE80211_AUTH_SHARED_CHALLENGE:
51812a08440Sreyk 					printf(" challenge");
51912a08440Sreyk 					break;
52012a08440Sreyk 				case IEEE80211_AUTH_SHARED_RESPONSE:
52112a08440Sreyk 					printf(" response");
52212a08440Sreyk 					break;
52312a08440Sreyk 				case IEEE80211_AUTH_SHARED_PASS:
52412a08440Sreyk 					printf(" pass");
52512a08440Sreyk 					break;
52612a08440Sreyk 				}
52712a08440Sreyk 				break;
52812a08440Sreyk 			case IEEE80211_AUTH_ALG_LEAP:
52912a08440Sreyk 				printf(" (leap)");
53012a08440Sreyk 				break;
53112a08440Sreyk 			}
53212a08440Sreyk 			break;
53318786664Sclaudio 		case IEEE80211_FC0_SUBTYPE_DEAUTH:
53418786664Sclaudio 		case IEEE80211_FC0_SUBTYPE_DISASSOC:
53518786664Sclaudio 			TCHECK2(*frm, 2);		/* Reason Code */
53618786664Sclaudio 			ieee80211_reason(frm[0] | (frm[1] << 8));
53718786664Sclaudio 			break;
53812a08440Sreyk 		}
53912a08440Sreyk 		break;
54012a08440Sreyk 	default:
54112a08440Sreyk 		printf(": type#%d", type);
54212a08440Sreyk 		break;
54312a08440Sreyk 	}
54412a08440Sreyk 
54512a08440Sreyk 	return (0);
54612a08440Sreyk 
54712a08440Sreyk  trunc:
54812a08440Sreyk 	/* Truncated 802.11 frame */
54912a08440Sreyk 	return (1);
55012a08440Sreyk }
55112a08440Sreyk 
55212a08440Sreyk u_int
55312a08440Sreyk ieee80211_any2ieee(u_int freq, u_int flags)
55412a08440Sreyk {
55512a08440Sreyk 	if (flags & IEEE80211_CHAN_2GHZ) {
55612a08440Sreyk 		if (freq == 2484)
55712a08440Sreyk 			return 14;
55812a08440Sreyk 		if (freq < 2484)
55912a08440Sreyk 			return (freq - 2407) / 5;
56012a08440Sreyk 		else
56112a08440Sreyk 			return 15 + ((freq - 2512) / 20);
56212a08440Sreyk 	} else if (flags & IEEE80211_CHAN_5GHZ) {
56312a08440Sreyk 		return (freq - 5000) / 5;
56412a08440Sreyk 	} else {
56512a08440Sreyk 		/* Assume channel is already an IEEE number */
56612a08440Sreyk 		return (freq);
56712a08440Sreyk 	}
56812a08440Sreyk }
56912a08440Sreyk 
57012a08440Sreyk int
57112a08440Sreyk ieee80211_print(struct ieee80211_frame *wh, u_int len)
57212a08440Sreyk {
57312a08440Sreyk 	if (eflag)
57412a08440Sreyk 		if (ieee80211_hdr(wh))
57512a08440Sreyk 			return (1);
57612a08440Sreyk 
57712a08440Sreyk 	printf("802.11");
57812a08440Sreyk 
57912a08440Sreyk 	return (ieee80211_frame(wh, len));
58012a08440Sreyk }
58112a08440Sreyk 
58212a08440Sreyk void
58312a08440Sreyk ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h,
58412a08440Sreyk     const u_char *p)
58512a08440Sreyk {
58612a08440Sreyk 	struct ieee80211_frame *wh = (struct ieee80211_frame*)p;
58712a08440Sreyk 
588c79cf170Sreyk 	if (!ieee80211_encap)
58912a08440Sreyk 		ts_print(&h->ts);
59012a08440Sreyk 
59112a08440Sreyk 	packetp = p;
59212a08440Sreyk 	snapend = p + h->caplen;
59312a08440Sreyk 
594a0774ae9Smglocker 	if (ieee80211_print(wh, (u_int)h->len) != 0)
59512a08440Sreyk 		printf("[|802.11]");
59612a08440Sreyk 
597c79cf170Sreyk 	if (!ieee80211_encap) {
59812a08440Sreyk 		if (xflag)
599a0774ae9Smglocker 			default_print(p, (u_int)h->len);
60012a08440Sreyk 		putchar('\n');
60112a08440Sreyk 	}
602c79cf170Sreyk }
60312a08440Sreyk 
60412a08440Sreyk void
60512a08440Sreyk ieee802_11_radio_if_print(u_char *user, const struct pcap_pkthdr *h,
60612a08440Sreyk     const u_char *p)
60712a08440Sreyk {
60812a08440Sreyk 	struct ieee80211_radiotap_header *rh =
60912a08440Sreyk 	    (struct ieee80211_radiotap_header*)p;
61012a08440Sreyk 	struct ieee80211_frame *wh;
61112a08440Sreyk 	u_int8_t *t;
61212a08440Sreyk 	u_int32_t present;
61312a08440Sreyk 	u_int len, rh_len;
614cce1ba42Sclaudio 	u_int16_t tmp;
61512a08440Sreyk 
616c79cf170Sreyk 	if (!ieee80211_encap)
61712a08440Sreyk 		ts_print(&h->ts);
61812a08440Sreyk 
61912a08440Sreyk 	packetp = p;
62012a08440Sreyk 	snapend = p + h->caplen;
62112a08440Sreyk 
62212a08440Sreyk 	TCHECK(*rh);
62312a08440Sreyk 
624a0774ae9Smglocker 	len = h->len;
62512a08440Sreyk 	rh_len = letoh16(rh->it_len);
62612a08440Sreyk 	if (rh->it_version != 0) {
627c79cf170Sreyk 		printf("[?radiotap + 802.11 v:%u]", rh->it_version);
62812a08440Sreyk 		goto out;
62912a08440Sreyk 	}
63012a08440Sreyk 
63112a08440Sreyk 	wh = (struct ieee80211_frame *)(p + rh_len);
63212a08440Sreyk 	if (len <= rh_len || ieee80211_print(wh, len - rh_len))
63312a08440Sreyk 		printf("[|802.11]");
63412a08440Sreyk 
63512a08440Sreyk 	t = (u_int8_t*)p + sizeof(struct ieee80211_radiotap_header);
63612a08440Sreyk 
63712a08440Sreyk 	if ((present = letoh32(rh->it_present)) == 0)
63812a08440Sreyk 		goto out;
63912a08440Sreyk 
64012a08440Sreyk 	printf(", <radiotap v%u", rh->it_version);
64112a08440Sreyk 
64212a08440Sreyk #define RADIOTAP(_x)	\
64312a08440Sreyk 	(present & (1 << IEEE80211_RADIOTAP_##_x))
64412a08440Sreyk 
64512a08440Sreyk 	if (RADIOTAP(TSFT)) {
646cce1ba42Sclaudio 		u_int64_t tsf;
647cce1ba42Sclaudio 
64812a08440Sreyk 		TCHECK2(*t, 8);
649cce1ba42Sclaudio 		bcopy(t, &tsf, sizeof(u_int64_t));
65012a08440Sreyk 		if (vflag > 1)
651cce1ba42Sclaudio 			printf(", tsf %llu", letoh64(tsf));
65212a08440Sreyk 		t += 8;
65312a08440Sreyk 	}
65412a08440Sreyk 
65512a08440Sreyk 	if (RADIOTAP(FLAGS)) {
65612a08440Sreyk 		u_int8_t flags = *(u_int8_t*)t;
657026ca542Sderaadt 		TCHECK2(*t, 1);
658026ca542Sderaadt 
65912a08440Sreyk 		if (flags & IEEE80211_RADIOTAP_F_CFP)
66012a08440Sreyk 			printf(", CFP");
66112a08440Sreyk 		if (flags & IEEE80211_RADIOTAP_F_SHORTPRE)
66212a08440Sreyk 			printf(", SHORTPRE");
66312a08440Sreyk 		if (flags & IEEE80211_RADIOTAP_F_WEP)
66412a08440Sreyk 			printf(", WEP");
66512a08440Sreyk 		if (flags & IEEE80211_RADIOTAP_F_FRAG)
66612a08440Sreyk 			printf(", FRAG");
66712a08440Sreyk 		t += 1;
66812a08440Sreyk 	}
66912a08440Sreyk 
67012a08440Sreyk 	if (RADIOTAP(RATE)) {
67112a08440Sreyk 		TCHECK2(*t, 1);
67212a08440Sreyk 		if (vflag)
67312a08440Sreyk 			printf(", %uMbit/s", (*(u_int8_t*)t) / 2);
67412a08440Sreyk 		t += 1;
67512a08440Sreyk 	}
67612a08440Sreyk 
67712a08440Sreyk 	if (RADIOTAP(CHANNEL)) {
67812a08440Sreyk 		u_int16_t freq, flags;
67912a08440Sreyk 		TCHECK2(*t, 2);
68012a08440Sreyk 
681cce1ba42Sclaudio 		bcopy(t, &freq, sizeof(u_int16_t));
682cce1ba42Sclaudio 		freq = letoh16(freq);
68312a08440Sreyk 		t += 2;
68412a08440Sreyk 		TCHECK2(*t, 2);
685cce1ba42Sclaudio 		bcopy(t, &flags, sizeof(u_int16_t));
686cce1ba42Sclaudio 		flags = letoh16(flags);
68712a08440Sreyk 		t += 2;
68812a08440Sreyk 
68912a08440Sreyk 		printf(", chan %u", ieee80211_any2ieee(freq, flags));
69012a08440Sreyk 
69112a08440Sreyk 		if (flags & IEEE80211_CHAN_DYN &&
69212a08440Sreyk 		    flags & IEEE80211_CHAN_2GHZ)
69312a08440Sreyk 			printf(", 11g");
69412a08440Sreyk 		else if (flags & IEEE80211_CHAN_CCK &&
69512a08440Sreyk 		    flags & IEEE80211_CHAN_2GHZ)
69612a08440Sreyk 			printf(", 11b");
69712a08440Sreyk 		else if (flags & IEEE80211_CHAN_OFDM &&
69812a08440Sreyk 		    flags & IEEE80211_CHAN_2GHZ)
69912a08440Sreyk 			printf(", 11G");
70012a08440Sreyk 		else if (flags & IEEE80211_CHAN_OFDM &&
70112a08440Sreyk 		    flags & IEEE80211_CHAN_5GHZ)
70212a08440Sreyk 			printf(", 11a");
70312a08440Sreyk 
70412a08440Sreyk 		if (flags & IEEE80211_CHAN_TURBO)
70512a08440Sreyk 			printf(", TURBO");
70612a08440Sreyk 		if (flags & IEEE80211_CHAN_XR)
70712a08440Sreyk 			printf(", XR");
70812a08440Sreyk 	}
70912a08440Sreyk 
71012a08440Sreyk 	if (RADIOTAP(FHSS)) {
71112a08440Sreyk 		TCHECK2(*t, 2);
71212a08440Sreyk 		printf(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1);
71312a08440Sreyk 		t += 2;
71412a08440Sreyk 	}
71512a08440Sreyk 
71612a08440Sreyk 	if (RADIOTAP(DBM_ANTSIGNAL)) {
71712a08440Sreyk 		TCHECK(*t);
71812a08440Sreyk 		printf(", sig %ddBm", *(int8_t*)t);
71912a08440Sreyk 		t += 1;
72012a08440Sreyk 	}
72112a08440Sreyk 
72212a08440Sreyk 	if (RADIOTAP(DBM_ANTNOISE)) {
72312a08440Sreyk 		TCHECK(*t);
72412a08440Sreyk 		printf(", noise %ddBm", *(int8_t*)t);
72512a08440Sreyk 		t += 1;
72612a08440Sreyk 	}
72712a08440Sreyk 
72812a08440Sreyk 	if (RADIOTAP(LOCK_QUALITY)) {
72912a08440Sreyk 		TCHECK2(*t, 2);
730cce1ba42Sclaudio 		if (vflag) {
731cce1ba42Sclaudio 			bcopy(t, &tmp, sizeof(u_int16_t));
732cce1ba42Sclaudio 			printf(", quality %u", letoh16(tmp));
733cce1ba42Sclaudio 		}
73412a08440Sreyk 		t += 2;
73512a08440Sreyk 	}
73612a08440Sreyk 
73712a08440Sreyk 	if (RADIOTAP(TX_ATTENUATION)) {
73812a08440Sreyk 		TCHECK2(*t, 2);
739cce1ba42Sclaudio 		if (vflag) {
740cce1ba42Sclaudio 			bcopy(t, &tmp, sizeof(u_int16_t));
741cce1ba42Sclaudio 			printf(", txatt %u", letoh16(tmp));
742cce1ba42Sclaudio 		}
74312a08440Sreyk 		t += 2;
74412a08440Sreyk 	}
74512a08440Sreyk 
74612a08440Sreyk 	if (RADIOTAP(DB_TX_ATTENUATION)) {
74712a08440Sreyk 		TCHECK2(*t, 2);
748cce1ba42Sclaudio 		if (vflag) {
749cce1ba42Sclaudio 			bcopy(t, &tmp, sizeof(u_int16_t));
750cce1ba42Sclaudio 			printf(", txatt %udB", letoh16(tmp));
751cce1ba42Sclaudio 		}
75212a08440Sreyk 		t += 2;
75312a08440Sreyk 	}
75412a08440Sreyk 
75512a08440Sreyk 	if (RADIOTAP(DBM_TX_POWER)) {
75612a08440Sreyk 		TCHECK(*t);
75712a08440Sreyk 		printf(", txpower %ddBm", *(int8_t*)t);
75812a08440Sreyk 		t += 1;
75912a08440Sreyk 	}
76012a08440Sreyk 
76112a08440Sreyk 	if (RADIOTAP(ANTENNA)) {
76212a08440Sreyk 		TCHECK(*t);
76312a08440Sreyk 		if (vflag)
76412a08440Sreyk 			printf(", antenna %u", *(u_int8_t*)t);
76512a08440Sreyk 		t += 1;
76612a08440Sreyk 	}
76712a08440Sreyk 
76812a08440Sreyk 	if (RADIOTAP(DB_ANTSIGNAL)) {
76912a08440Sreyk 		TCHECK(*t);
77012a08440Sreyk 		printf(", signal %udB", *(u_int8_t*)t);
77112a08440Sreyk 		t += 1;
77212a08440Sreyk 	}
77312a08440Sreyk 
77412a08440Sreyk 	if (RADIOTAP(DB_ANTNOISE)) {
77512a08440Sreyk 		TCHECK(*t);
77612a08440Sreyk 		printf(", noise %udB", *(u_int8_t*)t);
77712a08440Sreyk 		t += 1;
77812a08440Sreyk 	}
77912a08440Sreyk 
78012a08440Sreyk 	if (RADIOTAP(FCS)) {
78112a08440Sreyk 		TCHECK2(*t, 4);
782cce1ba42Sclaudio 		if (vflag) {
783cce1ba42Sclaudio 			u_int32_t fcs;
784cce1ba42Sclaudio 			bcopy(t, &fcs, sizeof(u_int32_t));
785cce1ba42Sclaudio 			printf(", fcs %08x", letoh32(fcs));
786cce1ba42Sclaudio 		}
78712a08440Sreyk 		t += 4;
78812a08440Sreyk 	}
78912a08440Sreyk 
7906fc94ee3Sreyk 	if (RADIOTAP(RSSI)) {
7916fc94ee3Sreyk 		u_int8_t rssi, max_rssi;
7926fc94ee3Sreyk 		TCHECK(*t);
7936fc94ee3Sreyk 		rssi = *(u_int8_t*)t;
7946fc94ee3Sreyk 		t += 1;
7956fc94ee3Sreyk 		TCHECK(*t);
7966fc94ee3Sreyk 		max_rssi = *(u_int8_t*)t;
7976fc94ee3Sreyk 		t += 1;
7986fc94ee3Sreyk 
7996fc94ee3Sreyk 		printf(", rssi %u/%u", rssi, max_rssi);
8006fc94ee3Sreyk 	}
8016fc94ee3Sreyk 
80212a08440Sreyk #undef RADIOTAP
80312a08440Sreyk 
80412a08440Sreyk 	putchar('>');
80512a08440Sreyk 	goto out;
80612a08440Sreyk 
80712a08440Sreyk  trunc:
80812a08440Sreyk 	/* Truncated frame */
80912a08440Sreyk 	printf("[|radiotap + 802.11]");
81012a08440Sreyk 
81112a08440Sreyk  out:
812c79cf170Sreyk 	if (!ieee80211_encap) {
81312a08440Sreyk 		if (xflag)
814a0774ae9Smglocker 			default_print(p, h->len);
81512a08440Sreyk 		putchar('\n');
81612a08440Sreyk 	}
817c79cf170Sreyk }
81818786664Sclaudio 
81918786664Sclaudio void
82018786664Sclaudio ieee80211_reason(u_int16_t reason)
82118786664Sclaudio {
82218786664Sclaudio 	if (!vflag)
82318786664Sclaudio 		return;
82418786664Sclaudio 
82518786664Sclaudio 	switch (reason) {
82618786664Sclaudio 	case IEEE80211_REASON_UNSPECIFIED:
82718786664Sclaudio 		printf(", unspecified failure");
82818786664Sclaudio 		break;
82918786664Sclaudio 	case IEEE80211_REASON_AUTH_EXPIRE:
83018786664Sclaudio 		printf(", authentication expired");
83118786664Sclaudio 		break;
83218786664Sclaudio 	case IEEE80211_REASON_AUTH_LEAVE:
83318786664Sclaudio 		printf(", deauth - station left");
83418786664Sclaudio 		break;
83518786664Sclaudio 	case IEEE80211_REASON_ASSOC_EXPIRE:
83618786664Sclaudio 		printf(", association expired");
83718786664Sclaudio 		break;
83818786664Sclaudio 	case IEEE80211_REASON_ASSOC_TOOMANY:
83918786664Sclaudio 		printf(", too many associated stations");
84018786664Sclaudio 		break;
84118786664Sclaudio 	case IEEE80211_REASON_NOT_AUTHED:
84218786664Sclaudio 		printf(", not authenticated");
84318786664Sclaudio 		break;
84418786664Sclaudio 	case IEEE80211_REASON_NOT_ASSOCED:
84518786664Sclaudio 		printf(", not associated");
84618786664Sclaudio 		break;
84718786664Sclaudio 	case IEEE80211_REASON_ASSOC_LEAVE:
84818786664Sclaudio 		printf(", disassociated - station left");
84918786664Sclaudio 		break;
85018786664Sclaudio 	case IEEE80211_REASON_ASSOC_NOT_AUTHED:
85118786664Sclaudio 		printf(", association but not authenticated");
85218786664Sclaudio 		break;
85318786664Sclaudio 	case IEEE80211_REASON_RSN_REQUIRED:
85418786664Sclaudio 		printf(", rsn required");
85518786664Sclaudio 		break;
85618786664Sclaudio 	case IEEE80211_REASON_RSN_INCONSISTENT:
85718786664Sclaudio 		printf(", rsn inconsistent");
85818786664Sclaudio 		break;
85918786664Sclaudio 	case IEEE80211_REASON_IE_INVALID:
86018786664Sclaudio 		printf(", ie invalid");
86118786664Sclaudio 		break;
86218786664Sclaudio 	case IEEE80211_REASON_MIC_FAILURE:
86318786664Sclaudio 		printf(", mic failure");
86418786664Sclaudio 		break;
86518786664Sclaudio 	default:
86618786664Sclaudio 		printf(", unknown reason %u", reason);
86718786664Sclaudio 	}
86818786664Sclaudio }
869