GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/hostapd/print-802_11.c Lines: 0 320 0.0 %
Date: 2017-11-13 Branches: 0 374 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-802_11.c,v 1.9 2016/01/12 09:28:10 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
/* 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
#include <sys/file.h>
24
#include <sys/ioctl.h>
25
26
#include <net/if.h>
27
#include <net/if_dl.h>
28
#include <net/if_media.h>
29
#include <net/if_arp.h>
30
#include <net/if_llc.h>
31
#include <net/bpf.h>
32
33
#include <netinet/in.h>
34
#include <netinet/if_ether.h>
35
#include <arpa/inet.h>
36
37
#include <net80211/ieee80211.h>
38
#include <net80211/ieee80211_radiotap.h>
39
40
#include <pcap.h>
41
#include <stdio.h>
42
#include <string.h>
43
#include <limits.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_REQUEST:
289
			if (!vflag)
290
				break;
291
			PRINTF(", tpcrequest");
292
			ieee80211_print_element(data, len);
293
			break;
294
		case IEEE80211_ELEMID_TPC_REPORT:
295
			if (!vflag)
296
				break;
297
			PRINTF(", tpcreport");
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_XR)
543
			PRINTF(", XR");
544
	}
545
546
	if (RADIOTAP(FHSS)) {
547
		TCHECK2(*t, 2);
548
		PRINTF(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1);
549
		t += 2;
550
	}
551
552
	if (RADIOTAP(DBM_ANTSIGNAL)) {
553
		TCHECK(*t);
554
		PRINTF(", sig %ddBm", *(int8_t*)t);
555
		t += 1;
556
	}
557
558
	if (RADIOTAP(DBM_ANTNOISE)) {
559
		TCHECK(*t);
560
		PRINTF(", noise %ddBm", *(int8_t*)t);
561
		t += 1;
562
	}
563
564
	if (RADIOTAP(LOCK_QUALITY)) {
565
		TCHECK2(*t, 2);
566
		if (vflag)
567
			PRINTF(", quality %u", letoh16(*(u_int16_t*)t));
568
		t += 2;
569
	}
570
571
	if (RADIOTAP(TX_ATTENUATION)) {
572
		TCHECK2(*t, 2);
573
		if (vflag)
574
			PRINTF(", txatt %u",
575
			    letoh16(*(u_int16_t*)t));
576
		t += 2;
577
	}
578
579
	if (RADIOTAP(DB_TX_ATTENUATION)) {
580
		TCHECK2(*t, 2);
581
		if (vflag)
582
			PRINTF(", txatt %udB",
583
			    letoh16(*(u_int16_t*)t));
584
		t += 2;
585
	}
586
587
	if (RADIOTAP(DBM_TX_POWER)) {
588
		TCHECK(*t);
589
		PRINTF(", txpower %ddBm", *(int8_t*)t);
590
		t += 1;
591
	}
592
593
	if (RADIOTAP(ANTENNA)) {
594
		TCHECK(*t);
595
		if (vflag)
596
			PRINTF(", antenna %u", *(u_int8_t*)t);
597
		t += 1;
598
	}
599
600
	if (RADIOTAP(DB_ANTSIGNAL)) {
601
		TCHECK(*t);
602
		PRINTF(", signal %udB", *(u_int8_t*)t);
603
		t += 1;
604
	}
605
606
	if (RADIOTAP(DB_ANTNOISE)) {
607
		TCHECK(*t);
608
		PRINTF(", noise %udB", *(u_int8_t*)t);
609
		t += 1;
610
	}
611
612
	if (RADIOTAP(FCS)) {
613
		TCHECK2(*t, 4);
614
		if (vflag)
615
			PRINTF(", fcs %08x", letoh32(*(u_int32_t*)t));
616
		t += 4;
617
	}
618
619
	if (RADIOTAP(RSSI)) {
620
		u_int8_t rssi, max_rssi;
621
		TCHECK(*t);
622
		rssi = *(u_int8_t*)t;
623
		t += 1;
624
		TCHECK(*t);
625
		max_rssi = *(u_int8_t*)t;
626
		t += 1;
627
628
		PRINTF(", rssi %u/%u", rssi, max_rssi);
629
	}
630
631
#undef RADIOTAP
632
633
	PRINTF(">");
634
	goto out;
635
636
 trunc:
637
	/* Truncated frame */
638
	PRINTF("[|radiotap + 802.11]");
639
640
 out:
641
	PRINTF(NULL);
642
}
643
644
void
645
hostapd_print_ieee80211(u_int dlt, u_int verbose, u_int8_t *buf, u_int len)
646
{
647
	if (verbose)
648
		vflag = 1;
649
	else
650
		vflag = 0;
651
652
	if (dlt == DLT_IEEE802_11)
653
		ieee802_11_if_print(buf, len);
654
	else
655
		ieee802_11_radio_if_print(buf, len);
656
}