xref: /openbsd-src/usr.sbin/hostapd/print-802_11.c (revision cb21588b789e158a41a4783b1dcf238685d192fc)
1*cb21588bSguenther /*	$OpenBSD: print-802_11.c,v 1.11 2019/05/10 01:29:31 guenther Exp $	*/
250ce650fSreyk 
350ce650fSreyk /*
42c56d0d6Sreyk  * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org>
550ce650fSreyk  *
650ce650fSreyk  * Permission to use, copy, modify, and distribute this software for any
750ce650fSreyk  * purpose with or without fee is hereby granted, provided that the above
850ce650fSreyk  * copyright notice and this permission notice appear in all copies.
950ce650fSreyk  *
1050ce650fSreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1150ce650fSreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1250ce650fSreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1350ce650fSreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1450ce650fSreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1550ce650fSreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1650ce650fSreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1750ce650fSreyk  */
1850ce650fSreyk 
1950ce650fSreyk /* usr.sbin/tcpdump/print-802_11.c,v 1.3 2005/03/09 11:43:17 deraadt Exp */
2050ce650fSreyk 
2150ce650fSreyk #include <sys/time.h>
2250ce650fSreyk #include <sys/socket.h>
2350ce650fSreyk 
2450ce650fSreyk #include <net/if.h>
2550ce650fSreyk #include <net/if_media.h>
2650ce650fSreyk #include <net/if_arp.h>
2750ce650fSreyk #include <net/if_llc.h>
2850ce650fSreyk #include <net/bpf.h>
2950ce650fSreyk 
3050ce650fSreyk #include <netinet/in.h>
3150ce650fSreyk #include <netinet/if_ether.h>
3250ce650fSreyk #include <arpa/inet.h>
3350ce650fSreyk 
3450ce650fSreyk #include <net80211/ieee80211.h>
3550ce650fSreyk #include <net80211/ieee80211_radiotap.h>
3650ce650fSreyk 
3750ce650fSreyk #include <pcap.h>
3850ce650fSreyk #include <stdio.h>
3950ce650fSreyk #include <string.h>
40b9fc9a72Sderaadt #include <limits.h>
4150ce650fSreyk 
4250ce650fSreyk #include "hostapd.h"
4350ce650fSreyk 
4450ce650fSreyk const char *ieee80211_mgt_subtype_name[] = {
4550ce650fSreyk 	"association request",
4650ce650fSreyk 	"association response",
4750ce650fSreyk 	"reassociation request",
4850ce650fSreyk 	"reassociation response",
4950ce650fSreyk 	"probe request",
5050ce650fSreyk 	"probe response",
5150ce650fSreyk 	"reserved#6",
5250ce650fSreyk 	"reserved#7",
5350ce650fSreyk 	"beacon",
5450ce650fSreyk 	"atim",
5550ce650fSreyk 	"disassociation",
5650ce650fSreyk 	"authentication",
5750ce650fSreyk 	"deauthentication",
5850ce650fSreyk 	"reserved#13",
5950ce650fSreyk 	"reserved#14",
6050ce650fSreyk 	"reserved#15"
6150ce650fSreyk };
6250ce650fSreyk 
6350ce650fSreyk const u_int8_t *snapend;
6450ce650fSreyk int vflag = 1, eflag = 1;
6550ce650fSreyk 
6650ce650fSreyk int	 ieee80211_hdr(struct ieee80211_frame *);
6750ce650fSreyk void	 ieee80211_print_element(u_int8_t *, u_int);
6850ce650fSreyk void	 ieee80211_print_essid(u_int8_t *, u_int);
6969952658Sreyk int	 ieee80211_elements(struct ieee80211_frame *);
7069952658Sreyk int	 ieee80211_frame(struct ieee80211_frame *);
7169952658Sreyk int	 ieee80211_print(struct ieee80211_frame *);
7250ce650fSreyk u_int	 ieee80211_any2ieee(u_int, u_int);
7350ce650fSreyk void	 ieee802_11_if_print(u_int8_t *, u_int);
7450ce650fSreyk void	 ieee802_11_radio_if_print(u_int8_t *, u_int);
7550ce650fSreyk 
7650ce650fSreyk #define TCARR(a)	TCHECK2(*a, sizeof(a))
7750ce650fSreyk 
7850ce650fSreyk int
ieee80211_hdr(struct ieee80211_frame * wh)7950ce650fSreyk ieee80211_hdr(struct ieee80211_frame *wh)
8050ce650fSreyk {
8150ce650fSreyk 	struct ieee80211_frame_addr4 *w4;
8250ce650fSreyk 
8350ce650fSreyk 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
8450ce650fSreyk 	case IEEE80211_FC1_DIR_NODS:
8550ce650fSreyk 		TCARR(wh->i_addr2);
8650ce650fSreyk 		PRINTF("%s", etheraddr_string(wh->i_addr2));
8750ce650fSreyk 		TCARR(wh->i_addr1);
8850ce650fSreyk 		PRINTF(" > %s", etheraddr_string(wh->i_addr1));
8950ce650fSreyk 		TCARR(wh->i_addr3);
9050ce650fSreyk 		PRINTF(", bssid %s", etheraddr_string(wh->i_addr3));
9150ce650fSreyk 		break;
9250ce650fSreyk 	case IEEE80211_FC1_DIR_TODS:
9350ce650fSreyk 		TCARR(wh->i_addr2);
9450ce650fSreyk 		PRINTF("%s", etheraddr_string(wh->i_addr2));
9550ce650fSreyk 		TCARR(wh->i_addr3);
9650ce650fSreyk 		PRINTF(" > %s", etheraddr_string(wh->i_addr3));
9750ce650fSreyk 		TCARR(wh->i_addr1);
9850ce650fSreyk 		PRINTF(", bssid %s, > DS", etheraddr_string(wh->i_addr1));
9950ce650fSreyk 		break;
10050ce650fSreyk 	case IEEE80211_FC1_DIR_FROMDS:
10150ce650fSreyk 		TCARR(wh->i_addr3);
10250ce650fSreyk 		PRINTF("%s", etheraddr_string(wh->i_addr3));
10350ce650fSreyk 		TCARR(wh->i_addr1);
10450ce650fSreyk 		PRINTF(" > %s", etheraddr_string(wh->i_addr1));
10550ce650fSreyk 		TCARR(wh->i_addr2);
10650ce650fSreyk 		PRINTF(", bssid %s, DS >", etheraddr_string(wh->i_addr2));
10750ce650fSreyk 		break;
10850ce650fSreyk 	case IEEE80211_FC1_DIR_DSTODS:
10950ce650fSreyk 		w4 = (struct ieee80211_frame_addr4 *) wh;
11050ce650fSreyk 		TCARR(w4->i_addr4);
11150ce650fSreyk 		PRINTF("%s", etheraddr_string(w4->i_addr4));
11250ce650fSreyk 		TCARR(w4->i_addr3);
11350ce650fSreyk 		PRINTF(" > %s", etheraddr_string(w4->i_addr3));
11450ce650fSreyk 		TCARR(w4->i_addr2);
11550ce650fSreyk 		PRINTF(", bssid %s", etheraddr_string(w4->i_addr2));
11650ce650fSreyk 		TCARR(w4->i_addr1);
11750ce650fSreyk 		PRINTF(" > %s, DS > DS", etheraddr_string(w4->i_addr1));
11850ce650fSreyk 		break;
11950ce650fSreyk 	}
12050ce650fSreyk 	if (vflag) {
12150ce650fSreyk 		TCARR(wh->i_seq);
12250ce650fSreyk 		PRINTF(" (seq %u)", letoh16(*(u_int16_t *)&wh->i_seq[0]));
12350ce650fSreyk 	}
12450ce650fSreyk 
12550ce650fSreyk 	return (0);
12650ce650fSreyk 
12750ce650fSreyk  trunc:
12850ce650fSreyk 	/* Truncated elements in frame */
12950ce650fSreyk 	return (1);
13050ce650fSreyk }
13150ce650fSreyk 
13250ce650fSreyk /* Caller checks len */
13350ce650fSreyk void
ieee80211_print_element(u_int8_t * data,u_int len)13450ce650fSreyk ieee80211_print_element(u_int8_t *data, u_int len)
13550ce650fSreyk {
13650ce650fSreyk 	u_int8_t *p;
13750ce650fSreyk 	u_int i;
13850ce650fSreyk 
13950ce650fSreyk 	PRINTF(" 0x");
14050ce650fSreyk 	for (i = 0, p = data; i < len; i++, p++)
14150ce650fSreyk 		PRINTF("%02x", *p);
14250ce650fSreyk }
14350ce650fSreyk 
14450ce650fSreyk /* Caller checks len */
14550ce650fSreyk void
ieee80211_print_essid(u_int8_t * essid,u_int len)14650ce650fSreyk ieee80211_print_essid(u_int8_t *essid, u_int len)
14750ce650fSreyk {
14850ce650fSreyk 	u_int8_t *p;
14950ce650fSreyk 	u_int i;
15050ce650fSreyk 
15150ce650fSreyk 	if (len > IEEE80211_NWID_LEN)
15250ce650fSreyk 		len = IEEE80211_NWID_LEN;
15350ce650fSreyk 
15450ce650fSreyk 	/* determine printable or not */
15550ce650fSreyk 	for (i = 0, p = essid; i < len; i++, p++) {
15650ce650fSreyk 		if (*p < ' ' || *p > 0x7e)
15750ce650fSreyk 			break;
15850ce650fSreyk 	}
15950ce650fSreyk 	if (i == len) {
16050ce650fSreyk 		PRINTF(" (");
16150ce650fSreyk 		for (i = 0, p = essid; i < len; i++, p++)
16250ce650fSreyk 			PRINTF("%c", *p);
16350ce650fSreyk 		PRINTF(")");
16450ce650fSreyk 	} else
16550ce650fSreyk 		ieee80211_print_element(essid, len);
16650ce650fSreyk }
16750ce650fSreyk 
16850ce650fSreyk int
ieee80211_elements(struct ieee80211_frame * wh)16969952658Sreyk ieee80211_elements(struct ieee80211_frame *wh)
17050ce650fSreyk {
17169952658Sreyk 	u_int8_t *frm;
17250ce650fSreyk 	u_int8_t *tstamp, *bintval, *capinfo;
17350ce650fSreyk 	int i;
17450ce650fSreyk 
17550ce650fSreyk 	frm = (u_int8_t *)&wh[1];
17650ce650fSreyk 
17750ce650fSreyk 	tstamp = frm;
17850ce650fSreyk 	TCHECK2(*tstamp, 8);
17950ce650fSreyk 	frm += 8;
18050ce650fSreyk 
18150ce650fSreyk 	bintval = frm;
18250ce650fSreyk 	TCHECK2(*bintval, 2);
18350ce650fSreyk 	frm += 2;
18450ce650fSreyk 
18550ce650fSreyk 	if (vflag)
18650ce650fSreyk 		PRINTF(", interval %u", letoh16(*(u_int16_t *)bintval));
18750ce650fSreyk 
18850ce650fSreyk 	capinfo = frm;
18950ce650fSreyk 	TCHECK2(*capinfo, 2);
19050ce650fSreyk 	frm += 2;
19150ce650fSreyk 
19250ce650fSreyk #if 0
19350ce650fSreyk 	if (vflag)
19450ce650fSreyk 		printb(", caps", letoh16(*(u_int16_t *)capinfo),
19550ce650fSreyk 		    IEEE80211_CAPINFO_BITS);
19650ce650fSreyk #endif
19750ce650fSreyk 
19850ce650fSreyk 	while (TTEST2(*frm, 2)) {
19950ce650fSreyk 		u_int len = frm[1];
20050ce650fSreyk 		u_int8_t *data = frm + 2;
20150ce650fSreyk 
20250ce650fSreyk 		if (!TTEST2(*data, len))
20350ce650fSreyk 			break;
20450ce650fSreyk 
20550ce650fSreyk #define ELEM_CHECK(l)	if (len != l) break
20650ce650fSreyk 
20750ce650fSreyk 		switch (*frm) {
20850ce650fSreyk 		case IEEE80211_ELEMID_SSID:
20950ce650fSreyk 			PRINTF(", ssid");
21050ce650fSreyk 			ieee80211_print_essid(data, len);
21150ce650fSreyk 			break;
21250ce650fSreyk 		case IEEE80211_ELEMID_RATES:
21350ce650fSreyk 			if (!vflag)
21450ce650fSreyk 				break;
21550ce650fSreyk 			PRINTF(", rates");
21650ce650fSreyk 			for (i = len; i > 0; i--, data++)
21750ce650fSreyk 				PRINTF(" %uM",
21850ce650fSreyk 				    (data[0] & IEEE80211_RATE_VAL) / 2);
21950ce650fSreyk 			break;
22050ce650fSreyk 		case IEEE80211_ELEMID_FHPARMS:
22150ce650fSreyk 			ELEM_CHECK(5);
22250ce650fSreyk 			PRINTF(", fh (dwell %u, chan %u, index %u)",
22350ce650fSreyk 			    (data[1] << 8) | data[0],
22450ce650fSreyk 			    (data[2] - 1) * 80 + data[3],	/* FH_CHAN */
22550ce650fSreyk 			    data[4]);
22650ce650fSreyk 			break;
22750ce650fSreyk 		case IEEE80211_ELEMID_DSPARMS:
22850ce650fSreyk 			ELEM_CHECK(1);
22950ce650fSreyk 			if (!vflag)
23050ce650fSreyk 				break;
23150ce650fSreyk 			PRINTF(", ds");
23250ce650fSreyk 			PRINTF(" (chan %u)", data[0]);
23350ce650fSreyk 			break;
23450ce650fSreyk 		case IEEE80211_ELEMID_CFPARMS:
23550ce650fSreyk 			if (!vflag)
23650ce650fSreyk 				break;
23750ce650fSreyk 			PRINTF(", cf");
23850ce650fSreyk 			ieee80211_print_element(data, len);
23950ce650fSreyk 			break;
24050ce650fSreyk 		case IEEE80211_ELEMID_TIM:
24150ce650fSreyk 			if (!vflag)
24250ce650fSreyk 				break;
24350ce650fSreyk 			PRINTF(", tim");
24450ce650fSreyk 			ieee80211_print_element(data, len);
24550ce650fSreyk 			break;
24650ce650fSreyk 		case IEEE80211_ELEMID_IBSSPARMS:
24750ce650fSreyk 			if (!vflag)
24850ce650fSreyk 				break;
24950ce650fSreyk 			PRINTF(", ibss");
25050ce650fSreyk 			ieee80211_print_element(data, len);
25150ce650fSreyk 			break;
25250ce650fSreyk 		case IEEE80211_ELEMID_COUNTRY:
25350ce650fSreyk 			if (!vflag)
25450ce650fSreyk 				break;
25550ce650fSreyk 			PRINTF(", country");
25650ce650fSreyk 			for (i = len; i > 0; i--, data++)
25750ce650fSreyk 				PRINTF(" %u", data[0]);
25850ce650fSreyk 			break;
25950ce650fSreyk 		case IEEE80211_ELEMID_CHALLENGE:
26050ce650fSreyk 			if (!vflag)
26150ce650fSreyk 				break;
26250ce650fSreyk 			PRINTF(", challenge");
26350ce650fSreyk 			ieee80211_print_element(data, len);
26450ce650fSreyk 			break;
26550ce650fSreyk 		case IEEE80211_ELEMID_ERP:
26650ce650fSreyk 			if (!vflag)
26750ce650fSreyk 				break;
26850ce650fSreyk 			PRINTF(", erp");
26950ce650fSreyk 			ieee80211_print_element(data, len);
27050ce650fSreyk 			break;
27150ce650fSreyk 		case IEEE80211_ELEMID_RSN:
27250ce650fSreyk 			if (!vflag)
27350ce650fSreyk 				break;
27450ce650fSreyk 			PRINTF(", rsn");
27550ce650fSreyk 			ieee80211_print_element(data, len);
27650ce650fSreyk 			break;
27750ce650fSreyk 		case IEEE80211_ELEMID_XRATES:
27850ce650fSreyk 			if (!vflag)
27950ce650fSreyk 				break;
28050ce650fSreyk 			PRINTF(", xrates");
28150ce650fSreyk 			for (i = len; i > 0; i--, data++)
28250ce650fSreyk 				PRINTF(" %uM",
28350ce650fSreyk 				    (data[0] & IEEE80211_RATE_VAL) / 2);
28450ce650fSreyk 			break;
2858138faddSstsp 		case IEEE80211_ELEMID_TPC_REQUEST:
28650ce650fSreyk 			if (!vflag)
28750ce650fSreyk 				break;
2888138faddSstsp 			PRINTF(", tpcrequest");
28950ce650fSreyk 			ieee80211_print_element(data, len);
29050ce650fSreyk 			break;
2918138faddSstsp 		case IEEE80211_ELEMID_TPC_REPORT:
29250ce650fSreyk 			if (!vflag)
29350ce650fSreyk 				break;
2948138faddSstsp 			PRINTF(", tpcreport");
29550ce650fSreyk 			ieee80211_print_element(data, len);
29650ce650fSreyk 			break;
29750ce650fSreyk 		case IEEE80211_ELEMID_VENDOR:
29850ce650fSreyk 			if (!vflag)
29950ce650fSreyk 				break;
30050ce650fSreyk 			PRINTF(", vendor");
30150ce650fSreyk 			ieee80211_print_element(data, len);
30250ce650fSreyk 			break;
30350ce650fSreyk 		default:
30450ce650fSreyk 			if (!vflag)
30550ce650fSreyk 				break;
30650ce650fSreyk 			PRINTF(", %u:%u", (u_int) *frm, len);
30750ce650fSreyk 			ieee80211_print_element(data, len);
30850ce650fSreyk 			break;
30950ce650fSreyk 		}
31050ce650fSreyk 		frm += len + 2;
31150ce650fSreyk 
31250ce650fSreyk 		if (frm >= snapend)
31350ce650fSreyk 			break;
31450ce650fSreyk 	}
31550ce650fSreyk 
31650ce650fSreyk #undef ELEM_CHECK
31750ce650fSreyk 
31850ce650fSreyk 	return (0);
31950ce650fSreyk 
32050ce650fSreyk  trunc:
32150ce650fSreyk 	/* Truncated elements in frame */
32250ce650fSreyk 	return (1);
32350ce650fSreyk }
32450ce650fSreyk 
32550ce650fSreyk int
ieee80211_frame(struct ieee80211_frame * wh)32669952658Sreyk ieee80211_frame(struct ieee80211_frame *wh)
32750ce650fSreyk {
32850ce650fSreyk 	u_int8_t subtype, type, *frm;
32950ce650fSreyk 
33050ce650fSreyk 	TCARR(wh->i_fc);
33150ce650fSreyk 
33250ce650fSreyk 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
33350ce650fSreyk 	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
33450ce650fSreyk 
33550ce650fSreyk 	frm = (u_int8_t *)&wh[1];
33650ce650fSreyk 
33750ce650fSreyk 	switch (type) {
33850ce650fSreyk 	case IEEE80211_FC0_TYPE_DATA:
33950ce650fSreyk 		PRINTF(": data");
34050ce650fSreyk 		break;
34150ce650fSreyk 	case IEEE80211_FC0_TYPE_MGT:
34250ce650fSreyk 		PRINTF(": %s", ieee80211_mgt_subtype_name[
34350ce650fSreyk 		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
34450ce650fSreyk 		switch (subtype) {
34550ce650fSreyk 		case IEEE80211_FC0_SUBTYPE_BEACON:
34650ce650fSreyk 		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
34769952658Sreyk 			if (ieee80211_elements(wh) != 0)
34850ce650fSreyk 				goto trunc;
34950ce650fSreyk 			break;
35050ce650fSreyk 		case IEEE80211_FC0_SUBTYPE_AUTH:
35150ce650fSreyk 			TCHECK2(*frm, 2);		/* Auth Algorithm */
35250ce650fSreyk 			switch (IEEE80211_AUTH_ALGORITHM(frm)) {
35350ce650fSreyk 			case IEEE80211_AUTH_ALG_OPEN:
35450ce650fSreyk 				TCHECK2(*frm, 4);	/* Auth Transaction */
35550ce650fSreyk 				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
35650ce650fSreyk 				case IEEE80211_AUTH_OPEN_REQUEST:
35750ce650fSreyk 					PRINTF(" request");
35850ce650fSreyk 					break;
35950ce650fSreyk 				case IEEE80211_AUTH_OPEN_RESPONSE:
36050ce650fSreyk 					PRINTF(" response");
36150ce650fSreyk 					break;
36250ce650fSreyk 				}
36350ce650fSreyk 				break;
36450ce650fSreyk 			case IEEE80211_AUTH_ALG_SHARED:
36550ce650fSreyk 				TCHECK2(*frm, 4);	/* Auth Transaction */
36650ce650fSreyk 				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
36750ce650fSreyk 				case IEEE80211_AUTH_SHARED_REQUEST:
36850ce650fSreyk 					PRINTF(" request");
36950ce650fSreyk 					break;
37050ce650fSreyk 				case IEEE80211_AUTH_SHARED_CHALLENGE:
37150ce650fSreyk 					PRINTF(" challenge");
37250ce650fSreyk 					break;
37350ce650fSreyk 				case IEEE80211_AUTH_SHARED_RESPONSE:
37450ce650fSreyk 					PRINTF(" response");
37550ce650fSreyk 					break;
37650ce650fSreyk 				case IEEE80211_AUTH_SHARED_PASS:
37750ce650fSreyk 					PRINTF(" pass");
37850ce650fSreyk 					break;
37950ce650fSreyk 				}
38050ce650fSreyk 				break;
38150ce650fSreyk 			case IEEE80211_AUTH_ALG_LEAP:
38250ce650fSreyk 				PRINTF(" (leap)");
38350ce650fSreyk 				break;
38450ce650fSreyk 			}
38550ce650fSreyk 			break;
38650ce650fSreyk 		}
38750ce650fSreyk 		break;
38850ce650fSreyk 	default:
38950ce650fSreyk 		PRINTF(": type#%d", type);
39050ce650fSreyk 		break;
39150ce650fSreyk 	}
39250ce650fSreyk 
39350ce650fSreyk 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
39450ce650fSreyk 		PRINTF(", WEP");
39550ce650fSreyk 
39650ce650fSreyk 	return (0);
39750ce650fSreyk 
39850ce650fSreyk  trunc:
39950ce650fSreyk 	/* Truncated 802.11 frame */
40050ce650fSreyk 	return (1);
40150ce650fSreyk }
40250ce650fSreyk 
40350ce650fSreyk u_int
ieee80211_any2ieee(u_int freq,u_int flags)40450ce650fSreyk ieee80211_any2ieee(u_int freq, u_int flags)
40550ce650fSreyk {
40650ce650fSreyk 	if (flags & IEEE80211_CHAN_2GHZ) {
40750ce650fSreyk 		if (freq == 2484)
40850ce650fSreyk 			return 14;
40950ce650fSreyk 		if (freq < 2484)
41050ce650fSreyk 			return (freq - 2407) / 5;
41150ce650fSreyk 		else
41250ce650fSreyk 			return 15 + ((freq - 2512) / 20);
41350ce650fSreyk 	} else if (flags & IEEE80211_CHAN_5GHZ) {
41450ce650fSreyk 		return (freq - 5000) / 5;
41550ce650fSreyk 	} else {
41650ce650fSreyk 		/* Assume channel is already an IEEE number */
41750ce650fSreyk 		return (freq);
41850ce650fSreyk 	}
41950ce650fSreyk }
42050ce650fSreyk 
42150ce650fSreyk int
ieee80211_print(struct ieee80211_frame * wh)42269952658Sreyk ieee80211_print(struct ieee80211_frame *wh)
42350ce650fSreyk {
42450ce650fSreyk 	if (eflag)
42550ce650fSreyk 		if (ieee80211_hdr(wh))
42650ce650fSreyk 			return (1);
42750ce650fSreyk 
42869952658Sreyk 	return (ieee80211_frame(wh));
42950ce650fSreyk }
43050ce650fSreyk 
43150ce650fSreyk void
ieee802_11_if_print(u_int8_t * buf,u_int len)43250ce650fSreyk ieee802_11_if_print(u_int8_t *buf, u_int len)
43350ce650fSreyk {
43450ce650fSreyk 	struct ieee80211_frame *wh = (struct ieee80211_frame*)buf;
43550ce650fSreyk 
43650ce650fSreyk 	snapend = buf + len;
43750ce650fSreyk 
43869952658Sreyk 	if (ieee80211_print(wh) != 0)
43950ce650fSreyk 		PRINTF("[|802.11]");
44050ce650fSreyk 
441f83005a6Sreyk 	PRINTF(NULL);
44250ce650fSreyk }
44350ce650fSreyk 
44450ce650fSreyk void
ieee802_11_radio_if_print(u_int8_t * buf,u_int len)44550ce650fSreyk ieee802_11_radio_if_print(u_int8_t *buf, u_int len)
44650ce650fSreyk {
44750ce650fSreyk 	struct ieee80211_radiotap_header *rh =
44850ce650fSreyk 	    (struct ieee80211_radiotap_header*)buf;
44950ce650fSreyk 	struct ieee80211_frame *wh;
45050ce650fSreyk 	u_int8_t *t;
45150ce650fSreyk 	u_int32_t present;
45250ce650fSreyk 	u_int rh_len;
45350ce650fSreyk 
45450ce650fSreyk 	snapend = buf + len;
45550ce650fSreyk 
45650ce650fSreyk 	TCHECK(*rh);
45750ce650fSreyk 
45850ce650fSreyk 	rh_len = letoh16(rh->it_len);
45950ce650fSreyk 	if (rh->it_version != 0) {
460f83005a6Sreyk 		PRINTF("[?radiotap + 802.11 v:%u]", rh->it_version);
46150ce650fSreyk 		goto out;
46250ce650fSreyk 	}
46350ce650fSreyk 
46450ce650fSreyk 	wh = (struct ieee80211_frame *)(buf + rh_len);
46569952658Sreyk 	if (len <= rh_len || ieee80211_print(wh))
46650ce650fSreyk 		PRINTF("[|802.11]");
46750ce650fSreyk 
46850ce650fSreyk 	t = (u_int8_t*)buf + sizeof(struct ieee80211_radiotap_header);
46950ce650fSreyk 
47050ce650fSreyk 	if ((present = letoh32(rh->it_present)) == 0)
47150ce650fSreyk 		goto out;
47250ce650fSreyk 
47350ce650fSreyk 	PRINTF(", <radiotap v%u", rh->it_version);
47450ce650fSreyk 
47550ce650fSreyk #define RADIOTAP(_x)	\
47650ce650fSreyk 	(present & (1 << IEEE80211_RADIOTAP_##_x))
47750ce650fSreyk 
47850ce650fSreyk 	if (RADIOTAP(TSFT)) {
47950ce650fSreyk 		u_int64_t tsf;
48050ce650fSreyk 		u_int32_t tsf_v[2];
48150ce650fSreyk 
48250ce650fSreyk 		TCHECK2(*t, 8);
48350ce650fSreyk 
48450ce650fSreyk 		tsf = letoh64(*(u_int64_t *)t);
48550ce650fSreyk 		tsf_v[0] = (u_int32_t)(tsf >> 32);
48650ce650fSreyk 		tsf_v[1] = (u_int32_t)(tsf & 0x00000000ffffffff);
48750ce650fSreyk 		if (vflag > 1)
48850ce650fSreyk 			PRINTF(", tsf 0x%08x%08x", tsf_v[0], tsf_v[1]);
48950ce650fSreyk 		t += 8;
49050ce650fSreyk 	}
49150ce650fSreyk 
49250ce650fSreyk 	if (RADIOTAP(FLAGS)) {
49350ce650fSreyk 		u_int8_t flags = *(u_int8_t*)t;
49450ce650fSreyk 		TCHECK2(*t, 1);
49550ce650fSreyk 
49650ce650fSreyk 		if (flags & IEEE80211_RADIOTAP_F_CFP)
49750ce650fSreyk 			PRINTF(", CFP");
49850ce650fSreyk 		if (flags & IEEE80211_RADIOTAP_F_SHORTPRE)
49950ce650fSreyk 			PRINTF(", SHORTPRE");
50050ce650fSreyk 		if (flags & IEEE80211_RADIOTAP_F_WEP)
50150ce650fSreyk 			PRINTF(", WEP");
50250ce650fSreyk 		if (flags & IEEE80211_RADIOTAP_F_FRAG)
50350ce650fSreyk 			PRINTF(", FRAG");
50450ce650fSreyk 		t += 1;
50550ce650fSreyk 	}
50650ce650fSreyk 
50750ce650fSreyk 	if (RADIOTAP(RATE)) {
50850ce650fSreyk 		TCHECK2(*t, 1);
50950ce650fSreyk 		if (vflag)
51050ce650fSreyk 			PRINTF(", %uMbit/s", (*(u_int8_t*)t) / 2);
51150ce650fSreyk 		t += 1;
51250ce650fSreyk 	}
51350ce650fSreyk 
51450ce650fSreyk 	if (RADIOTAP(CHANNEL)) {
51550ce650fSreyk 		u_int16_t freq, flags;
51650ce650fSreyk 		TCHECK2(*t, 2);
51750ce650fSreyk 
51850ce650fSreyk 		freq = letoh16(*(u_int16_t*)t);
51950ce650fSreyk 		t += 2;
52050ce650fSreyk 		TCHECK2(*t, 2);
52150ce650fSreyk 		flags = letoh16(*(u_int16_t*)t);
52250ce650fSreyk 		t += 2;
52350ce650fSreyk 
52450ce650fSreyk 		PRINTF(", chan %u", ieee80211_any2ieee(freq, flags));
52550ce650fSreyk 
52650ce650fSreyk 		if (flags & IEEE80211_CHAN_DYN &&
52750ce650fSreyk 		    flags & IEEE80211_CHAN_2GHZ)
52850ce650fSreyk 			PRINTF(", 11g");
52950ce650fSreyk 		else if (flags & IEEE80211_CHAN_CCK &&
53050ce650fSreyk 		    flags & IEEE80211_CHAN_2GHZ)
53150ce650fSreyk 			PRINTF(", 11b");
53250ce650fSreyk 		else if (flags & IEEE80211_CHAN_OFDM &&
53350ce650fSreyk 		    flags & IEEE80211_CHAN_2GHZ)
53450ce650fSreyk 			PRINTF(", 11G");
53550ce650fSreyk 		else if (flags & IEEE80211_CHAN_OFDM &&
53650ce650fSreyk 		    flags & IEEE80211_CHAN_5GHZ)
53750ce650fSreyk 			PRINTF(", 11a");
53850ce650fSreyk 
53950ce650fSreyk 		if (flags & IEEE80211_CHAN_XR)
54050ce650fSreyk 			PRINTF(", XR");
54150ce650fSreyk 	}
54250ce650fSreyk 
54350ce650fSreyk 	if (RADIOTAP(FHSS)) {
54450ce650fSreyk 		TCHECK2(*t, 2);
54550ce650fSreyk 		PRINTF(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1);
54650ce650fSreyk 		t += 2;
54750ce650fSreyk 	}
54850ce650fSreyk 
54950ce650fSreyk 	if (RADIOTAP(DBM_ANTSIGNAL)) {
55050ce650fSreyk 		TCHECK(*t);
55150ce650fSreyk 		PRINTF(", sig %ddBm", *(int8_t*)t);
55250ce650fSreyk 		t += 1;
55350ce650fSreyk 	}
55450ce650fSreyk 
55550ce650fSreyk 	if (RADIOTAP(DBM_ANTNOISE)) {
55650ce650fSreyk 		TCHECK(*t);
55750ce650fSreyk 		PRINTF(", noise %ddBm", *(int8_t*)t);
55850ce650fSreyk 		t += 1;
55950ce650fSreyk 	}
56050ce650fSreyk 
56150ce650fSreyk 	if (RADIOTAP(LOCK_QUALITY)) {
56250ce650fSreyk 		TCHECK2(*t, 2);
56350ce650fSreyk 		if (vflag)
56450ce650fSreyk 			PRINTF(", quality %u", letoh16(*(u_int16_t*)t));
56550ce650fSreyk 		t += 2;
56650ce650fSreyk 	}
56750ce650fSreyk 
56850ce650fSreyk 	if (RADIOTAP(TX_ATTENUATION)) {
56950ce650fSreyk 		TCHECK2(*t, 2);
57050ce650fSreyk 		if (vflag)
57150ce650fSreyk 			PRINTF(", txatt %u",
57250ce650fSreyk 			    letoh16(*(u_int16_t*)t));
57350ce650fSreyk 		t += 2;
57450ce650fSreyk 	}
57550ce650fSreyk 
57650ce650fSreyk 	if (RADIOTAP(DB_TX_ATTENUATION)) {
57750ce650fSreyk 		TCHECK2(*t, 2);
57850ce650fSreyk 		if (vflag)
57950ce650fSreyk 			PRINTF(", txatt %udB",
58050ce650fSreyk 			    letoh16(*(u_int16_t*)t));
58150ce650fSreyk 		t += 2;
58250ce650fSreyk 	}
58350ce650fSreyk 
58450ce650fSreyk 	if (RADIOTAP(DBM_TX_POWER)) {
58550ce650fSreyk 		TCHECK(*t);
58650ce650fSreyk 		PRINTF(", txpower %ddBm", *(int8_t*)t);
58750ce650fSreyk 		t += 1;
58850ce650fSreyk 	}
58950ce650fSreyk 
59050ce650fSreyk 	if (RADIOTAP(ANTENNA)) {
59150ce650fSreyk 		TCHECK(*t);
59250ce650fSreyk 		if (vflag)
59350ce650fSreyk 			PRINTF(", antenna %u", *(u_int8_t*)t);
59450ce650fSreyk 		t += 1;
59550ce650fSreyk 	}
59650ce650fSreyk 
59750ce650fSreyk 	if (RADIOTAP(DB_ANTSIGNAL)) {
59850ce650fSreyk 		TCHECK(*t);
59950ce650fSreyk 		PRINTF(", signal %udB", *(u_int8_t*)t);
60050ce650fSreyk 		t += 1;
60150ce650fSreyk 	}
60250ce650fSreyk 
60350ce650fSreyk 	if (RADIOTAP(DB_ANTNOISE)) {
60450ce650fSreyk 		TCHECK(*t);
60550ce650fSreyk 		PRINTF(", noise %udB", *(u_int8_t*)t);
60650ce650fSreyk 		t += 1;
60750ce650fSreyk 	}
60850ce650fSreyk 
60950ce650fSreyk 	if (RADIOTAP(FCS)) {
61050ce650fSreyk 		TCHECK2(*t, 4);
61150ce650fSreyk 		if (vflag)
61250ce650fSreyk 			PRINTF(", fcs %08x", letoh32(*(u_int32_t*)t));
61350ce650fSreyk 		t += 4;
61450ce650fSreyk 	}
61550ce650fSreyk 
6166fc94ee3Sreyk 	if (RADIOTAP(RSSI)) {
6176fc94ee3Sreyk 		u_int8_t rssi, max_rssi;
6186fc94ee3Sreyk 		TCHECK(*t);
6196fc94ee3Sreyk 		rssi = *(u_int8_t*)t;
6206fc94ee3Sreyk 		t += 1;
6216fc94ee3Sreyk 		TCHECK(*t);
6226fc94ee3Sreyk 		max_rssi = *(u_int8_t*)t;
6236fc94ee3Sreyk 		t += 1;
6246fc94ee3Sreyk 
6259aa8b2e1Sreyk 		PRINTF(", rssi %u/%u", rssi, max_rssi);
6266fc94ee3Sreyk 	}
6276fc94ee3Sreyk 
62850ce650fSreyk #undef RADIOTAP
62950ce650fSreyk 
63050ce650fSreyk 	PRINTF(">");
63150ce650fSreyk 	goto out;
63250ce650fSreyk 
63350ce650fSreyk  trunc:
63450ce650fSreyk 	/* Truncated frame */
63550ce650fSreyk 	PRINTF("[|radiotap + 802.11]");
63650ce650fSreyk 
63750ce650fSreyk  out:
638f83005a6Sreyk 	PRINTF(NULL);
63950ce650fSreyk }
64050ce650fSreyk 
64150ce650fSreyk void
hostapd_print_ieee80211(u_int dlt,u_int verbose,u_int8_t * buf,u_int len)64250ce650fSreyk hostapd_print_ieee80211(u_int dlt, u_int verbose, u_int8_t *buf, u_int len)
64350ce650fSreyk {
64450ce650fSreyk 	if (verbose)
64550ce650fSreyk 		vflag = 1;
64650ce650fSreyk 	else
64750ce650fSreyk 		vflag = 0;
64850ce650fSreyk 
64950ce650fSreyk 	if (dlt == DLT_IEEE802_11)
65050ce650fSreyk 		ieee802_11_if_print(buf, len);
65150ce650fSreyk 	else
65250ce650fSreyk 		ieee802_11_radio_if_print(buf, len);
65350ce650fSreyk }
654