xref: /openbsd-src/usr.sbin/hostapd/print-802_11.c (revision cb21588b789e158a41a4783b1dcf238685d192fc)
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 
44 const 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 
63 const u_int8_t *snapend;
64 int vflag = 1, eflag = 1;
65 
66 int	 ieee80211_hdr(struct ieee80211_frame *);
67 void	 ieee80211_print_element(u_int8_t *, u_int);
68 void	 ieee80211_print_essid(u_int8_t *, u_int);
69 int	 ieee80211_elements(struct ieee80211_frame *);
70 int	 ieee80211_frame(struct ieee80211_frame *);
71 int	 ieee80211_print(struct ieee80211_frame *);
72 u_int	 ieee80211_any2ieee(u_int, u_int);
73 void	 ieee802_11_if_print(u_int8_t *, u_int);
74 void	 ieee802_11_radio_if_print(u_int8_t *, u_int);
75 
76 #define TCARR(a)	TCHECK2(*a, sizeof(a))
77 
78 int
ieee80211_hdr(struct ieee80211_frame * wh)79 ieee80211_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 */
133 void
ieee80211_print_element(u_int8_t * data,u_int len)134 ieee80211_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 */
145 void
ieee80211_print_essid(u_int8_t * essid,u_int len)146 ieee80211_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 
168 int
ieee80211_elements(struct ieee80211_frame * wh)169 ieee80211_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 
325 int
ieee80211_frame(struct ieee80211_frame * wh)326 ieee80211_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 
403 u_int
ieee80211_any2ieee(u_int freq,u_int flags)404 ieee80211_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 
421 int
ieee80211_print(struct ieee80211_frame * wh)422 ieee80211_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 
431 void
ieee802_11_if_print(u_int8_t * buf,u_int len)432 ieee802_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 
444 void
ieee802_11_radio_if_print(u_int8_t * buf,u_int len)445 ieee802_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 
641 void
hostapd_print_ieee80211(u_int dlt,u_int verbose,u_int8_t * buf,u_int len)642 hostapd_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