1/*	$OpenBSD: print-802_11.c,v 1.11 2019/05/10 01:29:31 guenther 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/* usr.sbin/tcpdump/print-802_11.c,v 1.3 2005/03/09 11:43:17 deraadt Exp */
20
21#include <sys/time.h>
22#include <sys/socket.h>
23
24#include <net/if.h>
25#include <net/if_media.h>
26#include <net/if_arp.h>
27#include <net/if_llc.h>
28#include <net/bpf.h>
29
30#include <netinet/in.h>
31#include <netinet/if_ether.h>
32#include <arpa/inet.h>
33
34#include <net80211/ieee80211.h>
35#include <net80211/ieee80211_radiotap.h>
36
37#include <pcap.h>
38#include <stdio.h>
39#include <string.h>
40#include <limits.h>
41
42#include "hostapd.h"
43
44const char *ieee80211_mgt_subtype_name[] = {
45	"association request",
46	"association response",
47	"reassociation request",
48	"reassociation response",
49	"probe request",
50	"probe response",
51	"reserved#6",
52	"reserved#7",
53	"beacon",
54	"atim",
55	"disassociation",
56	"authentication",
57	"deauthentication",
58	"reserved#13",
59	"reserved#14",
60	"reserved#15"
61};
62
63const u_int8_t *snapend;
64int vflag = 1, eflag = 1;
65
66int	 ieee80211_hdr(struct ieee80211_frame *);
67void	 ieee80211_print_element(u_int8_t *, u_int);
68void	 ieee80211_print_essid(u_int8_t *, u_int);
69int	 ieee80211_elements(struct ieee80211_frame *);
70int	 ieee80211_frame(struct ieee80211_frame *);
71int	 ieee80211_print(struct ieee80211_frame *);
72u_int	 ieee80211_any2ieee(u_int, u_int);
73void	 ieee802_11_if_print(u_int8_t *, u_int);
74void	 ieee802_11_radio_if_print(u_int8_t *, u_int);
75
76#define TCARR(a)	TCHECK2(*a, sizeof(a))
77
78int
79ieee80211_hdr(struct ieee80211_frame *wh)
80{
81	struct ieee80211_frame_addr4 *w4;
82
83	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
84	case IEEE80211_FC1_DIR_NODS:
85		TCARR(wh->i_addr2);
86		PRINTF("%s", etheraddr_string(wh->i_addr2));
87		TCARR(wh->i_addr1);
88		PRINTF(" > %s", etheraddr_string(wh->i_addr1));
89		TCARR(wh->i_addr3);
90		PRINTF(", bssid %s", etheraddr_string(wh->i_addr3));
91		break;
92	case IEEE80211_FC1_DIR_TODS:
93		TCARR(wh->i_addr2);
94		PRINTF("%s", etheraddr_string(wh->i_addr2));
95		TCARR(wh->i_addr3);
96		PRINTF(" > %s", etheraddr_string(wh->i_addr3));
97		TCARR(wh->i_addr1);
98		PRINTF(", bssid %s, > DS", etheraddr_string(wh->i_addr1));
99		break;
100	case IEEE80211_FC1_DIR_FROMDS:
101		TCARR(wh->i_addr3);
102		PRINTF("%s", etheraddr_string(wh->i_addr3));
103		TCARR(wh->i_addr1);
104		PRINTF(" > %s", etheraddr_string(wh->i_addr1));
105		TCARR(wh->i_addr2);
106		PRINTF(", bssid %s, DS >", etheraddr_string(wh->i_addr2));
107		break;
108	case IEEE80211_FC1_DIR_DSTODS:
109		w4 = (struct ieee80211_frame_addr4 *) wh;
110		TCARR(w4->i_addr4);
111		PRINTF("%s", etheraddr_string(w4->i_addr4));
112		TCARR(w4->i_addr3);
113		PRINTF(" > %s", etheraddr_string(w4->i_addr3));
114		TCARR(w4->i_addr2);
115		PRINTF(", bssid %s", etheraddr_string(w4->i_addr2));
116		TCARR(w4->i_addr1);
117		PRINTF(" > %s, DS > DS", etheraddr_string(w4->i_addr1));
118		break;
119	}
120	if (vflag) {
121		TCARR(wh->i_seq);
122		PRINTF(" (seq %u)", letoh16(*(u_int16_t *)&wh->i_seq[0]));
123	}
124
125	return (0);
126
127 trunc:
128	/* Truncated elements in frame */
129	return (1);
130}
131
132/* Caller checks len */
133void
134ieee80211_print_element(u_int8_t *data, u_int len)
135{
136	u_int8_t *p;
137	u_int i;
138
139	PRINTF(" 0x");
140	for (i = 0, p = data; i < len; i++, p++)
141		PRINTF("%02x", *p);
142}
143
144/* Caller checks len */
145void
146ieee80211_print_essid(u_int8_t *essid, u_int len)
147{
148	u_int8_t *p;
149	u_int i;
150
151	if (len > IEEE80211_NWID_LEN)
152		len = IEEE80211_NWID_LEN;
153
154	/* determine printable or not */
155	for (i = 0, p = essid; i < len; i++, p++) {
156		if (*p < ' ' || *p > 0x7e)
157			break;
158	}
159	if (i == len) {
160		PRINTF(" (");
161		for (i = 0, p = essid; i < len; i++, p++)
162			PRINTF("%c", *p);
163		PRINTF(")");
164	} else
165		ieee80211_print_element(essid, len);
166}
167
168int
169ieee80211_elements(struct ieee80211_frame *wh)
170{
171	u_int8_t *frm;
172	u_int8_t *tstamp, *bintval, *capinfo;
173	int i;
174
175	frm = (u_int8_t *)&wh[1];
176
177	tstamp = frm;
178	TCHECK2(*tstamp, 8);
179	frm += 8;
180
181	bintval = frm;
182	TCHECK2(*bintval, 2);
183	frm += 2;
184
185	if (vflag)
186		PRINTF(", interval %u", letoh16(*(u_int16_t *)bintval));
187
188	capinfo = frm;
189	TCHECK2(*capinfo, 2);
190	frm += 2;
191
192#if 0
193	if (vflag)
194		printb(", caps", letoh16(*(u_int16_t *)capinfo),
195		    IEEE80211_CAPINFO_BITS);
196#endif
197
198	while (TTEST2(*frm, 2)) {
199		u_int len = frm[1];
200		u_int8_t *data = frm + 2;
201
202		if (!TTEST2(*data, len))
203			break;
204
205#define ELEM_CHECK(l)	if (len != l) break
206
207		switch (*frm) {
208		case IEEE80211_ELEMID_SSID:
209			PRINTF(", ssid");
210			ieee80211_print_essid(data, len);
211			break;
212		case IEEE80211_ELEMID_RATES:
213			if (!vflag)
214				break;
215			PRINTF(", rates");
216			for (i = len; i > 0; i--, data++)
217				PRINTF(" %uM",
218				    (data[0] & IEEE80211_RATE_VAL) / 2);
219			break;
220		case IEEE80211_ELEMID_FHPARMS:
221			ELEM_CHECK(5);
222			PRINTF(", fh (dwell %u, chan %u, index %u)",
223			    (data[1] << 8) | data[0],
224			    (data[2] - 1) * 80 + data[3],	/* FH_CHAN */
225			    data[4]);
226			break;
227		case IEEE80211_ELEMID_DSPARMS:
228			ELEM_CHECK(1);
229			if (!vflag)
230				break;
231			PRINTF(", ds");
232			PRINTF(" (chan %u)", data[0]);
233			break;
234		case IEEE80211_ELEMID_CFPARMS:
235			if (!vflag)
236				break;
237			PRINTF(", cf");
238			ieee80211_print_element(data, len);
239			break;
240		case IEEE80211_ELEMID_TIM:
241			if (!vflag)
242				break;
243			PRINTF(", tim");
244			ieee80211_print_element(data, len);
245			break;
246		case IEEE80211_ELEMID_IBSSPARMS:
247			if (!vflag)
248				break;
249			PRINTF(", ibss");
250			ieee80211_print_element(data, len);
251			break;
252		case IEEE80211_ELEMID_COUNTRY:
253			if (!vflag)
254				break;
255			PRINTF(", country");
256			for (i = len; i > 0; i--, data++)
257				PRINTF(" %u", data[0]);
258			break;
259		case IEEE80211_ELEMID_CHALLENGE:
260			if (!vflag)
261				break;
262			PRINTF(", challenge");
263			ieee80211_print_element(data, len);
264			break;
265		case IEEE80211_ELEMID_ERP:
266			if (!vflag)
267				break;
268			PRINTF(", erp");
269			ieee80211_print_element(data, len);
270			break;
271		case IEEE80211_ELEMID_RSN:
272			if (!vflag)
273				break;
274			PRINTF(", rsn");
275			ieee80211_print_element(data, len);
276			break;
277		case IEEE80211_ELEMID_XRATES:
278			if (!vflag)
279				break;
280			PRINTF(", xrates");
281			for (i = len; i > 0; i--, data++)
282				PRINTF(" %uM",
283				    (data[0] & IEEE80211_RATE_VAL) / 2);
284			break;
285		case IEEE80211_ELEMID_TPC_REQUEST:
286			if (!vflag)
287				break;
288			PRINTF(", tpcrequest");
289			ieee80211_print_element(data, len);
290			break;
291		case IEEE80211_ELEMID_TPC_REPORT:
292			if (!vflag)
293				break;
294			PRINTF(", tpcreport");
295			ieee80211_print_element(data, len);
296			break;
297		case IEEE80211_ELEMID_VENDOR:
298			if (!vflag)
299				break;
300			PRINTF(", vendor");
301			ieee80211_print_element(data, len);
302			break;
303		default:
304			if (!vflag)
305				break;
306			PRINTF(", %u:%u", (u_int) *frm, len);
307			ieee80211_print_element(data, len);
308			break;
309		}
310		frm += len + 2;
311
312		if (frm >= snapend)
313			break;
314	}
315
316#undef ELEM_CHECK
317
318	return (0);
319
320 trunc:
321	/* Truncated elements in frame */
322	return (1);
323}
324
325int
326ieee80211_frame(struct ieee80211_frame *wh)
327{
328	u_int8_t subtype, type, *frm;
329
330	TCARR(wh->i_fc);
331
332	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
333	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
334
335	frm = (u_int8_t *)&wh[1];
336
337	switch (type) {
338	case IEEE80211_FC0_TYPE_DATA:
339		PRINTF(": data");
340		break;
341	case IEEE80211_FC0_TYPE_MGT:
342		PRINTF(": %s", ieee80211_mgt_subtype_name[
343		    subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
344		switch (subtype) {
345		case IEEE80211_FC0_SUBTYPE_BEACON:
346		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
347			if (ieee80211_elements(wh) != 0)
348				goto trunc;
349			break;
350		case IEEE80211_FC0_SUBTYPE_AUTH:
351			TCHECK2(*frm, 2);		/* Auth Algorithm */
352			switch (IEEE80211_AUTH_ALGORITHM(frm)) {
353			case IEEE80211_AUTH_ALG_OPEN:
354				TCHECK2(*frm, 4);	/* Auth Transaction */
355				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
356				case IEEE80211_AUTH_OPEN_REQUEST:
357					PRINTF(" request");
358					break;
359				case IEEE80211_AUTH_OPEN_RESPONSE:
360					PRINTF(" response");
361					break;
362				}
363				break;
364			case IEEE80211_AUTH_ALG_SHARED:
365				TCHECK2(*frm, 4);	/* Auth Transaction */
366				switch (IEEE80211_AUTH_TRANSACTION(frm)) {
367				case IEEE80211_AUTH_SHARED_REQUEST:
368					PRINTF(" request");
369					break;
370				case IEEE80211_AUTH_SHARED_CHALLENGE:
371					PRINTF(" challenge");
372					break;
373				case IEEE80211_AUTH_SHARED_RESPONSE:
374					PRINTF(" response");
375					break;
376				case IEEE80211_AUTH_SHARED_PASS:
377					PRINTF(" pass");
378					break;
379				}
380				break;
381			case IEEE80211_AUTH_ALG_LEAP:
382				PRINTF(" (leap)");
383				break;
384			}
385			break;
386		}
387		break;
388	default:
389		PRINTF(": type#%d", type);
390		break;
391	}
392
393	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
394		PRINTF(", WEP");
395
396	return (0);
397
398 trunc:
399	/* Truncated 802.11 frame */
400	return (1);
401}
402
403u_int
404ieee80211_any2ieee(u_int freq, u_int flags)
405{
406	if (flags & IEEE80211_CHAN_2GHZ) {
407		if (freq == 2484)
408			return 14;
409		if (freq < 2484)
410			return (freq - 2407) / 5;
411		else
412			return 15 + ((freq - 2512) / 20);
413	} else if (flags & IEEE80211_CHAN_5GHZ) {
414		return (freq - 5000) / 5;
415	} else {
416		/* Assume channel is already an IEEE number */
417		return (freq);
418	}
419}
420
421int
422ieee80211_print(struct ieee80211_frame *wh)
423{
424	if (eflag)
425		if (ieee80211_hdr(wh))
426			return (1);
427
428	return (ieee80211_frame(wh));
429}
430
431void
432ieee802_11_if_print(u_int8_t *buf, u_int len)
433{
434	struct ieee80211_frame *wh = (struct ieee80211_frame*)buf;
435
436	snapend = buf + len;
437
438	if (ieee80211_print(wh) != 0)
439		PRINTF("[|802.11]");
440
441	PRINTF(NULL);
442}
443
444void
445ieee802_11_radio_if_print(u_int8_t *buf, u_int len)
446{
447	struct ieee80211_radiotap_header *rh =
448	    (struct ieee80211_radiotap_header*)buf;
449	struct ieee80211_frame *wh;
450	u_int8_t *t;
451	u_int32_t present;
452	u_int rh_len;
453
454	snapend = buf + len;
455
456	TCHECK(*rh);
457
458	rh_len = letoh16(rh->it_len);
459	if (rh->it_version != 0) {
460		PRINTF("[?radiotap + 802.11 v:%u]", rh->it_version);
461		goto out;
462	}
463
464	wh = (struct ieee80211_frame *)(buf + rh_len);
465	if (len <= rh_len || ieee80211_print(wh))
466		PRINTF("[|802.11]");
467
468	t = (u_int8_t*)buf + sizeof(struct ieee80211_radiotap_header);
469
470	if ((present = letoh32(rh->it_present)) == 0)
471		goto out;
472
473	PRINTF(", <radiotap v%u", rh->it_version);
474
475#define RADIOTAP(_x)	\
476	(present & (1 << IEEE80211_RADIOTAP_##_x))
477
478	if (RADIOTAP(TSFT)) {
479		u_int64_t tsf;
480		u_int32_t tsf_v[2];
481
482		TCHECK2(*t, 8);
483
484		tsf = letoh64(*(u_int64_t *)t);
485		tsf_v[0] = (u_int32_t)(tsf >> 32);
486		tsf_v[1] = (u_int32_t)(tsf & 0x00000000ffffffff);
487		if (vflag > 1)
488			PRINTF(", tsf 0x%08x%08x", tsf_v[0], tsf_v[1]);
489		t += 8;
490	}
491
492	if (RADIOTAP(FLAGS)) {
493		u_int8_t flags = *(u_int8_t*)t;
494		TCHECK2(*t, 1);
495
496		if (flags & IEEE80211_RADIOTAP_F_CFP)
497			PRINTF(", CFP");
498		if (flags & IEEE80211_RADIOTAP_F_SHORTPRE)
499			PRINTF(", SHORTPRE");
500		if (flags & IEEE80211_RADIOTAP_F_WEP)
501			PRINTF(", WEP");
502		if (flags & IEEE80211_RADIOTAP_F_FRAG)
503			PRINTF(", FRAG");
504		t += 1;
505	}
506
507	if (RADIOTAP(RATE)) {
508		TCHECK2(*t, 1);
509		if (vflag)
510			PRINTF(", %uMbit/s", (*(u_int8_t*)t) / 2);
511		t += 1;
512	}
513
514	if (RADIOTAP(CHANNEL)) {
515		u_int16_t freq, flags;
516		TCHECK2(*t, 2);
517
518		freq = letoh16(*(u_int16_t*)t);
519		t += 2;
520		TCHECK2(*t, 2);
521		flags = letoh16(*(u_int16_t*)t);
522		t += 2;
523
524		PRINTF(", chan %u", ieee80211_any2ieee(freq, flags));
525
526		if (flags & IEEE80211_CHAN_DYN &&
527		    flags & IEEE80211_CHAN_2GHZ)
528			PRINTF(", 11g");
529		else if (flags & IEEE80211_CHAN_CCK &&
530		    flags & IEEE80211_CHAN_2GHZ)
531			PRINTF(", 11b");
532		else if (flags & IEEE80211_CHAN_OFDM &&
533		    flags & IEEE80211_CHAN_2GHZ)
534			PRINTF(", 11G");
535		else if (flags & IEEE80211_CHAN_OFDM &&
536		    flags & IEEE80211_CHAN_5GHZ)
537			PRINTF(", 11a");
538
539		if (flags & IEEE80211_CHAN_XR)
540			PRINTF(", XR");
541	}
542
543	if (RADIOTAP(FHSS)) {
544		TCHECK2(*t, 2);
545		PRINTF(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1);
546		t += 2;
547	}
548
549	if (RADIOTAP(DBM_ANTSIGNAL)) {
550		TCHECK(*t);
551		PRINTF(", sig %ddBm", *(int8_t*)t);
552		t += 1;
553	}
554
555	if (RADIOTAP(DBM_ANTNOISE)) {
556		TCHECK(*t);
557		PRINTF(", noise %ddBm", *(int8_t*)t);
558		t += 1;
559	}
560
561	if (RADIOTAP(LOCK_QUALITY)) {
562		TCHECK2(*t, 2);
563		if (vflag)
564			PRINTF(", quality %u", letoh16(*(u_int16_t*)t));
565		t += 2;
566	}
567
568	if (RADIOTAP(TX_ATTENUATION)) {
569		TCHECK2(*t, 2);
570		if (vflag)
571			PRINTF(", txatt %u",
572			    letoh16(*(u_int16_t*)t));
573		t += 2;
574	}
575
576	if (RADIOTAP(DB_TX_ATTENUATION)) {
577		TCHECK2(*t, 2);
578		if (vflag)
579			PRINTF(", txatt %udB",
580			    letoh16(*(u_int16_t*)t));
581		t += 2;
582	}
583
584	if (RADIOTAP(DBM_TX_POWER)) {
585		TCHECK(*t);
586		PRINTF(", txpower %ddBm", *(int8_t*)t);
587		t += 1;
588	}
589
590	if (RADIOTAP(ANTENNA)) {
591		TCHECK(*t);
592		if (vflag)
593			PRINTF(", antenna %u", *(u_int8_t*)t);
594		t += 1;
595	}
596
597	if (RADIOTAP(DB_ANTSIGNAL)) {
598		TCHECK(*t);
599		PRINTF(", signal %udB", *(u_int8_t*)t);
600		t += 1;
601	}
602
603	if (RADIOTAP(DB_ANTNOISE)) {
604		TCHECK(*t);
605		PRINTF(", noise %udB", *(u_int8_t*)t);
606		t += 1;
607	}
608
609	if (RADIOTAP(FCS)) {
610		TCHECK2(*t, 4);
611		if (vflag)
612			PRINTF(", fcs %08x", letoh32(*(u_int32_t*)t));
613		t += 4;
614	}
615
616	if (RADIOTAP(RSSI)) {
617		u_int8_t rssi, max_rssi;
618		TCHECK(*t);
619		rssi = *(u_int8_t*)t;
620		t += 1;
621		TCHECK(*t);
622		max_rssi = *(u_int8_t*)t;
623		t += 1;
624
625		PRINTF(", rssi %u/%u", rssi, max_rssi);
626	}
627
628#undef RADIOTAP
629
630	PRINTF(">");
631	goto out;
632
633 trunc:
634	/* Truncated frame */
635	PRINTF("[|radiotap + 802.11]");
636
637 out:
638	PRINTF(NULL);
639}
640
641void
642hostapd_print_ieee80211(u_int dlt, u_int verbose, u_int8_t *buf, u_int len)
643{
644	if (verbose)
645		vflag = 1;
646	else
647		vflag = 0;
648
649	if (dlt == DLT_IEEE802_11)
650		ieee802_11_if_print(buf, len);
651	else
652		ieee802_11_radio_if_print(buf, len);
653}
654