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