xref: /openbsd/usr.sbin/tcpdump/print-802_11.c (revision 09467b48)
1 /*	$OpenBSD: print-802_11.c,v 1.40 2017/09/01 14:04:49 stsp Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/time.h>
20 #include <sys/socket.h>
21 #include <sys/file.h>
22 #include <sys/ioctl.h>
23 
24 #include <net/if.h>
25 
26 #include <netinet/in.h>
27 #include <netinet/if_ether.h>
28 
29 #include <net80211/ieee80211.h>
30 #include <net80211/ieee80211_radiotap.h>
31 
32 #include <ctype.h>
33 #include <pcap.h>
34 #include <stdio.h>
35 #include <string.h>
36 
37 #include "addrtoname.h"
38 #include "interface.h"
39 
40 const char *ieee80211_ctl_subtype_name[] = {
41 	"reserved#0",
42 	"reserved#1",
43 	"reserved#2",
44 	"reserved#3",
45 	"reserved#4",
46 	"reserved#5",
47 	"reserved#6",
48 	"wrapper",
49 	"block ack request",
50 	"block ack",
51 	"ps poll",
52 	"rts",
53 	"cts",
54 	"ack",
55 	"cf-end",
56 	"cf-end-ack",
57 };
58 
59 const char *ieee80211_mgt_subtype_name[] = {
60 	"association request",
61 	"association response",
62 	"reassociation request",
63 	"reassociation response",
64 	"probe request",
65 	"probe response",
66 	"reserved#6",
67 	"reserved#7",
68 	"beacon",
69 	"atim",
70 	"disassociation",
71 	"authentication",
72 	"deauthentication",
73 	"action",
74 	"action noack",
75 	"reserved#15"
76 };
77 
78 const char *ieee80211_data_subtype_name[] = {
79 	"data",
80 	"data cf ack",
81 	"data cf poll",
82 	"data cf poll ack",
83 	"no-data",
84 	"no-data cf poll",
85 	"no-data cf ack",
86 	"no-data cf poll ack",
87 	"QoS data",
88 	"QoS data cf ack",
89 	"QoS data cf poll",
90 	"QoS data cf poll ack",
91 	"QoS no-data",
92 	"QoS no-data cf poll",
93 	"QoS no-data cf ack",
94 	"QoS no-data cf poll ack"
95 };
96 
97 int	 ieee80211_hdr(struct ieee80211_frame *);
98 int	 ieee80211_data(struct ieee80211_frame *, u_int);
99 void	 ieee80211_print_element(u_int8_t *, u_int);
100 void	 ieee80211_print_essid(u_int8_t *, u_int);
101 void	 ieee80211_print_country(u_int8_t *, u_int);
102 void	 ieee80211_print_htcaps(u_int8_t *, u_int);
103 void	 ieee80211_print_htop(u_int8_t *, u_int);
104 void	 ieee80211_print_rsncipher(u_int8_t []);
105 void	 ieee80211_print_akm(u_int8_t []);
106 void	 ieee80211_print_rsn(u_int8_t *, u_int);
107 int	 ieee80211_print_beacon(struct ieee80211_frame *, u_int);
108 int	 ieee80211_print_assocreq(struct ieee80211_frame *, u_int);
109 int	 ieee80211_print_elements(uint8_t *);
110 int	 ieee80211_frame(struct ieee80211_frame *, u_int);
111 int	 ieee80211_print(struct ieee80211_frame *, u_int);
112 u_int	 ieee80211_any2ieee(u_int, u_int);
113 void	 ieee80211_reason(u_int16_t);
114 
115 #define TCARR(a)	TCHECK2(*a, sizeof(a))
116 
117 int ieee80211_encap = 0;
118 
119 int
120 ieee80211_hdr(struct ieee80211_frame *wh)
121 {
122 	struct ieee80211_frame_addr4 *w4;
123 
124 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
125 	case IEEE80211_FC1_DIR_NODS:
126 		TCARR(wh->i_addr2);
127 		printf("%s", etheraddr_string(wh->i_addr2));
128 		TCARR(wh->i_addr1);
129 		printf(" > %s", etheraddr_string(wh->i_addr1));
130 		TCARR(wh->i_addr3);
131 		printf(", bssid %s", etheraddr_string(wh->i_addr3));
132 		break;
133 	case IEEE80211_FC1_DIR_TODS:
134 		TCARR(wh->i_addr2);
135 		printf("%s", etheraddr_string(wh->i_addr2));
136 		TCARR(wh->i_addr3);
137 		printf(" > %s", etheraddr_string(wh->i_addr3));
138 		TCARR(wh->i_addr1);
139 		printf(", bssid %s, > DS", etheraddr_string(wh->i_addr1));
140 		break;
141 	case IEEE80211_FC1_DIR_FROMDS:
142 		TCARR(wh->i_addr3);
143 		printf("%s", etheraddr_string(wh->i_addr3));
144 		TCARR(wh->i_addr1);
145 		printf(" > %s", etheraddr_string(wh->i_addr1));
146 		TCARR(wh->i_addr2);
147 		printf(", bssid %s, DS >", etheraddr_string(wh->i_addr2));
148 		break;
149 	case IEEE80211_FC1_DIR_DSTODS:
150 		w4 = (struct ieee80211_frame_addr4 *) wh;
151 		TCARR(w4->i_addr4);
152 		printf("%s", etheraddr_string(w4->i_addr4));
153 		TCARR(w4->i_addr3);
154 		printf(" > %s", etheraddr_string(w4->i_addr3));
155 		TCARR(w4->i_addr2);
156 		printf(", bssid %s", etheraddr_string(w4->i_addr2));
157 		TCARR(w4->i_addr1);
158 		printf(" > %s, DS > DS", etheraddr_string(w4->i_addr1));
159 		break;
160 	}
161 	if (vflag) {
162 		u_int16_t seq;
163 		TCARR(wh->i_seq);
164 		bcopy(wh->i_seq, &seq, sizeof(u_int16_t));
165 		printf(" (seq %u): ", letoh16(seq));
166 	} else
167 		printf(": ");
168 
169 	return (0);
170 
171  trunc:
172 	/* Truncated elements in frame */
173 	return (1);
174 }
175 
176 int
177 ieee80211_data(struct ieee80211_frame *wh, u_int len)
178 {
179 	u_int8_t *t = (u_int8_t *)wh;
180 	u_int datalen;
181 	int data = !(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_NODATA);
182 	int hasqos = ((wh->i_fc[0] &
183 	    (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
184 	    (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS));
185 	u_char *esrc = NULL, *edst = NULL;
186 
187 	if (hasqos) {
188 		struct ieee80211_qosframe *wq;
189 
190 		wq = (struct ieee80211_qosframe *) wh;
191 		TCHECK(*wq);
192 		t += sizeof(*wq);
193 		datalen = len - sizeof(*wq);
194 	} else {
195 		TCHECK(*wh);
196 		t += sizeof(*wh);
197 		datalen = len - sizeof(*wh);
198 	}
199 
200 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
201 	case IEEE80211_FC1_DIR_TODS:
202 		esrc = wh->i_addr2;
203 		edst = wh->i_addr3;
204 		break;
205 	case IEEE80211_FC1_DIR_FROMDS:
206 		esrc = wh->i_addr3;
207 		edst = wh->i_addr1;
208 		break;
209 	case IEEE80211_FC1_DIR_NODS:
210 		esrc = wh->i_addr2;
211 		edst = wh->i_addr1;
212 		break;
213 	case IEEE80211_FC1_DIR_DSTODS:
214 		if (hasqos) {
215 			struct ieee80211_qosframe_addr4 *w4;
216 
217 			w4 = (struct ieee80211_qosframe_addr4 *) wh;
218 			TCHECK(*w4);
219 			t = (u_int8_t *) (w4 + 1);
220 			datalen = len - sizeof(*w4);
221 			esrc = w4->i_addr4;
222 			edst = w4->i_addr3;
223 		} else {
224 			struct ieee80211_frame_addr4 *w4;
225 
226 			w4 = (struct ieee80211_frame_addr4 *) wh;
227 			TCHECK(*w4);
228 			t = (u_int8_t *) (w4 + 1);
229 			datalen = len - sizeof(*w4);
230 			esrc = w4->i_addr4;
231 			edst = w4->i_addr3;
232 		}
233 		break;
234 	}
235 
236 	if (data && esrc)
237 		llc_print(t, datalen, datalen, esrc, edst);
238 	else if (eflag && esrc)
239 		printf("%s > %s",
240 		    etheraddr_string(esrc), etheraddr_string(edst));
241 
242 	return (0);
243 
244  trunc:
245 	/* Truncated elements in frame */
246 	return (1);
247 }
248 
249 /* Caller checks len */
250 void
251 ieee80211_print_element(u_int8_t *data, u_int len)
252 {
253 	u_int8_t *p;
254 	int i;
255 
256 	printf(" 0x");
257 	for (i = 0, p = data; i < len; i++, p++)
258 		printf("%02x", *p);
259 }
260 
261 /* Caller checks len */
262 void
263 ieee80211_print_essid(u_int8_t *essid, u_int len)
264 {
265 	u_int8_t *p;
266 	int i;
267 
268 	if (len > IEEE80211_NWID_LEN)
269 		len = IEEE80211_NWID_LEN;
270 
271 	/* determine printable or not */
272 	for (i = 0, p = essid; i < len; i++, p++) {
273 		if (*p < ' ' || *p > 0x7e)
274 			break;
275 	}
276 	if (i == len) {
277 		printf(" (");
278 		for (i = 0, p = essid; i < len; i++, p++)
279 			putchar(*p);
280 		putchar(')');
281 	} else
282 		ieee80211_print_element(essid, len);
283 }
284 
285 /* Caller checks len */
286 void
287 ieee80211_print_country(u_int8_t *data, u_int len)
288 {
289 	u_int8_t first_chan, nchan, maxpower;
290 
291 	if (len < 6)
292 		return;
293 
294 	/* country string */
295 	printf((isprint(data[0]) ? " '%c" : " '\\%03o"), data[0]);
296 	printf((isprint(data[1]) ? "%c" : "\\%03o"), data[1]);
297 	printf((isprint(data[2]) ? "%c'" : "\\%03o'"), data[2]);
298 
299 	len -= 3;
300 	data += 3;
301 
302 	/* channels and corresponding TX power limits */
303 	while (len >= 3) {
304 		/* no pretty-printing for nonsensical zero values,
305 		 * nor for operating extension IDs (values >= 201) */
306 		if (data[0] == 0 || data[1] == 0 ||
307 		    data[0] >= 201 || data[1] >= 201) {
308 			printf(", %d %d %d", data[0], data[1], data[2]);
309 			len -= 3;
310 			data += 3;
311 			continue;
312 		}
313 
314 		first_chan = data[0];
315 		nchan = data[1];
316 		maxpower = data[2];
317 
318 		printf(", channel%s %d", nchan == 1 ? "" : "s", first_chan);
319 		if (nchan > 1)
320 			printf("-%d", first_chan + nchan - 1);
321 		printf(" limit %ddB", maxpower);
322 
323 		len -= 3;
324 		data += 3;
325 	}
326 }
327 
328 /* Caller checks len */
329 void
330 ieee80211_print_htcaps(u_int8_t *data, u_int len)
331 {
332 	uint16_t htcaps, rxrate;
333 	int smps, rxstbc;
334 	uint8_t ampdu, txmcs;
335 	int i;
336 	uint8_t *rxmcs;
337 
338 	if (len < 2) {
339 		ieee80211_print_element(data, len);
340 		return;
341 	}
342 
343 	htcaps = (data[0]) | (data[1] << 8);
344 	printf("=<");
345 
346 	/* channel width */
347 	if (htcaps & IEEE80211_HTCAP_CBW20_40)
348 		printf("20/40MHz");
349 	else
350 		printf("20MHz");
351 
352 	/* LDPC coding */
353 	if (htcaps & IEEE80211_HTCAP_LDPC)
354 		printf(",LDPC");
355 
356 	/* spatial multiplexing power save mode */
357 	smps = (htcaps & IEEE80211_HTCAP_SMPS_MASK)
358 	    >> IEEE80211_HTCAP_SMPS_SHIFT;
359 	if (smps == 0)
360 		printf(",SMPS static");
361 	else if (smps == 1)
362 		printf(",SMPS dynamic");
363 
364 	/* 11n greenfield mode */
365 	if (htcaps & IEEE80211_HTCAP_GF)
366 		printf(",greenfield");
367 
368 	/* short guard interval */
369 	if (htcaps & IEEE80211_HTCAP_SGI20)
370 		printf(",SGI@20MHz");
371 	if (htcaps & IEEE80211_HTCAP_SGI40)
372 		printf(",SGI@40MHz");
373 
374 	/* space-time block coding */
375 	if (htcaps & IEEE80211_HTCAP_TXSTBC)
376 		printf(",TXSTBC");
377 	rxstbc = (htcaps & IEEE80211_HTCAP_RXSTBC_MASK)
378 	    >> IEEE80211_HTCAP_RXSTBC_SHIFT;
379 	if (rxstbc > 0 && rxstbc < 4)
380 		printf(",RXSTBC %d stream", rxstbc);
381 
382 	/* delayed block-ack */
383 	if (htcaps & IEEE80211_HTCAP_DELAYEDBA)
384 		printf(",delayed BA");
385 
386 	/* max A-MSDU length */
387 	if (htcaps & IEEE80211_HTCAP_AMSDU7935)
388 		printf(",A-MSDU 7935");
389 	else
390 		printf(",A-MSDU 3839");
391 
392 	/* DSSS/CCK in 40MHz mode */
393 	if (htcaps & IEEE80211_HTCAP_DSSSCCK40)
394 		printf(",DSSS/CCK@40MHz");
395 
396 	/* 40MHz intolerant */
397 	if (htcaps & IEEE80211_HTCAP_40INTOLERANT)
398 		printf(",40MHz intolerant");
399 
400 	/* L-SIG TXOP protection */
401 	if (htcaps & IEEE80211_HTCAP_LSIGTXOPPROT)
402 		printf(",L-SIG TXOP prot");
403 
404 	if (len < 3) {
405 		printf(">");
406 		return;
407 	}
408 
409 	/* A-MPDU parameters. */
410 	ampdu = data[2];
411 
412 	/* A-MPDU length exponent */
413 	if ((ampdu & IEEE80211_AMPDU_PARAM_LE) >= 0 &&
414 	    (ampdu & IEEE80211_AMPDU_PARAM_LE) <= 3)
415 		printf(",A-MPDU max %d",
416 		    (1 << (13 + (ampdu & IEEE80211_AMPDU_PARAM_LE))) - 1);
417 
418 	/* A-MPDU start spacing */
419 	if (ampdu & IEEE80211_AMPDU_PARAM_SS) {
420 		float ss;
421 
422 		switch ((ampdu & IEEE80211_AMPDU_PARAM_SS) >> 2) {
423 		case 1:
424 			ss = 0.25;
425 			break;
426 		case 2:
427 			ss = 0.5;
428 			break;
429 		case 3:
430 			ss = 1;
431 			break;
432 		case 4:
433 			ss = 2;
434 			break;
435 		case 5:
436 			ss = 4;
437 			break;
438 		case 6:
439 			ss = 8;
440 			break;
441 		case 7:
442 			ss = 16;
443 			break;
444 		default:
445 			ss = 0;
446 			break;
447 		}
448 		if (ss != 0)
449 			printf(",A-MPDU spacing %.2fus", ss);
450 	}
451 
452 	if (len < 21) {
453 		printf(">");
454 		return;
455 	}
456 
457 	/* Supported MCS set. */
458 	printf(",RxMCS 0x");
459 	rxmcs = &data[3];
460 	for (i = 0; i < 10; i++)
461 		printf("%02x", rxmcs[i]);
462 
463 	/* Max MCS Rx rate (a value of 0 means "not specified"). */
464 	rxrate = ((data[13] | (data[14]) << 8) & IEEE80211_MCS_RX_RATE_HIGH);
465 	if (rxrate)
466 		printf(",RxMaxrate %huMb/s", rxrate);
467 
468 	/* Tx MCS Set */
469 	txmcs = data[15];
470 	if (txmcs & IEEE80211_TX_MCS_SET_DEFINED) {
471 		if (txmcs & IEEE80211_TX_RX_MCS_NOT_EQUAL) {
472 			/* Number of spatial Tx streams. */
473 			printf(",%d Tx streams",
474 			     1 + ((txmcs & IEEE80211_TX_SPATIAL_STREAMS) >> 2));
475 			/* Transmit unequal modulation supported. */
476 			if (txmcs & IEEE80211_TX_UNEQUAL_MODULATION)
477 				printf(",UEQM");
478 		}
479 	}
480 
481 	printf(">");
482 }
483 
484 /* Caller checks len */
485 void
486 ieee80211_print_htop(u_int8_t *data, u_int len)
487 {
488 	u_int8_t primary_chan;
489 	u_int8_t htopinfo[5];
490 	u_int8_t basic_mcs[16];
491 	int sco, htprot, i;
492 
493 	if (len < sizeof(primary_chan) + sizeof(htopinfo) + sizeof(basic_mcs)) {
494 		ieee80211_print_element(data, len);
495 		return;
496 	}
497 
498 	htopinfo[0] = data[1];
499 
500 	printf("=<");
501 
502 	/* primary channel and secondary channel offset */
503 	primary_chan = data[0];
504 	sco = ((htopinfo[0] & IEEE80211_HTOP0_SCO_MASK)
505 	    >> IEEE80211_HTOP0_SCO_SHIFT);
506 	if (sco == 0) /* no secondary channel */
507 		printf("20MHz chan %d", primary_chan);
508 	else if (sco == 1) { /* secondary channel above */
509 		if (primary_chan >= 1 && primary_chan <= 13) /* 2GHz */
510 			printf("40MHz chan %d:%d", primary_chan,
511 			    primary_chan + 1);
512 		else if (primary_chan >= 34) /* 5GHz */
513 			printf("40MHz chan %d:%d", primary_chan,
514 			    primary_chan + 4);
515 		else
516 			printf("[invalid 40MHz chan %d+]", primary_chan);
517 	} else if (sco == 3) { /* secondary channel below */
518 		if (primary_chan >= 2 && primary_chan <= 14) /* 2GHz */
519 			printf("40MHz chan %d:%d", primary_chan,
520 			    primary_chan - 1);
521 		else if (primary_chan >= 40) /* 5GHz */
522 			printf("40MHz chan %d:%d", primary_chan,
523 			    primary_chan - 4);
524 		else
525 			printf("[invalid 40MHz chan %d-]", primary_chan);
526 	} else
527 		printf("chan %d [invalid secondary channel offset %d]",
528 		    primary_chan, sco);
529 
530 	/* STA channel width */
531 	if ((htopinfo[0] & IEEE80211_HTOP0_CHW) == 0)
532 		printf(",STA chanw 20MHz");
533 
534 	/* reduced interframe space (RIFS) permitted */
535 	if (htopinfo[0] & IEEE80211_HTOP0_RIFS)
536 		printf(",RIFS");
537 
538 	htopinfo[1] = data[2];
539 
540 	/* protection requirements for HT transmissions */
541 	htprot = ((htopinfo[1] & IEEE80211_HTOP1_PROT_MASK)
542 	    >> IEEE80211_HTOP1_PROT_SHIFT);
543 	switch (htprot) {
544 	case IEEE80211_HTPROT_NONE:
545 		printf(",htprot none");
546 		break;
547 	case IEEE80211_HTPROT_NONMEMBER:
548 		printf(",htprot non-member");
549 		break;
550 	case IEEE80211_HTPROT_20MHZ:
551 		printf(",htprot 20MHz");
552 		break;
553 	case IEEE80211_HTPROT_NONHT_MIXED:
554 		printf(",htprot non-HT-mixed");
555 		break;
556 	default:
557 		printf(",htprot %d", htprot);
558 		break;
559 	}
560 
561 	/* non-greenfield STA present */
562 	if (htopinfo[1] & IEEE80211_HTOP1_NONGF_STA)
563 		printf(",non-greenfield STA");
564 
565 	/* non-HT STA present */
566 	if (htopinfo[1] & IEEE80211_HTOP1_OBSS_NONHT_STA)
567 		printf(",non-HT STA");
568 
569 	htopinfo[3] = data[4];
570 
571 	/* dual-beacon */
572 	if (htopinfo[3] & IEEE80211_HTOP2_DUALBEACON)
573 		printf(",dualbeacon");
574 
575 	/* dual CTS protection */
576 	if (htopinfo[3] & IEEE80211_HTOP2_DUALCTSPROT)
577 		printf(",dualctsprot");
578 
579 	htopinfo[4] = data[5];
580 
581 	/* space-time block coding (STBC) beacon */
582 	if ((htopinfo[4] << 8) & IEEE80211_HTOP2_STBCBEACON)
583 		printf(",STBC beacon");
584 
585 	/* L-SIG (non-HT signal field) TX opportunity (TXOP) protection */
586 	if ((htopinfo[4] << 8) & IEEE80211_HTOP2_LSIGTXOP)
587 		printf(",lsigtxprot");
588 
589 	/* phased-coexistence operation (PCO) active */
590 	if ((htopinfo[4] << 8) & IEEE80211_HTOP2_PCOACTIVE) {
591 		/* PCO phase */
592 		if ((htopinfo[4] << 8) & IEEE80211_HTOP2_PCOPHASE40)
593 			printf(",pco40MHz");
594 		else
595 			printf(",pco20MHz");
596 	}
597 
598 	/* basic MCS set */
599 	memcpy(basic_mcs, &data[6], sizeof(basic_mcs));
600 	printf(",basic MCS set 0x");
601 	for (i = 0; i < sizeof(basic_mcs) / sizeof(basic_mcs[0]); i++)
602 			printf("%x", basic_mcs[i]);
603 
604 	printf(">");
605 }
606 
607 void
608 ieee80211_print_rsncipher(uint8_t selector[4])
609 {
610 	if (memcmp(selector, MICROSOFT_OUI, 3) != 0 &&
611 	    memcmp(selector, IEEE80211_OUI, 3) != 0) {
612 		printf("0x%x%x%x%x", selector[0], selector[1], selector[2],
613 		     selector[3]);
614 	    	return;
615 	}
616 
617 	/* See 802.11-2012 Table 8-99 */
618 	switch (selector[3]) {
619 	case 0:	/* use group data cipher suite */
620 		printf("usegroup");
621 		break;
622 	case 1:	/* WEP-40 */
623 		printf("wep40");
624 		break;
625 	case 2:	/* TKIP */
626 		printf("tkip");
627 		break;
628 	case 4:	/* CCMP (RSNA default) */
629 		printf("ccmp");
630 		break;
631 	case 5:	/* WEP-104 */
632 		printf("wep104");
633 		break;
634 	case 6:	/* BIP */
635 		printf("bip");
636 		break;
637 	default:
638 		printf("%d", selector[3]);
639 		break;
640 	}
641 }
642 
643 void
644 ieee80211_print_akm(uint8_t selector[4])
645 {
646 	if (memcmp(selector, MICROSOFT_OUI, 3) != 0 &&
647 	    memcmp(selector, IEEE80211_OUI, 3) != 0) {
648 		printf("0x%x%x%x%x", selector[0], selector[1], selector[2],
649 		     selector[3]);
650 	    	return;
651 	}
652 
653 	switch (selector[3]) {
654 	case 1:
655 		printf("802.1x");
656 		break;
657 	case 2:
658 		printf("PSK");
659 		break;
660 	case 5:
661 		printf("SHA256-802.1x");
662 		break;
663 	case 6:
664 		printf("SHA256-PSK");
665 		break;
666 	default:
667 		printf("%d", selector[3]);
668 		break;
669 	}
670 }
671 
672 /* Caller checks len */
673 void
674 ieee80211_print_rsn(u_int8_t *data, u_int len)
675 {
676 	uint16_t version, nciphers, nakms, rsncap, npmk;
677 	int i, j;
678 	uint8_t selector[4];
679 
680 	if (len < 2) {
681 		ieee80211_print_element(data, len);
682 		return;
683 	}
684 
685 	version = (data[0]) | (data[1] << 8);
686 	printf("=<version %d", version);
687 
688 	if (len < 6) {
689 		printf(">");
690 		return;
691 	}
692 
693 	data += 2;
694 	printf(",groupcipher ");
695 	for (i = 0; i < 4; i++)
696 		selector[i] = data[i];
697 	ieee80211_print_rsncipher(selector);
698 
699 	if (len < 8) {
700 		printf(">");
701 		return;
702 	}
703 
704 	data += 4;
705 	nciphers = (data[0]) | ((data[1]) << 8);
706 	data += 2;
707 
708 	if (len < 8 + (nciphers * 4)) {
709 		printf(">");
710 		return;
711 	}
712 
713 	printf(",cipher%s ", nciphers > 1 ? "s" : "");
714 	for (i = 0; i < nciphers; i++) {
715 		for (j = 0; j < 4; j++)
716 			selector[j] = data[i + j];
717 		ieee80211_print_rsncipher(selector);
718 		if (i < nciphers - 1)
719 			printf(" ");
720 		data += 4;
721 	}
722 
723 	if (len < 8 + (nciphers * 4) + 2) {
724 		printf(">");
725 		return;
726 	}
727 
728 	nakms = (data[0]) | ((data[1]) << 8);
729 	data += 2;
730 
731 	if (len < 8 + (nciphers * 4) + 2 + (nakms * 4)) {
732 		printf(">");
733 		return;
734 	}
735 
736 	printf(",akm%s ", nakms > 1 ? "s" : "");
737 	for (i = 0; i < nciphers; i++) {
738 		for (j = 0; j < 4; j++)
739 			selector[j] = data[i + j];
740 		ieee80211_print_akm(selector);
741 		if (i < nciphers - 1)
742 			printf(" ");
743 		data += 4;
744 	}
745 
746 	if (len < 8 + (nciphers * 4) + 2 + (nakms * 4) + 2) {
747 		printf(">");
748 		return;
749 	}
750 
751 	rsncap = (data[0]) | ((data[1]) << 8);
752 	printf(",rsncap 0x%x", rsncap);
753 	data += 2;
754 
755 	if (len < 8 + (nciphers * 4) + 2 + (nakms * 4) + 2 + 2) {
756 		printf(">");
757 		return;
758 	}
759 
760 	npmk = (data[0]) | ((data[1]) << 8);
761 	data += 2;
762 
763 	if (len < 8 + (nciphers * 4) + 2 + (nakms * 4) + 2 + 2 +
764 	    (npmk * IEEE80211_PMKID_LEN)) {
765 		printf(">");
766 		return;
767 	}
768 
769 	if (npmk >= 1)
770 		printf(",pmkid%s ", npmk > 1 ? "s" : "");
771 	for (i = 0; i < npmk; i++) {
772 		printf("0x");
773 		for (j = 0; j < IEEE80211_PMKID_LEN; j++)
774 			printf("%x", data[i + j]);
775 		if (i < npmk - 1)
776 			printf(" ");
777 		data += IEEE80211_PMKID_LEN;
778 	}
779 
780 	if (len < 8 + (nciphers * 4) + 2 + (nakms * 4) + 2 + 2 +
781 	    (npmk * IEEE80211_PMKID_LEN) + 4) {
782 		printf(">");
783 		return;
784 	}
785 
786 	printf(",integrity-groupcipher ");
787 	for (i = 0; i < 4; i++)
788 		selector[i] = data[i];
789 	ieee80211_print_rsncipher(selector);
790 
791 	printf(">");
792 }
793 
794 int
795 ieee80211_print_beacon(struct ieee80211_frame *wh, u_int len)
796 {
797 	uint64_t tstamp;
798 	uint16_t bintval, capinfo;
799 	uint8_t *frm;
800 
801 	if (len < sizeof(tstamp) + sizeof(bintval) + sizeof(capinfo))
802 		return 1; /* truncated */
803 
804 	frm = (u_int8_t *)&wh[1];
805 
806 	bcopy(frm, &tstamp, sizeof(u_int64_t));
807 	frm += 8;
808 	if (vflag > 1)
809 		printf(", timestamp %llu", letoh64(tstamp));
810 
811 	bcopy(frm, &bintval, sizeof(u_int16_t));
812 	frm += 2;
813 	if (vflag > 1)
814 		printf(", interval %u", letoh16(bintval));
815 
816 	bcopy(frm, &capinfo, sizeof(u_int16_t));
817 	frm += 2;
818 	if (vflag)
819 		printb(", caps", letoh16(capinfo), IEEE80211_CAPINFO_BITS);
820 
821 	return ieee80211_print_elements(frm);
822 }
823 
824 int
825 ieee80211_print_assocreq(struct ieee80211_frame *wh, u_int len)
826 {
827 	uint8_t subtype;
828 	uint16_t capinfo, lintval;
829 	uint8_t *frm;
830 
831 	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
832 
833 	if (len < sizeof(capinfo) + sizeof(lintval) +
834 	    (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ ?
835 	    IEEE80211_ADDR_LEN : 0))
836 		return 1; /* truncated */
837 
838 	frm = (u_int8_t *)&wh[1];
839 
840 	bcopy(frm, &capinfo, sizeof(u_int16_t));
841 	frm += 2;
842 	if (vflag)
843 		printb(", caps", letoh16(capinfo), IEEE80211_CAPINFO_BITS);
844 
845 	bcopy(frm, &lintval, sizeof(u_int16_t));
846 	frm += 2;
847 	if (vflag > 1)
848 		printf(", listen interval %u", letoh16(lintval));
849 
850 	if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
851 		if (vflag)
852 			printf(", AP %s", etheraddr_string(frm));
853 		frm += IEEE80211_ADDR_LEN;
854 	}
855 
856 	return ieee80211_print_elements(frm);
857 }
858 
859 int
860 ieee80211_print_elements(uint8_t *frm)
861 {
862 	int i;
863 
864 	while (TTEST2(*frm, 2)) {
865 		u_int len = frm[1];
866 		u_int8_t *data = frm + 2;
867 
868 		if (!TTEST2(*data, len))
869 			break;
870 
871 #define ELEM_CHECK(l)	if (len != l) goto trunc
872 
873 		switch (*frm) {
874 		case IEEE80211_ELEMID_SSID:
875 			printf(", ssid");
876 			ieee80211_print_essid(data, len);
877 			break;
878 		case IEEE80211_ELEMID_RATES:
879 			printf(", rates");
880 			if (!vflag)
881 				break;
882 			for (i = len; i > 0; i--, data++)
883 				printf(" %uM%s",
884 				    (data[0] & IEEE80211_RATE_VAL) / 2,
885 				    (data[0] & IEEE80211_RATE_BASIC
886 				    ? "*" : ""));
887 			break;
888 		case IEEE80211_ELEMID_FHPARMS:
889 			ELEM_CHECK(5);
890 			printf(", fh (dwell %u, chan %u, index %u)",
891 			    (data[1] << 8) | data[0],
892 			    (data[2] - 1) * 80 + data[3],	/* FH_CHAN */
893 			    data[4]);
894 			break;
895 		case IEEE80211_ELEMID_DSPARMS:
896 			ELEM_CHECK(1);
897 			printf(", ds");
898 			if (vflag)
899 				printf(" (chan %u)", data[0]);
900 			break;
901 		case IEEE80211_ELEMID_CFPARMS:
902 			printf(", cf");
903 			if (vflag)
904 				ieee80211_print_element(data, len);
905 			break;
906 		case IEEE80211_ELEMID_TIM:
907 			printf(", tim");
908 			if (vflag)
909 				ieee80211_print_element(data, len);
910 			break;
911 		case IEEE80211_ELEMID_IBSSPARMS:
912 			printf(", ibss");
913 			if (vflag)
914 				ieee80211_print_element(data, len);
915 			break;
916 		case IEEE80211_ELEMID_COUNTRY:
917 			printf(", country");
918 			if (vflag)
919 				ieee80211_print_country(data, len);
920 			break;
921 		case IEEE80211_ELEMID_CHALLENGE:
922 			printf(", challenge");
923 			if (vflag)
924 				ieee80211_print_element(data, len);
925 			break;
926 		case IEEE80211_ELEMID_CSA:
927 			ELEM_CHECK(3);
928 			printf(", csa (chan %u count %u%s)", data[1], data[2],
929 			    (data[0] == 1) ? " noTX" : "");
930 			break;
931 		case IEEE80211_ELEMID_ERP:
932 			printf(", erp");
933 			if (vflag)
934 				ieee80211_print_element(data, len);
935 			break;
936 		case IEEE80211_ELEMID_RSN:
937 			printf(", rsn");
938 			if (vflag)
939 				ieee80211_print_rsn(data, len);
940 			break;
941 		case IEEE80211_ELEMID_XRATES:
942 			printf(", xrates");
943 			if (!vflag)
944 				break;
945 			for (i = len; i > 0; i--, data++)
946 				printf(" %uM",
947 				    (data[0] & IEEE80211_RATE_VAL) / 2);
948 			break;
949 		case IEEE80211_ELEMID_TPC_REPORT:
950 			printf(", tpcreport");
951 			if (vflag)
952 				ieee80211_print_element(data, len);
953 			break;
954 		case IEEE80211_ELEMID_TPC_REQUEST:
955 			printf(", tpcrequest");
956 			if (vflag)
957 				ieee80211_print_element(data, len);
958 			break;
959 		case IEEE80211_ELEMID_HTCAPS:
960 			printf(", htcaps");
961 			if (vflag)
962 				ieee80211_print_htcaps(data, len);
963 			break;
964 		case IEEE80211_ELEMID_HTOP:
965 			printf(", htop");
966 			if (vflag)
967 				ieee80211_print_htop(data, len);
968 			break;
969 		case IEEE80211_ELEMID_POWER_CONSTRAINT:
970 			ELEM_CHECK(1);
971 			printf(", power constraint %udB", data[0]);
972 			break;
973 		case IEEE80211_ELEMID_QBSS_LOAD:
974 			ELEM_CHECK(5);
975 			printf(", %u stations, %d%% utilization, "
976 			    "admission capacity %uus/s",
977 			    (data[0] | data[1] << 8),
978 			    (data[2] * 100) / 255,
979 			    (data[3] | data[4] << 8) / 32);
980 			break;
981 		case IEEE80211_ELEMID_VENDOR:
982 			printf(", vendor");
983 			if (vflag)
984 				ieee80211_print_element(data, len);
985 			break;
986 		default:
987 			printf(", %u:%u", (u_int) *frm, len);
988 			if (vflag)
989 				ieee80211_print_element(data, len);
990 			break;
991 		}
992 		frm += len + 2;
993 
994 		if (frm >= snapend)
995 			break;
996 	}
997 
998 #undef ELEM_CHECK
999 
1000 	return (0);
1001 
1002  trunc:
1003 	/* Truncated elements in frame */
1004 	return (1);
1005 }
1006 
1007 int
1008 ieee80211_frame(struct ieee80211_frame *wh, u_int len)
1009 {
1010 	u_int8_t subtype, type, *frm;
1011 
1012 	TCARR(wh->i_fc);
1013 
1014 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1015 	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1016 
1017 	frm = (u_int8_t *)&wh[1];
1018 
1019 	if (vflag)
1020 		printb(" flags", wh->i_fc[1], IEEE80211_FC1_BITS);
1021 
1022 	switch (type) {
1023 	case IEEE80211_FC0_TYPE_DATA:
1024 		printf(": %s: ", ieee80211_data_subtype_name[
1025 		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
1026 		ieee80211_data(wh, len);
1027 		break;
1028 	case IEEE80211_FC0_TYPE_MGT:
1029 		printf(": %s", ieee80211_mgt_subtype_name[
1030 		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
1031 		switch (subtype) {
1032 		case IEEE80211_FC0_SUBTYPE_BEACON:
1033 		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
1034 			if (ieee80211_print_beacon(wh, len) != 0)
1035 				goto trunc;
1036 			break;
1037 		case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
1038 		case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
1039 			if (ieee80211_print_assocreq(wh, len) != 0)
1040 				goto trunc;
1041 			break;
1042 		case IEEE80211_FC0_SUBTYPE_AUTH:
1043 			TCHECK2(*frm, 2);		/* Auth Algorithm */
1044 			switch (IEEE80211_AUTH_ALGORITHM(frm)) {
1045 			case IEEE80211_AUTH_ALG_OPEN:
1046 				TCHECK2(*frm, 4);	/* Auth Transaction */
1047 				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
1048 				case IEEE80211_AUTH_OPEN_REQUEST:
1049 					printf(" request");
1050 					break;
1051 				case IEEE80211_AUTH_OPEN_RESPONSE:
1052 					printf(" response");
1053 					break;
1054 				}
1055 				break;
1056 			case IEEE80211_AUTH_ALG_SHARED:
1057 				TCHECK2(*frm, 4);	/* Auth Transaction */
1058 				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
1059 				case IEEE80211_AUTH_SHARED_REQUEST:
1060 					printf(" request");
1061 					break;
1062 				case IEEE80211_AUTH_SHARED_CHALLENGE:
1063 					printf(" challenge");
1064 					break;
1065 				case IEEE80211_AUTH_SHARED_RESPONSE:
1066 					printf(" response");
1067 					break;
1068 				case IEEE80211_AUTH_SHARED_PASS:
1069 					printf(" pass");
1070 					break;
1071 				}
1072 				break;
1073 			case IEEE80211_AUTH_ALG_LEAP:
1074 				printf(" (leap)");
1075 				break;
1076 			}
1077 			break;
1078 		case IEEE80211_FC0_SUBTYPE_DEAUTH:
1079 		case IEEE80211_FC0_SUBTYPE_DISASSOC:
1080 			TCHECK2(*frm, 2);		/* Reason Code */
1081 			ieee80211_reason(frm[0] | (frm[1] << 8));
1082 			break;
1083 		}
1084 		break;
1085 	case IEEE80211_FC0_TYPE_CTL: {
1086 		u_int8_t *t = (u_int8_t *) wh;
1087 
1088 		printf(": %s", ieee80211_ctl_subtype_name[
1089 		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
1090 		if (!vflag)
1091 			break;
1092 
1093 		/* See 802.11 2012 "8.3.1 Control frames". */
1094 		t += 2; /* skip Frame Control */
1095 		switch (subtype) {
1096 		case IEEE80211_FC0_SUBTYPE_RTS:
1097 		case IEEE80211_FC0_SUBTYPE_BAR:
1098 		case IEEE80211_FC0_SUBTYPE_BA:
1099 			TCHECK2(*t, 2); /* Duration */
1100 			printf(", duration %dus", (t[0] | t[1] << 8));
1101 			t += 2;
1102 			TCHECK2(*t, 6); /* RA */
1103 			printf(", ra %s", etheraddr_string(t));
1104 			t += 6;
1105 			TCHECK2(*t, 6); /* TA */
1106 			printf(", ta %s", etheraddr_string(t));
1107 			if (subtype == IEEE80211_FC0_SUBTYPE_BAR ||
1108 			    subtype == IEEE80211_FC0_SUBTYPE_BA) {
1109 				u_int16_t ctrl;
1110 
1111 				t += 6;
1112 				TCHECK2(*t, 2); /* BAR/BA control */
1113 				ctrl = t[0] | (t[1] << 8);
1114 				if (ctrl & IEEE80211_BA_ACK_POLICY)
1115 					printf(", no ack");
1116 				else
1117 					printf(", normal ack");
1118 				if ((ctrl & IEEE80211_BA_MULTI_TID) == 0 &&
1119 				    (ctrl & IEEE80211_BA_COMPRESSED) == 0)
1120 					printf(", basic variant");
1121 				else if ((ctrl & IEEE80211_BA_MULTI_TID) &&
1122 				    (ctrl & IEEE80211_BA_COMPRESSED))
1123 					printf(", multi-tid variant");
1124 				else if (ctrl & IEEE80211_BA_COMPRESSED)
1125 					printf(", compressed variant");
1126 			}
1127 			break;
1128 		case IEEE80211_FC0_SUBTYPE_CTS:
1129 		case IEEE80211_FC0_SUBTYPE_ACK:
1130 			TCHECK2(*t, 2); /* Duration */
1131 			printf(", duration %dus", (t[0] | t[1] << 8));
1132 			t += 2;
1133 			TCHECK2(*t, 6); /* RA */
1134 			printf(", ra %s", etheraddr_string(t));
1135 			break;
1136 		case IEEE80211_FC0_SUBTYPE_PS_POLL:
1137 			TCHECK2(*t, 2); /* AID */
1138 			printf(", aid 0x%x", (t[0] | t[1] << 8));
1139 			t += 2;
1140 			TCHECK2(*t, 6); /* BSSID(RA) */
1141 			printf(", ra %s", etheraddr_string(t));
1142 			t += 6;
1143 			TCHECK2(*t, 6); /* TA */
1144 			printf(", ta %s", etheraddr_string(t));
1145 			break;
1146 		}
1147 		break;
1148 	}
1149 	default:
1150 		printf(": type#%d", type);
1151 		break;
1152 	}
1153 
1154 	return (0);
1155 
1156  trunc:
1157 	/* Truncated 802.11 frame */
1158 	return (1);
1159 }
1160 
1161 u_int
1162 ieee80211_any2ieee(u_int freq, u_int flags)
1163 {
1164 	if (flags & IEEE80211_CHAN_2GHZ) {
1165 		if (freq == 2484)
1166 			return 14;
1167 		if (freq < 2484)
1168 			return (freq - 2407) / 5;
1169 		else
1170 			return 15 + ((freq - 2512) / 20);
1171 	} else if (flags & IEEE80211_CHAN_5GHZ) {
1172 		return (freq - 5000) / 5;
1173 	} else {
1174 		/* Assume channel is already an IEEE number */
1175 		return (freq);
1176 	}
1177 }
1178 
1179 int
1180 ieee80211_print(struct ieee80211_frame *wh, u_int len)
1181 {
1182 	if (eflag)
1183 		if (ieee80211_hdr(wh))
1184 			return (1);
1185 
1186 	printf("802.11");
1187 
1188 	return (ieee80211_frame(wh, len));
1189 }
1190 
1191 void
1192 ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h,
1193     const u_char *p)
1194 {
1195 	struct ieee80211_frame *wh = (struct ieee80211_frame*)p;
1196 
1197 	if (!ieee80211_encap)
1198 		ts_print(&h->ts);
1199 
1200 	packetp = p;
1201 	snapend = p + h->caplen;
1202 
1203 	if (ieee80211_print(wh, (u_int)h->len) != 0)
1204 		printf("[|802.11]");
1205 
1206 	if (!ieee80211_encap) {
1207 		if (xflag)
1208 			default_print(p, (u_int)h->len);
1209 		putchar('\n');
1210 	}
1211 }
1212 
1213 void
1214 ieee802_11_radio_if_print(u_char *user, const struct pcap_pkthdr *h,
1215     const u_char *p)
1216 {
1217 	struct ieee80211_radiotap_header *rh =
1218 	    (struct ieee80211_radiotap_header*)p;
1219 	struct ieee80211_frame *wh;
1220 	u_int8_t *t;
1221 	u_int32_t present;
1222 	u_int len, rh_len;
1223 	u_int16_t tmp;
1224 
1225 	if (!ieee80211_encap)
1226 		ts_print(&h->ts);
1227 
1228 	packetp = p;
1229 	snapend = p + h->caplen;
1230 
1231 	TCHECK(*rh);
1232 
1233 	len = h->len;
1234 	rh_len = letoh16(rh->it_len);
1235 	if (rh->it_version != 0) {
1236 		printf("[?radiotap + 802.11 v:%u]", rh->it_version);
1237 		goto out;
1238 	}
1239 
1240 	wh = (struct ieee80211_frame *)(p + rh_len);
1241 	if (len <= rh_len || ieee80211_print(wh, len - rh_len))
1242 		printf("[|802.11]");
1243 
1244 	t = (u_int8_t*)p + sizeof(struct ieee80211_radiotap_header);
1245 
1246 	if ((present = letoh32(rh->it_present)) == 0)
1247 		goto out;
1248 
1249 	printf(", <radiotap v%u", rh->it_version);
1250 
1251 #define RADIOTAP(_x)	\
1252 	(present & (1 << IEEE80211_RADIOTAP_##_x))
1253 
1254 	if (RADIOTAP(TSFT)) {
1255 		u_int64_t tsf;
1256 
1257 		TCHECK2(*t, 8);
1258 		bcopy(t, &tsf, sizeof(u_int64_t));
1259 		if (vflag > 1)
1260 			printf(", tsf %llu", letoh64(tsf));
1261 		t += 8;
1262 	}
1263 
1264 	if (RADIOTAP(FLAGS)) {
1265 		u_int8_t flags = *(u_int8_t*)t;
1266 		TCHECK2(*t, 1);
1267 
1268 		if (flags & IEEE80211_RADIOTAP_F_CFP)
1269 			printf(", CFP");
1270 		if (flags & IEEE80211_RADIOTAP_F_SHORTPRE)
1271 			printf(", SHORTPRE");
1272 		if (flags & IEEE80211_RADIOTAP_F_WEP)
1273 			printf(", WEP");
1274 		if (flags & IEEE80211_RADIOTAP_F_FRAG)
1275 			printf(", FRAG");
1276 		t += 1;
1277 	}
1278 
1279 	if (RADIOTAP(RATE)) {
1280 		TCHECK2(*t, 1);
1281 		if (vflag) {
1282 			uint8_t rate = *(u_int8_t*)t;
1283 			if (rate & 0x80)
1284 				printf(", MCS %u", rate & 0x7f);
1285 			else
1286 				printf(", %uMbit/s", rate / 2);
1287 		}
1288 		t += 1;
1289 	}
1290 
1291 	if (RADIOTAP(CHANNEL)) {
1292 		u_int16_t freq, flags;
1293 		TCHECK2(*t, 2);
1294 
1295 		bcopy(t, &freq, sizeof(u_int16_t));
1296 		freq = letoh16(freq);
1297 		t += 2;
1298 		TCHECK2(*t, 2);
1299 		bcopy(t, &flags, sizeof(u_int16_t));
1300 		flags = letoh16(flags);
1301 		t += 2;
1302 
1303 		printf(", chan %u", ieee80211_any2ieee(freq, flags));
1304 
1305 		if (flags & IEEE80211_CHAN_HT)
1306 			printf(", 11n");
1307 		else if (flags & IEEE80211_CHAN_DYN &&
1308 		    flags & IEEE80211_CHAN_2GHZ)
1309 			printf(", 11g");
1310 		else if (flags & IEEE80211_CHAN_CCK &&
1311 		    flags & IEEE80211_CHAN_2GHZ)
1312 			printf(", 11b");
1313 		else if (flags & IEEE80211_CHAN_OFDM &&
1314 		    flags & IEEE80211_CHAN_2GHZ)
1315 			printf(", 11G");
1316 		else if (flags & IEEE80211_CHAN_OFDM &&
1317 		    flags & IEEE80211_CHAN_5GHZ)
1318 			printf(", 11a");
1319 
1320 		if (flags & IEEE80211_CHAN_XR)
1321 			printf(", XR");
1322 	}
1323 
1324 	if (RADIOTAP(FHSS)) {
1325 		TCHECK2(*t, 2);
1326 		printf(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1);
1327 		t += 2;
1328 	}
1329 
1330 	if (RADIOTAP(DBM_ANTSIGNAL)) {
1331 		TCHECK(*t);
1332 		printf(", sig %ddBm", *(int8_t*)t);
1333 		t += 1;
1334 	}
1335 
1336 	if (RADIOTAP(DBM_ANTNOISE)) {
1337 		TCHECK(*t);
1338 		printf(", noise %ddBm", *(int8_t*)t);
1339 		t += 1;
1340 	}
1341 
1342 	if (RADIOTAP(LOCK_QUALITY)) {
1343 		TCHECK2(*t, 2);
1344 		if (vflag) {
1345 			bcopy(t, &tmp, sizeof(u_int16_t));
1346 			printf(", quality %u", letoh16(tmp));
1347 		}
1348 		t += 2;
1349 	}
1350 
1351 	if (RADIOTAP(TX_ATTENUATION)) {
1352 		TCHECK2(*t, 2);
1353 		if (vflag) {
1354 			bcopy(t, &tmp, sizeof(u_int16_t));
1355 			printf(", txatt %u", letoh16(tmp));
1356 		}
1357 		t += 2;
1358 	}
1359 
1360 	if (RADIOTAP(DB_TX_ATTENUATION)) {
1361 		TCHECK2(*t, 2);
1362 		if (vflag) {
1363 			bcopy(t, &tmp, sizeof(u_int16_t));
1364 			printf(", txatt %udB", letoh16(tmp));
1365 		}
1366 		t += 2;
1367 	}
1368 
1369 	if (RADIOTAP(DBM_TX_POWER)) {
1370 		TCHECK(*t);
1371 		printf(", txpower %ddBm", *(int8_t*)t);
1372 		t += 1;
1373 	}
1374 
1375 	if (RADIOTAP(ANTENNA)) {
1376 		TCHECK(*t);
1377 		if (vflag)
1378 			printf(", antenna %u", *(u_int8_t*)t);
1379 		t += 1;
1380 	}
1381 
1382 	if (RADIOTAP(DB_ANTSIGNAL)) {
1383 		TCHECK(*t);
1384 		printf(", signal %udB", *(u_int8_t*)t);
1385 		t += 1;
1386 	}
1387 
1388 	if (RADIOTAP(DB_ANTNOISE)) {
1389 		TCHECK(*t);
1390 		printf(", noise %udB", *(u_int8_t*)t);
1391 		t += 1;
1392 	}
1393 
1394 	if (RADIOTAP(FCS)) {
1395 		TCHECK2(*t, 4);
1396 		if (vflag) {
1397 			u_int32_t fcs;
1398 			bcopy(t, &fcs, sizeof(u_int32_t));
1399 			printf(", fcs %08x", letoh32(fcs));
1400 		}
1401 		t += 4;
1402 	}
1403 
1404 	if (RADIOTAP(RSSI)) {
1405 		u_int8_t rssi, max_rssi;
1406 		TCHECK(*t);
1407 		rssi = *(u_int8_t*)t;
1408 		t += 1;
1409 		TCHECK(*t);
1410 		max_rssi = *(u_int8_t*)t;
1411 		t += 1;
1412 
1413 		printf(", rssi %u/%u", rssi, max_rssi);
1414 	}
1415 
1416 #undef RADIOTAP
1417 
1418 	putchar('>');
1419 	goto out;
1420 
1421  trunc:
1422 	/* Truncated frame */
1423 	printf("[|radiotap + 802.11]");
1424 
1425  out:
1426 	if (!ieee80211_encap) {
1427 		if (xflag)
1428 			default_print(p, h->len);
1429 		putchar('\n');
1430 	}
1431 }
1432 
1433 void
1434 ieee80211_reason(u_int16_t reason)
1435 {
1436 	if (!vflag)
1437 		return;
1438 
1439 	switch (reason) {
1440 	case IEEE80211_REASON_UNSPECIFIED:
1441 		printf(", unspecified failure");
1442 		break;
1443 	case IEEE80211_REASON_AUTH_EXPIRE:
1444 		printf(", authentication expired");
1445 		break;
1446 	case IEEE80211_REASON_AUTH_LEAVE:
1447 		printf(", deauth - station left");
1448 		break;
1449 	case IEEE80211_REASON_ASSOC_EXPIRE:
1450 		printf(", association expired");
1451 		break;
1452 	case IEEE80211_REASON_ASSOC_TOOMANY:
1453 		printf(", too many associated stations");
1454 		break;
1455 	case IEEE80211_REASON_NOT_AUTHED:
1456 		printf(", not authenticated");
1457 		break;
1458 	case IEEE80211_REASON_NOT_ASSOCED:
1459 		printf(", not associated");
1460 		break;
1461 	case IEEE80211_REASON_ASSOC_LEAVE:
1462 		printf(", disassociated - station left");
1463 		break;
1464 	case IEEE80211_REASON_ASSOC_NOT_AUTHED:
1465 		printf(", association but not authenticated");
1466 		break;
1467 	case IEEE80211_REASON_RSN_REQUIRED:
1468 		printf(", rsn required");
1469 		break;
1470 	case IEEE80211_REASON_RSN_INCONSISTENT:
1471 		printf(", rsn inconsistent");
1472 		break;
1473 	case IEEE80211_REASON_IE_INVALID:
1474 		printf(", ie invalid");
1475 		break;
1476 	case IEEE80211_REASON_MIC_FAILURE:
1477 		printf(", mic failure");
1478 		break;
1479 	default:
1480 		printf(", unknown reason %u", reason);
1481 	}
1482 }
1483