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