]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_11.c
optional unit suffix on -C
[tcpdump] / print-802_11.c
1 /*
2 * Copyright (c) 2001
3 * Fortress Technologies, Inc. All rights reserved.
4 * Charlie Lenahan (clenahan@fortresstech.com)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code distributions
8 * retain the above copyright notice and this paragraph in its entirety, (2)
9 * distributions including binary code include the above copyright notice and
10 * this paragraph in its entirety in the documentation or other materials
11 * provided with the distribution, and (3) all advertising materials mentioning
12 * features or use of this software display the following acknowledgement:
13 * ``This product includes software developed by the University of California,
14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15 * the University nor the names of its contributors may be used to endorse
16 * or promote products derived from this software without specific prior
17 * written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
22
23 /* \summary: IEEE 802.11 printer */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include "netdissect-stdinc.h"
30
31 #include <string.h>
32
33 #include "netdissect.h"
34 #include "addrtoname.h"
35
36 #include "extract.h"
37
38 #include "cpack.h"
39
40
41 /* Lengths of 802.11 header components. */
42 #define IEEE802_11_FC_LEN 2
43 #define IEEE802_11_DUR_LEN 2
44 #define IEEE802_11_DA_LEN 6
45 #define IEEE802_11_SA_LEN 6
46 #define IEEE802_11_BSSID_LEN 6
47 #define IEEE802_11_RA_LEN 6
48 #define IEEE802_11_TA_LEN 6
49 #define IEEE802_11_ADDR1_LEN 6
50 #define IEEE802_11_SEQ_LEN 2
51 #define IEEE802_11_CTL_LEN 2
52 #define IEEE802_11_CARRIED_FC_LEN 2
53 #define IEEE802_11_HT_CONTROL_LEN 4
54 #define IEEE802_11_IV_LEN 3
55 #define IEEE802_11_KID_LEN 1
56
57 /* Frame check sequence length. */
58 #define IEEE802_11_FCS_LEN 4
59
60 /* Lengths of beacon components. */
61 #define IEEE802_11_TSTAMP_LEN 8
62 #define IEEE802_11_BCNINT_LEN 2
63 #define IEEE802_11_CAPINFO_LEN 2
64 #define IEEE802_11_LISTENINT_LEN 2
65
66 #define IEEE802_11_AID_LEN 2
67 #define IEEE802_11_STATUS_LEN 2
68 #define IEEE802_11_REASON_LEN 2
69
70 /* Length of previous AP in reassocation frame */
71 #define IEEE802_11_AP_LEN 6
72
73 #define T_MGMT 0x0 /* management */
74 #define T_CTRL 0x1 /* control */
75 #define T_DATA 0x2 /* data */
76 #define T_RESV 0x3 /* reserved */
77
78 #define ST_ASSOC_REQUEST 0x0
79 #define ST_ASSOC_RESPONSE 0x1
80 #define ST_REASSOC_REQUEST 0x2
81 #define ST_REASSOC_RESPONSE 0x3
82 #define ST_PROBE_REQUEST 0x4
83 #define ST_PROBE_RESPONSE 0x5
84 /* RESERVED 0x6 */
85 /* RESERVED 0x7 */
86 #define ST_BEACON 0x8
87 #define ST_ATIM 0x9
88 #define ST_DISASSOC 0xA
89 #define ST_AUTH 0xB
90 #define ST_DEAUTH 0xC
91 #define ST_ACTION 0xD
92 /* RESERVED 0xE */
93 /* RESERVED 0xF */
94
95 static const struct tok st_str[] = {
96 { ST_ASSOC_REQUEST, "Assoc Request" },
97 { ST_ASSOC_RESPONSE, "Assoc Response" },
98 { ST_REASSOC_REQUEST, "ReAssoc Request" },
99 { ST_REASSOC_RESPONSE, "ReAssoc Response" },
100 { ST_PROBE_REQUEST, "Probe Request" },
101 { ST_PROBE_RESPONSE, "Probe Response" },
102 { ST_BEACON, "Beacon" },
103 { ST_ATIM, "ATIM" },
104 { ST_DISASSOC, "Disassociation" },
105 { ST_AUTH, "Authentication" },
106 { ST_DEAUTH, "DeAuthentication" },
107 { ST_ACTION, "Action" },
108 { 0, NULL }
109 };
110
111 #define CTRL_CONTROL_WRAPPER 0x7
112 #define CTRL_BAR 0x8
113 #define CTRL_BA 0x9
114 #define CTRL_PS_POLL 0xA
115 #define CTRL_RTS 0xB
116 #define CTRL_CTS 0xC
117 #define CTRL_ACK 0xD
118 #define CTRL_CF_END 0xE
119 #define CTRL_END_ACK 0xF
120
121 static const struct tok ctrl_str[] = {
122 { CTRL_CONTROL_WRAPPER, "Control Wrapper" },
123 { CTRL_BAR, "BAR" },
124 { CTRL_BA, "BA" },
125 { CTRL_PS_POLL, "Power Save-Poll" },
126 { CTRL_RTS, "Request-To-Send" },
127 { CTRL_CTS, "Clear-To-Send" },
128 { CTRL_ACK, "Acknowledgment" },
129 { CTRL_CF_END, "CF-End" },
130 { CTRL_END_ACK, "CF-End+CF-Ack" },
131 { 0, NULL }
132 };
133
134 #define DATA_DATA 0x0
135 #define DATA_DATA_CF_ACK 0x1
136 #define DATA_DATA_CF_POLL 0x2
137 #define DATA_DATA_CF_ACK_POLL 0x3
138 #define DATA_NODATA 0x4
139 #define DATA_NODATA_CF_ACK 0x5
140 #define DATA_NODATA_CF_POLL 0x6
141 #define DATA_NODATA_CF_ACK_POLL 0x7
142
143 #define DATA_QOS_DATA 0x8
144 #define DATA_QOS_DATA_CF_ACK 0x9
145 #define DATA_QOS_DATA_CF_POLL 0xA
146 #define DATA_QOS_DATA_CF_ACK_POLL 0xB
147 #define DATA_QOS_NODATA 0xC
148 #define DATA_QOS_CF_POLL_NODATA 0xE
149 #define DATA_QOS_CF_ACK_POLL_NODATA 0xF
150
151 /*
152 * The subtype field of a data frame is, in effect, composed of 4 flag
153 * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
154 * any data), and QoS.
155 */
156 #define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01)
157 #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02)
158 #define DATA_FRAME_IS_NULL(x) ((x) & 0x04)
159 #define DATA_FRAME_IS_QOS(x) ((x) & 0x08)
160
161 /*
162 * Bits in the frame control field.
163 */
164 #define FC_VERSION(fc) ((fc) & 0x3)
165 #define FC_TYPE(fc) (((fc) >> 2) & 0x3)
166 #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF)
167 #define FC_TO_DS(fc) ((fc) & 0x0100)
168 #define FC_FROM_DS(fc) ((fc) & 0x0200)
169 #define FC_MORE_FLAG(fc) ((fc) & 0x0400)
170 #define FC_RETRY(fc) ((fc) & 0x0800)
171 #define FC_POWER_MGMT(fc) ((fc) & 0x1000)
172 #define FC_MORE_DATA(fc) ((fc) & 0x2000)
173 #define FC_PROTECTED(fc) ((fc) & 0x4000)
174 #define FC_ORDER(fc) ((fc) & 0x8000)
175
176 struct mgmt_header_t {
177 nd_uint16_t fc;
178 nd_uint16_t duration;
179 nd_mac_addr da;
180 nd_mac_addr sa;
181 nd_mac_addr bssid;
182 nd_uint16_t seq_ctrl;
183 };
184
185 #define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
186 IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\
187 IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN)
188
189 #define CAPABILITY_ESS(cap) ((cap) & 0x0001)
190 #define CAPABILITY_IBSS(cap) ((cap) & 0x0002)
191 #define CAPABILITY_CFP(cap) ((cap) & 0x0004)
192 #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008)
193 #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010)
194
195 struct ssid_t {
196 uint8_t element_id;
197 uint8_t length;
198 u_char ssid[33]; /* 32 + 1 for null */
199 };
200
201 struct rates_t {
202 uint8_t element_id;
203 uint8_t length;
204 uint8_t rate[16];
205 };
206
207 struct challenge_t {
208 uint8_t element_id;
209 uint8_t length;
210 uint8_t text[254]; /* 1-253 + 1 for null */
211 };
212
213 struct fh_t {
214 uint8_t element_id;
215 uint8_t length;
216 uint16_t dwell_time;
217 uint8_t hop_set;
218 uint8_t hop_pattern;
219 uint8_t hop_index;
220 };
221
222 struct ds_t {
223 uint8_t element_id;
224 uint8_t length;
225 uint8_t channel;
226 };
227
228 struct cf_t {
229 uint8_t element_id;
230 uint8_t length;
231 uint8_t count;
232 uint8_t period;
233 uint16_t max_duration;
234 uint16_t dur_remaining;
235 };
236
237 struct tim_t {
238 uint8_t element_id;
239 uint8_t length;
240 uint8_t count;
241 uint8_t period;
242 uint8_t bitmap_control;
243 uint8_t bitmap[251];
244 };
245
246 #define E_SSID 0
247 #define E_RATES 1
248 #define E_FH 2
249 #define E_DS 3
250 #define E_CF 4
251 #define E_TIM 5
252 #define E_IBSS 6
253 /* reserved 7 */
254 /* reserved 8 */
255 /* reserved 9 */
256 /* reserved 10 */
257 /* reserved 11 */
258 /* reserved 12 */
259 /* reserved 13 */
260 /* reserved 14 */
261 /* reserved 15 */
262 /* reserved 16 */
263
264 #define E_CHALLENGE 16
265 /* reserved 17 */
266 /* reserved 18 */
267 /* reserved 19 */
268 /* reserved 16 */
269 /* reserved 16 */
270
271
272 struct mgmt_body_t {
273 uint8_t timestamp[IEEE802_11_TSTAMP_LEN];
274 uint16_t beacon_interval;
275 uint16_t listen_interval;
276 uint16_t status_code;
277 uint16_t aid;
278 u_char ap[IEEE802_11_AP_LEN];
279 uint16_t reason_code;
280 uint16_t auth_alg;
281 uint16_t auth_trans_seq_num;
282 int challenge_present;
283 struct challenge_t challenge;
284 uint16_t capability_info;
285 int ssid_present;
286 struct ssid_t ssid;
287 int rates_present;
288 struct rates_t rates;
289 int ds_present;
290 struct ds_t ds;
291 int cf_present;
292 struct cf_t cf;
293 int fh_present;
294 struct fh_t fh;
295 int tim_present;
296 struct tim_t tim;
297 };
298
299 struct ctrl_control_wrapper_hdr_t {
300 nd_uint16_t fc;
301 nd_uint16_t duration;
302 nd_mac_addr addr1;
303 nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN];
304 nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN];
305 };
306
307 #define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
308 IEEE802_11_ADDR1_LEN+\
309 IEEE802_11_CARRIED_FC_LEN+\
310 IEEE802_11_HT_CONTROL_LEN)
311
312 struct ctrl_rts_hdr_t {
313 nd_uint16_t fc;
314 nd_uint16_t duration;
315 nd_mac_addr ra;
316 nd_mac_addr ta;
317 };
318
319 #define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
320 IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
321
322 struct ctrl_cts_hdr_t {
323 nd_uint16_t fc;
324 nd_uint16_t duration;
325 nd_mac_addr ra;
326 };
327
328 #define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
329
330 struct ctrl_ack_hdr_t {
331 nd_uint16_t fc;
332 nd_uint16_t duration;
333 nd_mac_addr ra;
334 };
335
336 #define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
337
338 struct ctrl_ps_poll_hdr_t {
339 nd_uint16_t fc;
340 nd_uint16_t aid;
341 nd_mac_addr bssid;
342 nd_mac_addr ta;
343 };
344
345 #define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
346 IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN)
347
348 struct ctrl_end_hdr_t {
349 nd_uint16_t fc;
350 nd_uint16_t duration;
351 nd_mac_addr ra;
352 nd_mac_addr bssid;
353 };
354
355 #define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
356 IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
357
358 struct ctrl_end_ack_hdr_t {
359 nd_uint16_t fc;
360 nd_uint16_t duration;
361 nd_mac_addr ra;
362 nd_mac_addr bssid;
363 };
364
365 #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
366 IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
367
368 struct ctrl_ba_hdr_t {
369 nd_uint16_t fc;
370 nd_uint16_t duration;
371 nd_mac_addr ra;
372 };
373
374 #define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
375
376 struct ctrl_bar_hdr_t {
377 nd_uint16_t fc;
378 nd_uint16_t dur;
379 nd_mac_addr ra;
380 nd_mac_addr ta;
381 nd_uint16_t ctl;
382 nd_uint16_t seq;
383 };
384
385 #define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
386 IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\
387 IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN)
388
389 struct meshcntl_t {
390 nd_uint8_t flags;
391 nd_uint8_t ttl;
392 nd_uint32_t seq;
393 nd_mac_addr addr4;
394 nd_mac_addr addr5;
395 nd_mac_addr addr6;
396 };
397
398 #define IV_IV(iv) ((iv) & 0xFFFFFF)
399 #define IV_PAD(iv) (((iv) >> 24) & 0x3F)
400 #define IV_KEYID(iv) (((iv) >> 30) & 0x03)
401
402 #define PRINT_SSID(p) \
403 if (p.ssid_present) { \
404 ND_PRINT(" ("); \
405 fn_print_str(ndo, p.ssid.ssid); \
406 ND_PRINT(")"); \
407 }
408
409 #define PRINT_RATE(_sep, _r, _suf) \
410 ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
411 #define PRINT_RATES(p) \
412 if (p.rates_present) { \
413 int z; \
414 const char *sep = " ["; \
415 for (z = 0; z < p.rates.length ; z++) { \
416 PRINT_RATE(sep, p.rates.rate[z], \
417 (p.rates.rate[z] & 0x80 ? "*" : "")); \
418 sep = " "; \
419 } \
420 if (p.rates.length != 0) \
421 ND_PRINT(" Mbit]"); \
422 }
423
424 #define PRINT_DS_CHANNEL(p) \
425 if (p.ds_present) \
426 ND_PRINT(" CH: %u", p.ds.channel); \
427 ND_PRINT("%s", \
428 CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
429
430 #define MAX_MCS_INDEX 76
431
432 /*
433 * Indices are:
434 *
435 * the MCS index (0-76);
436 *
437 * 0 for 20 MHz, 1 for 40 MHz;
438 *
439 * 0 for a long guard interval, 1 for a short guard interval.
440 */
441 static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
442 /* MCS 0 */
443 { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, },
444 /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, },
445 },
446
447 /* MCS 1 */
448 { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
449 /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
450 },
451
452 /* MCS 2 */
453 { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
454 /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
455 },
456
457 /* MCS 3 */
458 { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
459 /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
460 },
461
462 /* MCS 4 */
463 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
464 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
465 },
466
467 /* MCS 5 */
468 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
469 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
470 },
471
472 /* MCS 6 */
473 { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
474 /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
475 },
476
477 /* MCS 7 */
478 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
479 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
480 },
481
482 /* MCS 8 */
483 { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
484 /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
485 },
486
487 /* MCS 9 */
488 { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
489 /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
490 },
491
492 /* MCS 10 */
493 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
494 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
495 },
496
497 /* MCS 11 */
498 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
499 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
500 },
501
502 /* MCS 12 */
503 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
504 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
505 },
506
507 /* MCS 13 */
508 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
509 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
510 },
511
512 /* MCS 14 */
513 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
514 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
515 },
516
517 /* MCS 15 */
518 { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
519 /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
520 },
521
522 /* MCS 16 */
523 { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
524 /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
525 },
526
527 /* MCS 17 */
528 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
529 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
530 },
531
532 /* MCS 18 */
533 { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
534 /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
535 },
536
537 /* MCS 19 */
538 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
539 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
540 },
541
542 /* MCS 20 */
543 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
544 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
545 },
546
547 /* MCS 21 */
548 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
549 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
550 },
551
552 /* MCS 22 */
553 { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
554 /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
555 },
556
557 /* MCS 23 */
558 { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
559 /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
560 },
561
562 /* MCS 24 */
563 { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
564 /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
565 },
566
567 /* MCS 25 */
568 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
569 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
570 },
571
572 /* MCS 26 */
573 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
574 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
575 },
576
577 /* MCS 27 */
578 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
579 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
580 },
581
582 /* MCS 28 */
583 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
584 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
585 },
586
587 /* MCS 29 */
588 { /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, },
589 /* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, },
590 },
591
592 /* MCS 30 */
593 { /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, },
594 /* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, },
595 },
596
597 /* MCS 31 */
598 { /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, },
599 /* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, },
600 },
601
602 /* MCS 32 */
603 { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */
604 /* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, },
605 },
606
607 /* MCS 33 */
608 { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
609 /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
610 },
611
612 /* MCS 34 */
613 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
614 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
615 },
616
617 /* MCS 35 */
618 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
619 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
620 },
621
622 /* MCS 36 */
623 { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
624 /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
625 },
626
627 /* MCS 37 */
628 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
629 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
630 },
631
632 /* MCS 38 */
633 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
634 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
635 },
636
637 /* MCS 39 */
638 { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
639 /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
640 },
641
642 /* MCS 40 */
643 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
644 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
645 },
646
647 /* MCS 41 */
648 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
649 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
650 },
651
652 /* MCS 42 */
653 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
654 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
655 },
656
657 /* MCS 43 */
658 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
659 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
660 },
661
662 /* MCS 44 */
663 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
664 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
665 },
666
667 /* MCS 45 */
668 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
669 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
670 },
671
672 /* MCS 46 */
673 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
674 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
675 },
676
677 /* MCS 47 */
678 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
679 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
680 },
681
682 /* MCS 48 */
683 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
684 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
685 },
686
687 /* MCS 49 */
688 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
689 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
690 },
691
692 /* MCS 50 */
693 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
694 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
695 },
696
697 /* MCS 51 */
698 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
699 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
700 },
701
702 /* MCS 52 */
703 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
704 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
705 },
706
707 /* MCS 53 */
708 { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
709 /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
710 },
711
712 /* MCS 54 */
713 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
714 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
715 },
716
717 /* MCS 55 */
718 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
719 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
720 },
721
722 /* MCS 56 */
723 { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
724 /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
725 },
726
727 /* MCS 57 */
728 { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
729 /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
730 },
731
732 /* MCS 58 */
733 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
734 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
735 },
736
737 /* MCS 59 */
738 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
739 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
740 },
741
742 /* MCS 60 */
743 { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
744 /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
745 },
746
747 /* MCS 61 */
748 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
749 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
750 },
751
752 /* MCS 62 */
753 { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
754 /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
755 },
756
757 /* MCS 63 */
758 { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
759 /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
760 },
761
762 /* MCS 64 */
763 { /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, },
764 /* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, },
765 },
766
767 /* MCS 65 */
768 { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
769 /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
770 },
771
772 /* MCS 66 */
773 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
774 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
775 },
776
777 /* MCS 67 */
778 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
779 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
780 },
781
782 /* MCS 68 */
783 { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
784 /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
785 },
786
787 /* MCS 69 */
788 { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
789 /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
790 },
791
792 /* MCS 70 */
793 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
794 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
795 },
796
797 /* MCS 71 */
798 { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
799 /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
800 },
801
802 /* MCS 72 */
803 { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
804 /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
805 },
806
807 /* MCS 73 */
808 { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
809 /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
810 },
811
812 /* MCS 74 */
813 { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
814 /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
815 },
816
817 /* MCS 75 */
818 { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
819 /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
820 },
821
822 /* MCS 76 */
823 { /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, },
824 /* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, },
825 },
826 };
827
828 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
829 #define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0]))
830
831 static const char *status_text[] = {
832 "Successful", /* 0 */
833 "Unspecified failure", /* 1 */
834 "TDLS wakeup schedule rejected but alternative schedule "
835 "provided", /* 2 */
836 "TDLS wakeup schedule rejected",/* 3 */
837 "Reserved", /* 4 */
838 "Security disabled", /* 5 */
839 "Unacceptable lifetime", /* 6 */
840 "Not in same BSS", /* 7 */
841 "Reserved", /* 8 */
842 "Reserved", /* 9 */
843 "Cannot Support all requested capabilities in the Capability "
844 "Information field", /* 10 */
845 "Reassociation denied due to inability to confirm that association "
846 "exists", /* 11 */
847 "Association denied due to reason outside the scope of this "
848 "standard", /* 12 */
849 "Responding STA does not support the specified authentication "
850 "algorithm", /* 13 */
851 "Received an Authentication frame with authentication transaction "
852 "sequence number out of expected sequence", /* 14 */
853 "Authentication rejected because of challenge failure", /* 15 */
854 "Authentication rejected due to timeout waiting for next frame in "
855 "sequence", /* 16 */
856 "Association denied because AP is unable to handle "
857 "additional associated STAs", /* 17 */
858 "Association denied due to requesting STA not supporting "
859 "all of the data rates in the BSSBasicRateSet parameter, "
860 "the Basic HT-MCS Set field of the HT Operation "
861 "parameter, or the Basic VHT-MCS and NSS Set field in "
862 "the VHT Operation parameter", /* 18 */
863 "Association denied due to requesting STA not supporting "
864 "the short preamble option", /* 19 */
865 "Reserved", /* 20 */
866 "Reserved", /* 21 */
867 "Association request rejected because Spectrum Management "
868 "capability is required", /* 22 */
869 "Association request rejected because the information in the "
870 "Power Capability element is unacceptable", /* 23 */
871 "Association request rejected because the information in the "
872 "Supported Channels element is unacceptable", /* 24 */
873 "Association denied due to requesting STA not supporting "
874 "the Short Slot Time option", /* 25 */
875 "Reserved", /* 26 */
876 "Association denied because the requested STA does not support HT "
877 "features", /* 27 */
878 "R0KH unreachable", /* 28 */
879 "Association denied because the requesting STA does not "
880 "support the phased coexistence operation (PCO) "
881 "transition time required by the AP", /* 29 */
882 "Association request rejected temporarily; try again "
883 "later", /* 30 */
884 "Robust management frame policy violation", /* 31 */
885 "Unspecified, QoS-related failure", /* 32 */
886 "Association denied because QoS AP or PCP has "
887 "insufficient bandwidth to handle another QoS "
888 "STA", /* 33 */
889 "Association denied due to excessive frame loss rates and/or "
890 "poor conditions on current operating channel", /* 34 */
891 "Association (with QoS BSS) denied because the requesting STA "
892 "does not support the QoS facility", /* 35 */
893 "Reserved", /* 36 */
894 "The request has been declined", /* 37 */
895 "The request has not been successful as one or more parameters "
896 "have invalid values", /* 38 */
897 "The allocation or TS has not been created because the request "
898 "cannot be honored; however, a suggested TSPEC/DMG TSPEC is "
899 "provided so that the initiating STA can attempt to set "
900 "another allocation or TS with the suggested changes to the "
901 "TSPEC/DMG TSPEC", /* 39 */
902 "Invalid element, i.e., an element defined in this standard "
903 "for which the content does not meet the specifications in "
904 "Clause 9", /* 40 */
905 "Invalid group cipher", /* 41 */
906 "Invalid pairwise cipher", /* 42 */
907 "Invalid AKMP", /* 43 */
908 "Unsupported RSNE version", /* 44 */
909 "Invalid RSNE capabilities", /* 45 */
910 "Cipher suite rejected because of security policy", /* 46 */
911 "The TS or allocation has not been created; however, the "
912 "HC or PCP might be capable of creating a TS or "
913 "allocation, in response to a request, after the time "
914 "indicated in the TS Delay element", /* 47 */
915 "Direct Link is not allowed in the BSS by policy", /* 48 */
916 "The Destination STA is not present within this BSS", /* 49 */
917 "The Destination STA is not a QoS STA", /* 50 */
918
919 "Association denied because the listen interval is "
920 "too large", /* 51 */
921 "Invalid FT Action frame count", /* 52 */
922 "Invalid pairwise master key identifier (PMKID)", /* 53 */
923 "Invalid MDE", /* 54 */
924 "Invalid FTE", /* 55 */
925 "Requested TCLAS processing is not supported by the AP "
926 "or PCP", /* 56 */
927 "The AP or PCP has insufficient TCLAS processing "
928 "resources to satisfy the request", /* 57 */
929 "The TS has not been created because the request "
930 "cannot be honored; however, the HC or PCP suggests "
931 "that the STA transition to a different BSS to set up "
932 "the TS", /* 58 */
933 "GAS Advertisement Protocol not supported", /* 59 */
934 "No outstanding GAS request", /* 60 */
935 "GAS Response not received from the Advertisement "
936 "Server", /* 61 */
937 "STA timed out waiting for GAS Query Response", /* 62 */
938 "LARGE GAS Response is larger than query response "
939 "length limit", /* 63 */
940 "Request refused because home network does not support "
941 "request", /* 64 */
942 "Advertisement Server in the network is not currently "
943 "reachable", /* 65 */
944 "Reserved", /* 66 */
945 "Request refused due to permissions received via SSPN "
946 "interface", /* 67 */
947 "Request refused because the AP or PCP does not "
948 "support unauthenticated access", /* 68 */
949 "Reserved", /* 69 */
950 "Reserved", /* 70 */
951 "Reserved", /* 71 */
952 "Invalid contents of RSNE", /* 72 */
953 "U-APSD coexistence is not supported", /* 73 */
954 "Requested U-APSD coexistence mode is not supported", /* 74 */
955 "Requested Interval/Duration value cannot be "
956 "supported with U-APSD coexistence", /* 75 */
957 "Authentication is rejected because an Anti-Clogging "
958 "Token is required", /* 76 */
959 "Authentication is rejected because the offered "
960 "finite cyclic group is not supported", /* 77 */
961 "The TBTT adjustment request has not been successful "
962 "because the STA could not find an alternative TBTT", /* 78 */
963 "Transmission failure", /* 79 */
964 "Requested TCLAS Not Supported", /* 80 */
965 "TCLAS Resources Exhausted", /* 81 */
966 "Rejected with Suggested BSS transition", /* 82 */
967 "Reject with recommended schedule", /* 83 */
968 "Reject because no wakeup schedule specified", /* 84 */
969 "Success, the destination STA is in power save mode", /* 85 */
970 "FST pending, in process of admitting FST session", /* 86 */
971 "Performing FST now", /* 87 */
972 "FST pending, gap(s) in block ack window", /* 88 */
973 "Reject because of U-PID setting", /* 89 */
974 "Reserved", /* 90 */
975 "Reserved", /* 91 */
976 "(Re)Association refused for some external reason", /* 92 */
977 "(Re)Association refused because of memory limits "
978 "at the AP", /* 93 */
979 "(Re)Association refused because emergency services "
980 "are not supported at the AP", /* 94 */
981 "GAS query response not yet received", /* 95 */
982 "Reject since the request is for transition to a "
983 "frequency band subject to DSE procedures and "
984 "FST Initiator is a dependent STA", /* 96 */
985 "Requested TCLAS processing has been terminated by "
986 "the AP", /* 97 */
987 "The TS schedule conflicts with an existing "
988 "schedule; an alternative schedule is provided", /* 98 */
989 "The association has been denied; however, one or "
990 "more Multi-band elements are included that can "
991 "be used by the receiving STA to join the BSS", /* 99 */
992 "The request failed due to a reservation conflict", /* 100 */
993 "The request failed due to exceeded MAF limit", /* 101 */
994 "The request failed due to exceeded MCCA track "
995 "limit", /* 102 */
996 "Association denied because the information in the"
997 "Spectrum Management field is unacceptable", /* 103 */
998 "Association denied because the requesting STA "
999 "does not support VHT features", /* 104 */
1000 "Enablement denied", /* 105 */
1001 "Enablement denied due to restriction from an "
1002 "authorized GDB", /* 106 */
1003 "Authorization deenabled", /* 107 */
1004 };
1005 #define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0]))
1006
1007 static const char *reason_text[] = {
1008 "Reserved", /* 0 */
1009 "Unspecified reason", /* 1 */
1010 "Previous authentication no longer valid", /* 2 */
1011 "Deauthenticated because sending STA is leaving (or has left) "
1012 "IBSS or ESS", /* 3 */
1013 "Disassociated due to inactivity", /* 4 */
1014 "Disassociated because AP is unable to handle all currently "
1015 " associated STAs", /* 5 */
1016 "Class 2 frame received from nonauthenticated STA", /* 6 */
1017 "Class 3 frame received from nonassociated STA", /* 7 */
1018 "Disassociated because sending STA is leaving "
1019 "(or has left) BSS", /* 8 */
1020 "STA requesting (re)association is not authenticated with "
1021 "responding STA", /* 9 */
1022 "Disassociated because the information in the Power Capability "
1023 "element is unacceptable", /* 10 */
1024 "Disassociated because the information in the Supported Channels "
1025 "element is unacceptable", /* 11 */
1026 "Disassociated due to BSS transition management", /* 12 */
1027 "Invalid element, i.e., an element defined in this standard for "
1028 "which the content does not meet the specifications "
1029 "in Clause 9", /* 13 */
1030 "Message integrity code (MIC) failure", /* 14 */
1031 "4-Way Handshake timeout", /* 15 */
1032 "Group key handshake timeout", /* 16 */
1033 "Information element in 4-Way Handshake different from (Re)Association"
1034 "Request/Probe Response/Beacon frame", /* 17 */
1035 "Invalid group cipher", /* 18 */
1036 "Invalid pairwise cipher", /* 19 */
1037 "Invalid AKMP", /* 20 */
1038 "Unsupported RSNE version", /* 21 */
1039 "Invalid RSNE capabilities", /* 22 */
1040 "IEEE 802.1X authentication failed", /* 23 */
1041 "Cipher suite rejected because of the security policy", /* 24 */
1042 "TDLS direct-link teardown due to TDLS peer STA "
1043 "unreachable via the TDLS direct link", /* 25 */
1044 "TDLS direct-link teardown for unspecified reason", /* 26 */
1045 "Disassociated because session terminated by SSP request",/* 27 */
1046 "Disassociated because of lack of SSP roaming agreement",/* 28 */
1047 "Requested service rejected because of SSP cipher suite or "
1048 "AKM requirement", /* 29 */
1049 "Requested service not authorized in this location", /* 30 */
1050 "TS deleted because QoS AP lacks sufficient bandwidth for this "
1051 "QoS STA due to a change in BSS service characteristics or "
1052 "operational mode (e.g. an HT BSS change from 40 MHz channel "
1053 "to 20 MHz channel)", /* 31 */
1054 "Disassociated for unspecified, QoS-related reason", /* 32 */
1055 "Disassociated because QoS AP lacks sufficient bandwidth for this "
1056 "QoS STA", /* 33 */
1057 "Disassociated because of excessive number of frames that need to be "
1058 "acknowledged, but are not acknowledged due to AP transmissions "
1059 "and/or poor channel conditions", /* 34 */
1060 "Disassociated because STA is transmitting outside the limits "
1061 "of its TXOPs", /* 35 */
1062 "Requested from peer STA as the STA is leaving the BSS "
1063 "(or resetting)", /* 36 */
1064 "Requested from peer STA as it does not want to use the "
1065 "mechanism", /* 37 */
1066 "Requested from peer STA as the STA received frames using the "
1067 "mechanism for which a set up is required", /* 38 */
1068 "Requested from peer STA due to time out", /* 39 */
1069 "Reserved", /* 40 */
1070 "Reserved", /* 41 */
1071 "Reserved", /* 42 */
1072 "Reserved", /* 43 */
1073 "Reserved", /* 44 */
1074 "Peer STA does not support the requested cipher suite", /* 45 */
1075 "In a DLS Teardown frame: The teardown was initiated by the "
1076 "DLS peer. In a Disassociation frame: Disassociated because "
1077 "authorized access limit reached", /* 46 */
1078 "In a DLS Teardown frame: The teardown was initiated by the "
1079 "AP. In a Disassociation frame: Disassociated due to external "
1080 "service requirements", /* 47 */
1081 "Invalid FT Action frame count", /* 48 */
1082 "Invalid pairwise master key identifier (PMKID)", /* 49 */
1083 "Invalid MDE", /* 50 */
1084 "Invalid FTE", /* 51 */
1085 "Mesh peering canceled for unknown reasons", /* 52 */
1086 "The mesh STA has reached the supported maximum number of "
1087 "peer mesh STAs", /* 53 */
1088 "The received information violates the Mesh Configuration "
1089 "policy configured in the mesh STA profile", /* 54 */
1090 "The mesh STA has received a Mesh Peering Close frame "
1091 "requesting to close the mesh peering", /* 55 */
1092 "The mesh STA has resent dot11MeshMaxRetries Mesh "
1093 "Peering Open frames, without receiving a Mesh Peering "
1094 "Confirm frame", /* 56 */
1095 "The confirmTimer for the mesh peering instance times out", /* 57 */
1096 "The mesh STA fails to unwrap the GTK or the values in the "
1097 "wrapped contents do not match", /* 58 */
1098 "The mesh STA receives inconsistent information about the "
1099 "mesh parameters between mesh peering Management frames", /* 59 */
1100 "The mesh STA fails the authenticated mesh peering exchange "
1101 "because due to failure in selecting either the pairwise "
1102 "ciphersuite or group ciphersuite", /* 60 */
1103 "The mesh STA does not have proxy information for this "
1104 "external destination", /* 61 */
1105 "The mesh STA does not have forwarding information for this "
1106 "destination", /* 62 */
1107 "The mesh STA determines that the link to the next hop of an "
1108 "active path in its forwarding information is no longer "
1109 "usable", /* 63 */
1110 "The Deauthentication frame was sent because the MAC "
1111 "address of the STA already exists in the mesh BSS", /* 64 */
1112 "The mesh STA performs channel switch to meet regulatory "
1113 "requirements", /* 65 */
1114 "The mesh STA performs channel switching with unspecified "
1115 "reason", /* 66 */
1116 };
1117 #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0]))
1118
1119 static int
1120 wep_print(netdissect_options *ndo,
1121 const u_char *p)
1122 {
1123 uint32_t iv;
1124
1125 ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN);
1126 iv = GET_LE_U_4(p);
1127
1128 ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
1129 IV_KEYID(iv));
1130
1131 return 1;
1132 trunc:
1133 return 0;
1134 }
1135
1136 static int
1137 parse_elements(netdissect_options *ndo,
1138 struct mgmt_body_t *pbody, const u_char *p, int offset,
1139 u_int length)
1140 {
1141 u_int elementlen;
1142 struct ssid_t ssid;
1143 struct challenge_t challenge;
1144 struct rates_t rates;
1145 struct ds_t ds;
1146 struct cf_t cf;
1147 struct tim_t tim;
1148
1149 /*
1150 * We haven't seen any elements yet.
1151 */
1152 pbody->challenge_present = 0;
1153 pbody->ssid_present = 0;
1154 pbody->rates_present = 0;
1155 pbody->ds_present = 0;
1156 pbody->cf_present = 0;
1157 pbody->tim_present = 0;
1158
1159 while (length != 0) {
1160 /* Make sure we at least have the element ID and length. */
1161 ND_TCHECK_2(p + offset);
1162 if (length < 2)
1163 goto trunc;
1164 elementlen = GET_U_1(p + offset + 1);
1165
1166 /* Make sure we have the entire element. */
1167 ND_TCHECK_LEN(p + offset + 2, elementlen);
1168 if (length < elementlen + 2)
1169 goto trunc;
1170
1171 switch (GET_U_1(p + offset)) {
1172 case E_SSID:
1173 memcpy(&ssid, p + offset, 2);
1174 offset += 2;
1175 length -= 2;
1176 if (ssid.length != 0) {
1177 if (ssid.length > sizeof(ssid.ssid) - 1)
1178 return 0;
1179 memcpy(&ssid.ssid, p + offset, ssid.length);
1180 offset += ssid.length;
1181 length -= ssid.length;
1182 }
1183 ssid.ssid[ssid.length] = '\0';
1184 /*
1185 * Present and not truncated.
1186 *
1187 * If we haven't already seen an SSID IE,
1188 * copy this one, otherwise ignore this one,
1189 * so we later report the first one we saw.
1190 */
1191 if (!pbody->ssid_present) {
1192 pbody->ssid = ssid;
1193 pbody->ssid_present = 1;
1194 }
1195 break;
1196 case E_CHALLENGE:
1197 memcpy(&challenge, p + offset, 2);
1198 offset += 2;
1199 length -= 2;
1200 if (challenge.length != 0) {
1201 if (challenge.length >
1202 sizeof(challenge.text) - 1)
1203 return 0;
1204 memcpy(&challenge.text, p + offset,
1205 challenge.length);
1206 offset += challenge.length;
1207 length -= challenge.length;
1208 }
1209 challenge.text[challenge.length] = '\0';
1210 /*
1211 * Present and not truncated.
1212 *
1213 * If we haven't already seen a challenge IE,
1214 * copy this one, otherwise ignore this one,
1215 * so we later report the first one we saw.
1216 */
1217 if (!pbody->challenge_present) {
1218 pbody->challenge = challenge;
1219 pbody->challenge_present = 1;
1220 }
1221 break;
1222 case E_RATES:
1223 memcpy(&rates, p + offset, 2);
1224 offset += 2;
1225 length -= 2;
1226 if (rates.length != 0) {
1227 if (rates.length > sizeof(rates.rate))
1228 return 0;
1229 memcpy(&rates.rate, p + offset, rates.length);
1230 offset += rates.length;
1231 length -= rates.length;
1232 }
1233 /*
1234 * Present and not truncated.
1235 *
1236 * If we haven't already seen a rates IE,
1237 * copy this one if it's not zero-length,
1238 * otherwise ignore this one, so we later
1239 * report the first one we saw.
1240 *
1241 * We ignore zero-length rates IEs as some
1242 * devices seem to put a zero-length rates
1243 * IE, followed by an SSID IE, followed by
1244 * a non-zero-length rates IE into frames,
1245 * even though IEEE Std 802.11-2007 doesn't
1246 * seem to indicate that a zero-length rates
1247 * IE is valid.
1248 */
1249 if (!pbody->rates_present && rates.length != 0) {
1250 pbody->rates = rates;
1251 pbody->rates_present = 1;
1252 }
1253 break;
1254 case E_DS:
1255 memcpy(&ds, p + offset, 2);
1256 offset += 2;
1257 length -= 2;
1258 if (ds.length != 1) {
1259 offset += ds.length;
1260 length -= ds.length;
1261 break;
1262 }
1263 ds.channel = GET_U_1(p + offset);
1264 offset += 1;
1265 length -= 1;
1266 /*
1267 * Present and not truncated.
1268 *
1269 * If we haven't already seen a DS IE,
1270 * copy this one, otherwise ignore this one,
1271 * so we later report the first one we saw.
1272 */
1273 if (!pbody->ds_present) {
1274 pbody->ds = ds;
1275 pbody->ds_present = 1;
1276 }
1277 break;
1278 case E_CF:
1279 memcpy(&cf, p + offset, 2);
1280 offset += 2;
1281 length -= 2;
1282 if (cf.length != 6) {
1283 offset += cf.length;
1284 length -= cf.length;
1285 break;
1286 }
1287 memcpy(&cf.count, p + offset, 6);
1288 offset += 6;
1289 length -= 6;
1290 /*
1291 * Present and not truncated.
1292 *
1293 * If we haven't already seen a CF IE,
1294 * copy this one, otherwise ignore this one,
1295 * so we later report the first one we saw.
1296 */
1297 if (!pbody->cf_present) {
1298 pbody->cf = cf;
1299 pbody->cf_present = 1;
1300 }
1301 break;
1302 case E_TIM:
1303 memcpy(&tim, p + offset, 2);
1304 offset += 2;
1305 length -= 2;
1306 if (tim.length <= 3U) {
1307 offset += tim.length;
1308 length -= tim.length;
1309 break;
1310 }
1311 if (tim.length - 3U > sizeof(tim.bitmap))
1312 return 0;
1313 memcpy(&tim.count, p + offset, 3);
1314 offset += 3;
1315 length -= 3;
1316
1317 memcpy(tim.bitmap, p + offset, tim.length - 3);
1318 offset += tim.length - 3;
1319 length -= tim.length - 3;
1320 /*
1321 * Present and not truncated.
1322 *
1323 * If we haven't already seen a TIM IE,
1324 * copy this one, otherwise ignore this one,
1325 * so we later report the first one we saw.
1326 */
1327 if (!pbody->tim_present) {
1328 pbody->tim = tim;
1329 pbody->tim_present = 1;
1330 }
1331 break;
1332 default:
1333 #if 0
1334 ND_PRINT("(1) unhandled element_id (%u) ",
1335 GET_U_1(p + offset));
1336 #endif
1337 offset += 2 + elementlen;
1338 length -= 2 + elementlen;
1339 break;
1340 }
1341 }
1342
1343 /* No problems found. */
1344 return 1;
1345 trunc:
1346 return 0;
1347 }
1348
1349 /*********************************************************************************
1350 * Print Handle functions for the management frame types
1351 *********************************************************************************/
1352
1353 static int
1354 handle_beacon(netdissect_options *ndo,
1355 const u_char *p, u_int length)
1356 {
1357 struct mgmt_body_t pbody;
1358 int offset = 0;
1359 int ret;
1360
1361 memset(&pbody, 0, sizeof(pbody));
1362
1363 ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1364 IEEE802_11_CAPINFO_LEN);
1365 if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1366 IEEE802_11_CAPINFO_LEN)
1367 goto trunc;
1368 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
1369 offset += IEEE802_11_TSTAMP_LEN;
1370 length -= IEEE802_11_TSTAMP_LEN;
1371 pbody.beacon_interval = GET_LE_U_2(p + offset);
1372 offset += IEEE802_11_BCNINT_LEN;
1373 length -= IEEE802_11_BCNINT_LEN;
1374 pbody.capability_info = GET_LE_U_2(p + offset);
1375 offset += IEEE802_11_CAPINFO_LEN;
1376 length -= IEEE802_11_CAPINFO_LEN;
1377
1378 ret = parse_elements(ndo, &pbody, p, offset, length);
1379
1380 PRINT_SSID(pbody);
1381 PRINT_RATES(pbody);
1382 ND_PRINT(" %s",
1383 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
1384 PRINT_DS_CHANNEL(pbody);
1385
1386 return ret;
1387 trunc:
1388 return 0;
1389 }
1390
1391 static int
1392 handle_assoc_request(netdissect_options *ndo,
1393 const u_char *p, u_int length)
1394 {
1395 struct mgmt_body_t pbody;
1396 int offset = 0;
1397 int ret;
1398
1399 memset(&pbody, 0, sizeof(pbody));
1400
1401 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
1402 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
1403 goto trunc;
1404 pbody.capability_info = GET_LE_U_2(p);
1405 offset += IEEE802_11_CAPINFO_LEN;
1406 length -= IEEE802_11_CAPINFO_LEN;
1407 pbody.listen_interval = GET_LE_U_2(p + offset);
1408 offset += IEEE802_11_LISTENINT_LEN;
1409 length -= IEEE802_11_LISTENINT_LEN;
1410
1411 ret = parse_elements(ndo, &pbody, p, offset, length);
1412
1413 PRINT_SSID(pbody);
1414 PRINT_RATES(pbody);
1415 return ret;
1416 trunc:
1417 return 0;
1418 }
1419
1420 static int
1421 handle_assoc_response(netdissect_options *ndo,
1422 const u_char *p, u_int length)
1423 {
1424 struct mgmt_body_t pbody;
1425 int offset = 0;
1426 int ret;
1427
1428 memset(&pbody, 0, sizeof(pbody));
1429
1430 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1431 IEEE802_11_AID_LEN);
1432 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1433 IEEE802_11_AID_LEN)
1434 goto trunc;
1435 pbody.capability_info = GET_LE_U_2(p);
1436 offset += IEEE802_11_CAPINFO_LEN;
1437 length -= IEEE802_11_CAPINFO_LEN;
1438 pbody.status_code = GET_LE_U_2(p + offset);
1439 offset += IEEE802_11_STATUS_LEN;
1440 length -= IEEE802_11_STATUS_LEN;
1441 pbody.aid = GET_LE_U_2(p + offset);
1442 offset += IEEE802_11_AID_LEN;
1443 length -= IEEE802_11_AID_LEN;
1444
1445 ret = parse_elements(ndo, &pbody, p, offset, length);
1446
1447 ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
1448 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
1449 (pbody.status_code < NUM_STATUSES
1450 ? status_text[pbody.status_code]
1451 : "n/a"));
1452
1453 return ret;
1454 trunc:
1455 return 0;
1456 }
1457
1458 static int
1459 handle_reassoc_request(netdissect_options *ndo,
1460 const u_char *p, u_int length)
1461 {
1462 struct mgmt_body_t pbody;
1463 int offset = 0;
1464 int ret;
1465
1466 memset(&pbody, 0, sizeof(pbody));
1467
1468 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1469 IEEE802_11_AP_LEN);
1470 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1471 IEEE802_11_AP_LEN)
1472 goto trunc;
1473 pbody.capability_info = GET_LE_U_2(p);
1474 offset += IEEE802_11_CAPINFO_LEN;
1475 length -= IEEE802_11_CAPINFO_LEN;
1476 pbody.listen_interval = GET_LE_U_2(p + offset);
1477 offset += IEEE802_11_LISTENINT_LEN;
1478 length -= IEEE802_11_LISTENINT_LEN;
1479 memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
1480 offset += IEEE802_11_AP_LEN;
1481 length -= IEEE802_11_AP_LEN;
1482
1483 ret = parse_elements(ndo, &pbody, p, offset, length);
1484
1485 PRINT_SSID(pbody);
1486 ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap ));
1487
1488 return ret;
1489 trunc:
1490 return 0;
1491 }
1492
1493 static int
1494 handle_reassoc_response(netdissect_options *ndo,
1495 const u_char *p, u_int length)
1496 {
1497 /* Same as a Association Response */
1498 return handle_assoc_response(ndo, p, length);
1499 }
1500
1501 static int
1502 handle_probe_request(netdissect_options *ndo,
1503 const u_char *p, u_int length)
1504 {
1505 struct mgmt_body_t pbody;
1506 int offset = 0;
1507 int ret;
1508
1509 memset(&pbody, 0, sizeof(pbody));
1510
1511 ret = parse_elements(ndo, &pbody, p, offset, length);
1512
1513 PRINT_SSID(pbody);
1514 PRINT_RATES(pbody);
1515
1516 return ret;
1517 }
1518
1519 static int
1520 handle_probe_response(netdissect_options *ndo,
1521 const u_char *p, u_int length)
1522 {
1523 struct mgmt_body_t pbody;
1524 int offset = 0;
1525 int ret;
1526
1527 memset(&pbody, 0, sizeof(pbody));
1528
1529 ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1530 IEEE802_11_CAPINFO_LEN);
1531 if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1532 IEEE802_11_CAPINFO_LEN)
1533 goto trunc;
1534 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
1535 offset += IEEE802_11_TSTAMP_LEN;
1536 length -= IEEE802_11_TSTAMP_LEN;
1537 pbody.beacon_interval = GET_LE_U_2(p + offset);
1538 offset += IEEE802_11_BCNINT_LEN;
1539 length -= IEEE802_11_BCNINT_LEN;
1540 pbody.capability_info = GET_LE_U_2(p + offset);
1541 offset += IEEE802_11_CAPINFO_LEN;
1542 length -= IEEE802_11_CAPINFO_LEN;
1543
1544 ret = parse_elements(ndo, &pbody, p, offset, length);
1545
1546 PRINT_SSID(pbody);
1547 PRINT_RATES(pbody);
1548 PRINT_DS_CHANNEL(pbody);
1549
1550 return ret;
1551 trunc:
1552 return 0;
1553 }
1554
1555 static int
1556 handle_atim(void)
1557 {
1558 /* the frame body for ATIM is null. */
1559 return 1;
1560 }
1561
1562 static int
1563 handle_disassoc(netdissect_options *ndo,
1564 const u_char *p, u_int length)
1565 {
1566 struct mgmt_body_t pbody;
1567
1568 memset(&pbody, 0, sizeof(pbody));
1569
1570 ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
1571 if (length < IEEE802_11_REASON_LEN)
1572 goto trunc;
1573 pbody.reason_code = GET_LE_U_2(p);
1574
1575 ND_PRINT(": %s",
1576 (pbody.reason_code < NUM_REASONS)
1577 ? reason_text[pbody.reason_code]
1578 : "Reserved");
1579
1580 return 1;
1581 trunc:
1582 return 0;
1583 }
1584
1585 static int
1586 handle_auth(netdissect_options *ndo,
1587 const u_char *p, u_int length)
1588 {
1589 struct mgmt_body_t pbody;
1590 int offset = 0;
1591 int ret;
1592
1593 memset(&pbody, 0, sizeof(pbody));
1594
1595 ND_TCHECK_6(p);
1596 if (length < 6)
1597 goto trunc;
1598 pbody.auth_alg = GET_LE_U_2(p);
1599 offset += 2;
1600 length -= 2;
1601 pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
1602 offset += 2;
1603 length -= 2;
1604 pbody.status_code = GET_LE_U_2(p + offset);
1605 offset += 2;
1606 length -= 2;
1607
1608 ret = parse_elements(ndo, &pbody, p, offset, length);
1609
1610 if ((pbody.auth_alg == 1) &&
1611 ((pbody.auth_trans_seq_num == 2) ||
1612 (pbody.auth_trans_seq_num == 3))) {
1613 ND_PRINT(" (%s)-%x [Challenge Text] %s",
1614 (pbody.auth_alg < NUM_AUTH_ALGS)
1615 ? auth_alg_text[pbody.auth_alg]
1616 : "Reserved",
1617 pbody.auth_trans_seq_num,
1618 ((pbody.auth_trans_seq_num % 2)
1619 ? ((pbody.status_code < NUM_STATUSES)
1620 ? status_text[pbody.status_code]
1621 : "n/a") : ""));
1622 return ret;
1623 }
1624 ND_PRINT(" (%s)-%x: %s",
1625 (pbody.auth_alg < NUM_AUTH_ALGS)
1626 ? auth_alg_text[pbody.auth_alg]
1627 : "Reserved",
1628 pbody.auth_trans_seq_num,
1629 (pbody.auth_trans_seq_num % 2)
1630 ? ((pbody.status_code < NUM_STATUSES)
1631 ? status_text[pbody.status_code]
1632 : "n/a")
1633 : "");
1634
1635 return ret;
1636 trunc:
1637 return 0;
1638 }
1639
1640 static int
1641 handle_deauth(netdissect_options *ndo,
1642 const uint8_t *src, const u_char *p, u_int length)
1643 {
1644 struct mgmt_body_t pbody;
1645 const char *reason = NULL;
1646
1647 memset(&pbody, 0, sizeof(pbody));
1648
1649 ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
1650 if (length < IEEE802_11_REASON_LEN)
1651 goto trunc;
1652 pbody.reason_code = GET_LE_U_2(p);
1653
1654 reason = (pbody.reason_code < NUM_REASONS)
1655 ? reason_text[pbody.reason_code]
1656 : "Reserved";
1657
1658 if (ndo->ndo_eflag) {
1659 ND_PRINT(": %s", reason);
1660 } else {
1661 ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
1662 }
1663 return 1;
1664 trunc:
1665 return 0;
1666 }
1667
1668 static const struct tok category_str[] = {
1669 { 0, "Spectrum Management" },
1670 { 1, "QoS" },
1671 { 2, "DLS" },
1672 { 3, "BA" },
1673 { 7, "HT" },
1674 { 13, "MeshAction" },
1675 { 14, "MultiohopAction" },
1676 { 15, "SelfprotectAction" },
1677 { 127, "Vendor" },
1678 { 0, NULL }
1679 };
1680
1681 static const struct tok act_ba_str[] = {
1682 { 0, "ADDBA Request" },
1683 { 1, "ADDBA Response" },
1684 { 2, "DELBA" },
1685 { 0, NULL }
1686 };
1687
1688 static const struct tok act_ht_str[] = {
1689 { 0, "TxChWidth" },
1690 { 1, "MIMOPwrSave" },
1691 { 0, NULL }
1692 };
1693
1694 static const struct tok act_mesh_str[] = {
1695 { 0, "MeshLink" },
1696 { 1, "HWMP" },
1697 { 2, "Gate Announcement" },
1698 { 3, "Congestion Control" },
1699 { 4, "MCCA Setup Request" },
1700 { 5, "MCCA Setup Reply" },
1701 { 6, "MCCA Advertisement Request" },
1702 { 7, "MCCA Advertisement" },
1703 { 8, "MCCA Teardown" },
1704 { 9, "TBTT Adjustment Request" },
1705 { 10, "TBTT Adjustment Response" },
1706 { 0, NULL }
1707 };
1708
1709 static const struct tok act_mhop_str[] = {
1710 { 0, "Proxy Update" },
1711 { 1, "Proxy Update Confirmation" },
1712 { 0, NULL }
1713 };
1714
1715 static const struct tok act_selfpr_str[] = {
1716 { 1, "Peering Open" },
1717 { 2, "Peering Confirm" },
1718 { 3, "Peering Close" },
1719 { 4, "Group Key Inform" },
1720 { 5, "Group Key Acknowledge" },
1721 { 0, NULL }
1722 };
1723
1724 static const struct uint_tokary category2tokary[] = {
1725 { 3, act_ba_str },
1726 { 7, act_ht_str },
1727 { 13, act_mesh_str },
1728 { 14, act_mhop_str },
1729 { 15, act_selfpr_str },
1730 /* uint2tokary() does not use array termination. */
1731 };
1732
1733 static int
1734 handle_action(netdissect_options *ndo,
1735 const uint8_t *src, const u_char *p, u_int length)
1736 {
1737 uint8_t category, action;
1738 const struct tok *action_str;
1739
1740 ND_TCHECK_2(p);
1741 if (length < 2)
1742 goto trunc;
1743 if (ndo->ndo_eflag) {
1744 ND_PRINT(": ");
1745 } else {
1746 ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
1747 }
1748 category = GET_U_1(p);
1749 ND_PRINT("%s ", tok2str(category_str, "Reserved(%u)", category));
1750 action = GET_U_1(p + 1);
1751 action_str = uint2tokary(category2tokary, category);
1752 if (!action_str)
1753 ND_PRINT("Act#%u", action);
1754 else
1755 ND_PRINT("%s", tok2str(action_str, "Act#%u", action));
1756
1757 return 1;
1758 trunc:
1759 return 0;
1760 }
1761
1762
1763 /*********************************************************************************
1764 * Print Body funcs
1765 *********************************************************************************/
1766
1767
1768 static int
1769 mgmt_body_print(netdissect_options *ndo,
1770 uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
1771 {
1772 ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
1773
1774 /* There may be a problem w/ AP not having this bit set */
1775 if (FC_PROTECTED(fc))
1776 return wep_print(ndo, p);
1777 switch (FC_SUBTYPE(fc)) {
1778 case ST_ASSOC_REQUEST:
1779 return handle_assoc_request(ndo, p, length);
1780 case ST_ASSOC_RESPONSE:
1781 return handle_assoc_response(ndo, p, length);
1782 case ST_REASSOC_REQUEST:
1783 return handle_reassoc_request(ndo, p, length);
1784 case ST_REASSOC_RESPONSE:
1785 return handle_reassoc_response(ndo, p, length);
1786 case ST_PROBE_REQUEST:
1787 return handle_probe_request(ndo, p, length);
1788 case ST_PROBE_RESPONSE:
1789 return handle_probe_response(ndo, p, length);
1790 case ST_BEACON:
1791 return handle_beacon(ndo, p, length);
1792 case ST_ATIM:
1793 return handle_atim();
1794 case ST_DISASSOC:
1795 return handle_disassoc(ndo, p, length);
1796 case ST_AUTH:
1797 return handle_auth(ndo, p, length);
1798 case ST_DEAUTH:
1799 return handle_deauth(ndo, src, p, length);
1800 case ST_ACTION:
1801 return handle_action(ndo, src, p, length);
1802 default:
1803 return 1;
1804 }
1805 }
1806
1807
1808 /*********************************************************************************
1809 * Handles printing all the control frame types
1810 *********************************************************************************/
1811
1812 static int
1813 ctrl_body_print(netdissect_options *ndo,
1814 uint16_t fc, const u_char *p)
1815 {
1816 ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
1817 switch (FC_SUBTYPE(fc)) {
1818 case CTRL_CONTROL_WRAPPER:
1819 /* XXX - requires special handling */
1820 break;
1821 case CTRL_BAR:
1822 ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
1823 if (!ndo->ndo_eflag)
1824 ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1825 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
1826 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
1827 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
1828 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
1829 break;
1830 case CTRL_BA:
1831 ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
1832 if (!ndo->ndo_eflag)
1833 ND_PRINT(" RA:%s ",
1834 GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
1835 break;
1836 case CTRL_PS_POLL:
1837 ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
1838 ND_PRINT(" AID(%x)",
1839 GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
1840 break;
1841 case CTRL_RTS:
1842 ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
1843 if (!ndo->ndo_eflag)
1844 ND_PRINT(" TA:%s ",
1845 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
1846 break;
1847 case CTRL_CTS:
1848 ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
1849 if (!ndo->ndo_eflag)
1850 ND_PRINT(" RA:%s ",
1851 GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
1852 break;
1853 case CTRL_ACK:
1854 ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
1855 if (!ndo->ndo_eflag)
1856 ND_PRINT(" RA:%s ",
1857 GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
1858 break;
1859 case CTRL_CF_END:
1860 ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
1861 if (!ndo->ndo_eflag)
1862 ND_PRINT(" RA:%s ",
1863 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
1864 break;
1865 case CTRL_END_ACK:
1866 ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
1867 if (!ndo->ndo_eflag)
1868 ND_PRINT(" RA:%s ",
1869 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
1870 break;
1871 }
1872 return 1;
1873 trunc:
1874 return 0;
1875 }
1876
1877 /*
1878 * Data Frame - Address field contents
1879 *
1880 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
1881 * 0 | 0 | DA | SA | BSSID | n/a
1882 * 0 | 1 | DA | BSSID | SA | n/a
1883 * 1 | 0 | BSSID | SA | DA | n/a
1884 * 1 | 1 | RA | TA | DA | SA
1885 */
1886
1887 /*
1888 * Function to get source and destination MAC addresses for a data frame.
1889 */
1890 static void
1891 get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
1892 const uint8_t **dstp)
1893 {
1894 #define ADDR1 (p + 4)
1895 #define ADDR2 (p + 10)
1896 #define ADDR3 (p + 16)
1897 #define ADDR4 (p + 24)
1898
1899 if (!FC_TO_DS(fc)) {
1900 if (!FC_FROM_DS(fc)) {
1901 /* not To DS and not From DS */
1902 *srcp = ADDR2;
1903 *dstp = ADDR1;
1904 } else {
1905 /* not To DS and From DS */
1906 *srcp = ADDR3;
1907 *dstp = ADDR1;
1908 }
1909 } else {
1910 if (!FC_FROM_DS(fc)) {
1911 /* From DS and not To DS */
1912 *srcp = ADDR2;
1913 *dstp = ADDR3;
1914 } else {
1915 /* To DS and From DS */
1916 *srcp = ADDR4;
1917 *dstp = ADDR3;
1918 }
1919 }
1920
1921 #undef ADDR1
1922 #undef ADDR2
1923 #undef ADDR3
1924 #undef ADDR4
1925 }
1926
1927 static void
1928 get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
1929 {
1930 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
1931
1932 if (srcp != NULL)
1933 *srcp = hp->sa;
1934 if (dstp != NULL)
1935 *dstp = hp->da;
1936 }
1937
1938 /*
1939 * Print Header funcs
1940 */
1941
1942 static void
1943 data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1944 {
1945 u_int subtype = FC_SUBTYPE(fc);
1946
1947 if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
1948 DATA_FRAME_IS_QOS(subtype)) {
1949 ND_PRINT("CF ");
1950 if (DATA_FRAME_IS_CF_ACK(subtype)) {
1951 if (DATA_FRAME_IS_CF_POLL(subtype))
1952 ND_PRINT("Ack/Poll");
1953 else
1954 ND_PRINT("Ack");
1955 } else {
1956 if (DATA_FRAME_IS_CF_POLL(subtype))
1957 ND_PRINT("Poll");
1958 }
1959 if (DATA_FRAME_IS_QOS(subtype))
1960 ND_PRINT("+QoS");
1961 ND_PRINT(" ");
1962 }
1963
1964 #define ADDR1 (p + 4)
1965 #define ADDR2 (p + 10)
1966 #define ADDR3 (p + 16)
1967 #define ADDR4 (p + 24)
1968
1969 if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1970 ND_PRINT("DA:%s SA:%s BSSID:%s ",
1971 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1972 GET_ETHERADDR_STRING(ADDR3));
1973 } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1974 ND_PRINT("DA:%s BSSID:%s SA:%s ",
1975 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1976 GET_ETHERADDR_STRING(ADDR3));
1977 } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1978 ND_PRINT("BSSID:%s SA:%s DA:%s ",
1979 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1980 GET_ETHERADDR_STRING(ADDR3));
1981 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1982 ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
1983 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1984 GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
1985 }
1986
1987 #undef ADDR1
1988 #undef ADDR2
1989 #undef ADDR3
1990 #undef ADDR4
1991 }
1992
1993 static void
1994 mgmt_header_print(netdissect_options *ndo, const u_char *p)
1995 {
1996 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
1997
1998 ND_PRINT("BSSID:%s DA:%s SA:%s ",
1999 GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
2000 GET_ETHERADDR_STRING((hp)->sa));
2001 }
2002
2003 static void
2004 ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
2005 {
2006 switch (FC_SUBTYPE(fc)) {
2007 case CTRL_BAR:
2008 ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
2009 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
2010 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
2011 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
2012 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
2013 break;
2014 case CTRL_BA:
2015 ND_PRINT("RA:%s ",
2016 GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
2017 break;
2018 case CTRL_PS_POLL:
2019 ND_PRINT("BSSID:%s TA:%s ",
2020 GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
2021 GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
2022 break;
2023 case CTRL_RTS:
2024 ND_PRINT("RA:%s TA:%s ",
2025 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
2026 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
2027 break;
2028 case CTRL_CTS:
2029 ND_PRINT("RA:%s ",
2030 GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
2031 break;
2032 case CTRL_ACK:
2033 ND_PRINT("RA:%s ",
2034 GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
2035 break;
2036 case CTRL_CF_END:
2037 ND_PRINT("RA:%s BSSID:%s ",
2038 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
2039 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
2040 break;
2041 case CTRL_END_ACK:
2042 ND_PRINT("RA:%s BSSID:%s ",
2043 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
2044 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
2045 break;
2046 default:
2047 /* We shouldn't get here - we should already have quit */
2048 break;
2049 }
2050 }
2051
2052 static int
2053 extract_header_length(netdissect_options *ndo,
2054 uint16_t fc)
2055 {
2056 int len;
2057
2058 switch (FC_TYPE(fc)) {
2059 case T_MGMT:
2060 return MGMT_HDRLEN;
2061 case T_CTRL:
2062 switch (FC_SUBTYPE(fc)) {
2063 case CTRL_CONTROL_WRAPPER:
2064 return CTRL_CONTROL_WRAPPER_HDRLEN;
2065 case CTRL_BAR:
2066 return CTRL_BAR_HDRLEN;
2067 case CTRL_BA:
2068 return CTRL_BA_HDRLEN;
2069 case CTRL_PS_POLL:
2070 return CTRL_PS_POLL_HDRLEN;
2071 case CTRL_RTS:
2072 return CTRL_RTS_HDRLEN;
2073 case CTRL_CTS:
2074 return CTRL_CTS_HDRLEN;
2075 case CTRL_ACK:
2076 return CTRL_ACK_HDRLEN;
2077 case CTRL_CF_END:
2078 return CTRL_END_HDRLEN;
2079 case CTRL_END_ACK:
2080 return CTRL_END_ACK_HDRLEN;
2081 default:
2082 ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
2083 return 0;
2084 }
2085 case T_DATA:
2086 len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
2087 if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
2088 len += 2;
2089 return len;
2090 default:
2091 ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
2092 return 0;
2093 }
2094 }
2095
2096 static int
2097 extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
2098 {
2099 return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
2100 }
2101
2102 /*
2103 * Print the 802.11 MAC header.
2104 */
2105 static void
2106 ieee_802_11_hdr_print(netdissect_options *ndo,
2107 uint16_t fc, const u_char *p, u_int hdrlen,
2108 u_int meshdrlen)
2109 {
2110 if (ndo->ndo_vflag) {
2111 if (FC_MORE_DATA(fc))
2112 ND_PRINT("More Data ");
2113 if (FC_MORE_FLAG(fc))
2114 ND_PRINT("More Fragments ");
2115 if (FC_POWER_MGMT(fc))
2116 ND_PRINT("Pwr Mgmt ");
2117 if (FC_RETRY(fc))
2118 ND_PRINT("Retry ");
2119 if (FC_ORDER(fc))
2120 ND_PRINT("Strictly Ordered ");
2121 if (FC_PROTECTED(fc))
2122 ND_PRINT("Protected ");
2123 if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
2124 ND_PRINT("%uus ",
2125 GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
2126 }
2127 if (meshdrlen != 0) {
2128 const struct meshcntl_t *mc =
2129 (const struct meshcntl_t *)(p + hdrlen - meshdrlen);
2130 u_int ae = GET_U_1(mc->flags) & 3;
2131
2132 ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
2133 GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
2134 if (ae > 0)
2135 ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
2136 if (ae > 1)
2137 ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
2138 if (ae > 2)
2139 ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
2140 ND_PRINT(") ");
2141 }
2142
2143 switch (FC_TYPE(fc)) {
2144 case T_MGMT:
2145 mgmt_header_print(ndo, p);
2146 break;
2147 case T_CTRL:
2148 ctrl_header_print(ndo, fc, p);
2149 break;
2150 case T_DATA:
2151 data_header_print(ndo, fc, p);
2152 break;
2153 default:
2154 break;
2155 }
2156 }
2157
2158 static u_int
2159 ieee802_11_print(netdissect_options *ndo,
2160 const u_char *p, u_int length, u_int orig_caplen, int pad,
2161 u_int fcslen)
2162 {
2163 uint16_t fc;
2164 u_int caplen, hdrlen, meshdrlen;
2165 struct lladdr_info src, dst;
2166 int llc_hdrlen;
2167
2168 ndo->ndo_protocol = "802.11";
2169 caplen = orig_caplen;
2170 /* Remove FCS, if present */
2171 if (length < fcslen) {
2172 nd_print_trunc(ndo);
2173 return caplen;
2174 }
2175 length -= fcslen;
2176 if (caplen > length) {
2177 /* Amount of FCS in actual packet data, if any */
2178 fcslen = caplen - length;
2179 caplen -= fcslen;
2180 ndo->ndo_snapend -= fcslen;
2181 }
2182
2183 if (caplen < IEEE802_11_FC_LEN) {
2184 nd_print_trunc(ndo);
2185 return orig_caplen;
2186 }
2187
2188 fc = GET_LE_U_2(p);
2189 hdrlen = extract_header_length(ndo, fc);
2190 if (hdrlen == 0) {
2191 /* Unknown frame type or control frame subtype; quit. */
2192 return (0);
2193 }
2194 if (pad)
2195 hdrlen = roundup2(hdrlen, 4);
2196 if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
2197 DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
2198 if(!ND_TTEST_1(p + hdrlen)) {
2199 nd_print_trunc(ndo);
2200 return hdrlen;
2201 }
2202 meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
2203 hdrlen += meshdrlen;
2204 } else
2205 meshdrlen = 0;
2206
2207 if (caplen < hdrlen) {
2208 nd_print_trunc(ndo);
2209 return hdrlen;
2210 }
2211
2212 if (ndo->ndo_eflag)
2213 ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
2214
2215 /*
2216 * Go past the 802.11 header.
2217 */
2218 length -= hdrlen;
2219 caplen -= hdrlen;
2220 p += hdrlen;
2221
2222 src.addr_string = etheraddr_string;
2223 dst.addr_string = etheraddr_string;
2224 switch (FC_TYPE(fc)) {
2225 case T_MGMT:
2226 get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
2227 if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
2228 nd_print_trunc(ndo);
2229 return hdrlen;
2230 }
2231 break;
2232 case T_CTRL:
2233 if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
2234 nd_print_trunc(ndo);
2235 return hdrlen;
2236 }
2237 break;
2238 case T_DATA:
2239 if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
2240 return hdrlen; /* no-data frame */
2241 /* There may be a problem w/ AP not having this bit set */
2242 if (FC_PROTECTED(fc)) {
2243 ND_PRINT("Data");
2244 if (!wep_print(ndo, p)) {
2245 nd_print_trunc(ndo);
2246 return hdrlen;
2247 }
2248 } else {
2249 get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
2250 llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
2251 if (llc_hdrlen < 0) {
2252 /*
2253 * Some kinds of LLC packet we cannot
2254 * handle intelligently
2255 */
2256 if (!ndo->ndo_suppress_default_print)
2257 ND_DEFAULTPRINT(p, caplen);
2258 llc_hdrlen = -llc_hdrlen;
2259 }
2260 hdrlen += llc_hdrlen;
2261 }
2262 break;
2263 default:
2264 /* We shouldn't get here - we should already have quit */
2265 break;
2266 }
2267
2268 return hdrlen;
2269 }
2270
2271 /*
2272 * This is the top level routine of the printer. 'p' points
2273 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
2274 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
2275 * is the number of bytes actually captured.
2276 */
2277 void
2278 ieee802_11_if_print(netdissect_options *ndo,
2279 const struct pcap_pkthdr *h, const u_char *p)
2280 {
2281 ndo->ndo_protocol = "802.11";
2282 ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
2283 }
2284
2285
2286 /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
2287 /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */
2288
2289 /*-
2290 * Copyright (c) 2003, 2004 David Young. All rights reserved.
2291 *
2292 * Redistribution and use in source and binary forms, with or without
2293 * modification, are permitted provided that the following conditions
2294 * are met:
2295 * 1. Redistributions of source code must retain the above copyright
2296 * notice, this list of conditions and the following disclaimer.
2297 * 2. Redistributions in binary form must reproduce the above copyright
2298 * notice, this list of conditions and the following disclaimer in the
2299 * documentation and/or other materials provided with the distribution.
2300 * 3. The name of David Young may not be used to endorse or promote
2301 * products derived from this software without specific prior
2302 * written permission.
2303 *
2304 * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
2305 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2306 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2307 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
2308 * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2309 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2310 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2312 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2313 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2314 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2315 * OF SUCH DAMAGE.
2316 */
2317
2318 /* A generic radio capture format is desirable. It must be
2319 * rigidly defined (e.g., units for fields should be given),
2320 * and easily extensible.
2321 *
2322 * The following is an extensible radio capture format. It is
2323 * based on a bitmap indicating which fields are present.
2324 *
2325 * I am trying to describe precisely what the application programmer
2326 * should expect in the following, and for that reason I tell the
2327 * units and origin of each measurement (where it applies), or else I
2328 * use sufficiently weaselly language ("is a monotonically nondecreasing
2329 * function of...") that I cannot set false expectations for lawyerly
2330 * readers.
2331 */
2332
2333 /*
2334 * The radio capture header precedes the 802.11 header.
2335 *
2336 * Note well: all radiotap fields are little-endian.
2337 */
2338 struct ieee80211_radiotap_header {
2339 nd_uint8_t it_version; /* Version 0. Only increases
2340 * for drastic changes,
2341 * introduction of compatible
2342 * new fields does not count.
2343 */
2344 nd_uint8_t it_pad;
2345 nd_uint16_t it_len; /* length of the whole
2346 * header in bytes, including
2347 * it_version, it_pad,
2348 * it_len, and data fields.
2349 */
2350 nd_uint32_t it_present; /* A bitmap telling which
2351 * fields are present. Set bit 31
2352 * (0x80000000) to extend the
2353 * bitmap by another 32 bits.
2354 * Additional extensions are made
2355 * by setting bit 31.
2356 */
2357 };
2358
2359 /* Name Data type Units
2360 * ---- --------- -----
2361 *
2362 * IEEE80211_RADIOTAP_TSFT uint64_t microseconds
2363 *
2364 * Value in microseconds of the MAC's 64-bit 802.11 Time
2365 * Synchronization Function timer when the first bit of the
2366 * MPDU arrived at the MAC. For received frames, only.
2367 *
2368 * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
2369 *
2370 * Tx/Rx frequency in MHz, followed by flags (see below).
2371 * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
2372 * represent an HT channel as there is not enough room in
2373 * the flags word.
2374 *
2375 * IEEE80211_RADIOTAP_FHSS uint16_t see below
2376 *
2377 * For frequency-hopping radios, the hop set (first byte)
2378 * and pattern (second byte).
2379 *
2380 * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index
2381 *
2382 * Tx/Rx data rate. If bit 0x80 is set then it represents an
2383 * an MCS index and not an IEEE rate.
2384 *
2385 * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
2386 * one milliwatt (dBm)
2387 *
2388 * RF signal power at the antenna, decibel difference from
2389 * one milliwatt.
2390 *
2391 * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from
2392 * one milliwatt (dBm)
2393 *
2394 * RF noise power at the antenna, decibel difference from one
2395 * milliwatt.
2396 *
2397 * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
2398 *
2399 * RF signal power at the antenna, decibel difference from an
2400 * arbitrary, fixed reference.
2401 *
2402 * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
2403 *
2404 * RF noise power at the antenna, decibel difference from an
2405 * arbitrary, fixed reference point.
2406 *
2407 * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
2408 *
2409 * Quality of Barker code lock. Unitless. Monotonically
2410 * nondecreasing with "better" lock strength. Called "Signal
2411 * Quality" in datasheets. (Is there a standard way to measure
2412 * this?)
2413 *
2414 * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
2415 *
2416 * Transmit power expressed as unitless distance from max
2417 * power set at factory calibration. 0 is max power.
2418 * Monotonically nondecreasing with lower power levels.
2419 *
2420 * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
2421 *
2422 * Transmit power expressed as decibel distance from max power
2423 * set at factory calibration. 0 is max power. Monotonically
2424 * nondecreasing with lower power levels.
2425 *
2426 * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from
2427 * one milliwatt (dBm)
2428 *
2429 * Transmit power expressed as dBm (decibels from a 1 milliwatt
2430 * reference). This is the absolute power level measured at
2431 * the antenna port.
2432 *
2433 * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
2434 *
2435 * Properties of transmitted and received frames. See flags
2436 * defined below.
2437 *
2438 * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
2439 *
2440 * Unitless indication of the Rx/Tx antenna for this packet.
2441 * The first antenna is antenna 0.
2442 *
2443 * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
2444 *
2445 * Properties of received frames. See flags defined below.
2446 *
2447 * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap
2448 * uint16_t MHz
2449 * uint8_t channel number
2450 * uint8_t .5 dBm
2451 *
2452 * Extended channel specification: flags (see below) followed by
2453 * frequency in MHz, the corresponding IEEE channel number, and
2454 * finally the maximum regulatory transmit power cap in .5 dBm
2455 * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL
2456 * and only one of the two should be present.
2457 *
2458 * IEEE80211_RADIOTAP_MCS uint8_t known
2459 * uint8_t flags
2460 * uint8_t mcs
2461 *
2462 * Bitset indicating which fields have known values, followed
2463 * by bitset of flag values, followed by the MCS rate index as
2464 * in IEEE 802.11n.
2465 *
2466 *
2467 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
2468 *
2469 * Contains the AMPDU information for the subframe.
2470 *
2471 * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
2472 *
2473 * Contains VHT information about this frame.
2474 *
2475 * IEEE80211_RADIOTAP_VENDOR_NAMESPACE
2476 * uint8_t OUI[3]
2477 * uint8_t subspace
2478 * uint16_t length
2479 *
2480 * The Vendor Namespace Field contains three sub-fields. The first
2481 * sub-field is 3 bytes long. It contains the vendor's IEEE 802
2482 * Organizationally Unique Identifier (OUI). The fourth byte is a
2483 * vendor-specific "namespace selector."
2484 *
2485 */
2486 enum ieee80211_radiotap_type {
2487 IEEE80211_RADIOTAP_TSFT = 0,
2488 IEEE80211_RADIOTAP_FLAGS = 1,
2489 IEEE80211_RADIOTAP_RATE = 2,
2490 IEEE80211_RADIOTAP_CHANNEL = 3,
2491 IEEE80211_RADIOTAP_FHSS = 4,
2492 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
2493 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
2494 IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
2495 IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
2496 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
2497 IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
2498 IEEE80211_RADIOTAP_ANTENNA = 11,
2499 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
2500 IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
2501 IEEE80211_RADIOTAP_RX_FLAGS = 14,
2502 /* NB: gap for netbsd definitions */
2503 IEEE80211_RADIOTAP_XCHANNEL = 18,
2504 IEEE80211_RADIOTAP_MCS = 19,
2505 IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
2506 IEEE80211_RADIOTAP_VHT = 21,
2507 IEEE80211_RADIOTAP_NAMESPACE = 29,
2508 IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
2509 IEEE80211_RADIOTAP_EXT = 31
2510 };
2511
2512 /* channel attributes */
2513 #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */
2514 #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */
2515 #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */
2516 #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */
2517 #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */
2518 #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */
2519 #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */
2520 #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */
2521 #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */
2522 #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */
2523 #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */
2524 #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */
2525 #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */
2526 #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */
2527 #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */
2528
2529 /* Useful combinations of channel characteristics, borrowed from Ethereal */
2530 #define IEEE80211_CHAN_A \
2531 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2532 #define IEEE80211_CHAN_B \
2533 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2534 #define IEEE80211_CHAN_G \
2535 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2536 #define IEEE80211_CHAN_TA \
2537 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
2538 #define IEEE80211_CHAN_TG \
2539 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO)
2540
2541
2542 /* For IEEE80211_RADIOTAP_FLAGS */
2543 #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
2544 * during CFP
2545 */
2546 #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
2547 * with short
2548 * preamble
2549 */
2550 #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
2551 * with WEP encryption
2552 */
2553 #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
2554 * with fragmentation
2555 */
2556 #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
2557 #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
2558 * 802.11 header and payload
2559 * (to 32-bit boundary)
2560 */
2561 #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */
2562
2563 /* For IEEE80211_RADIOTAP_RX_FLAGS */
2564 #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
2565 #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */
2566
2567 /* For IEEE80211_RADIOTAP_MCS known */
2568 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01
2569 #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */
2570 #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04
2571 #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08
2572 #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10
2573 #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20
2574 #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40
2575 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80
2576
2577 /* For IEEE80211_RADIOTAP_MCS flags */
2578 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03
2579 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0
2580 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1
2581 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2
2582 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3
2583 #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */
2584 #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08
2585 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
2586 #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
2587 #define IEEE80211_RADIOTAP_MCS_STBC_1 1
2588 #define IEEE80211_RADIOTAP_MCS_STBC_2 2
2589 #define IEEE80211_RADIOTAP_MCS_STBC_3 3
2590 #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
2591 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80
2592
2593 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
2594 #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
2595 #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
2596 #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
2597 #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
2598 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
2599 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
2600
2601 /* For IEEE80211_RADIOTAP_VHT known */
2602 #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001
2603 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002
2604 #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004
2605 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008
2606 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010
2607 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020
2608 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040
2609 #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080
2610 #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100
2611
2612 /* For IEEE80211_RADIOTAP_VHT flags */
2613 #define IEEE80211_RADIOTAP_VHT_STBC 0x01
2614 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02
2615 #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04
2616 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08
2617 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10
2618 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20
2619
2620 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f
2621
2622 #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f
2623 #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0
2624 #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4
2625
2626 #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01
2627
2628 #define IEEE80211_CHAN_FHSS \
2629 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
2630 #define IEEE80211_CHAN_A \
2631 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2632 #define IEEE80211_CHAN_B \
2633 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2634 #define IEEE80211_CHAN_PUREG \
2635 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
2636 #define IEEE80211_CHAN_G \
2637 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2638
2639 #define IS_CHAN_FHSS(flags) \
2640 ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
2641 #define IS_CHAN_A(flags) \
2642 ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
2643 #define IS_CHAN_B(flags) \
2644 ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
2645 #define IS_CHAN_PUREG(flags) \
2646 ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
2647 #define IS_CHAN_G(flags) \
2648 ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
2649 #define IS_CHAN_ANYG(flags) \
2650 (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
2651
2652 static void
2653 print_chaninfo(netdissect_options *ndo,
2654 uint16_t freq, uint32_t flags, uint32_t presentflags)
2655 {
2656 ND_PRINT("%u MHz", freq);
2657 if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
2658 /*
2659 * We have the MCS field, so this is 11n, regardless
2660 * of what the channel flags say.
2661 */
2662 ND_PRINT(" 11n");
2663 } else {
2664 if (IS_CHAN_FHSS(flags))
2665 ND_PRINT(" FHSS");
2666 if (IS_CHAN_A(flags)) {
2667 if (flags & IEEE80211_CHAN_HALF)
2668 ND_PRINT(" 11a/10Mhz");
2669 else if (flags & IEEE80211_CHAN_QUARTER)
2670 ND_PRINT(" 11a/5Mhz");
2671 else
2672 ND_PRINT(" 11a");
2673 }
2674 if (IS_CHAN_ANYG(flags)) {
2675 if (flags & IEEE80211_CHAN_HALF)
2676 ND_PRINT(" 11g/10Mhz");
2677 else if (flags & IEEE80211_CHAN_QUARTER)
2678 ND_PRINT(" 11g/5Mhz");
2679 else
2680 ND_PRINT(" 11g");
2681 } else if (IS_CHAN_B(flags))
2682 ND_PRINT(" 11b");
2683 if (flags & IEEE80211_CHAN_TURBO)
2684 ND_PRINT(" Turbo");
2685 }
2686 /*
2687 * These apply to 11n.
2688 */
2689 if (flags & IEEE80211_CHAN_HT20)
2690 ND_PRINT(" ht/20");
2691 else if (flags & IEEE80211_CHAN_HT40D)
2692 ND_PRINT(" ht/40-");
2693 else if (flags & IEEE80211_CHAN_HT40U)
2694 ND_PRINT(" ht/40+");
2695 ND_PRINT(" ");
2696 }
2697
2698 static int
2699 print_radiotap_field(netdissect_options *ndo,
2700 struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
2701 uint32_t presentflags)
2702 {
2703 u_int i;
2704 int rc;
2705
2706 switch (bit) {
2707
2708 case IEEE80211_RADIOTAP_TSFT: {
2709 uint64_t tsft;
2710
2711 rc = nd_cpack_uint64(ndo, s, &tsft);
2712 if (rc != 0)
2713 goto trunc;
2714 ND_PRINT("%" PRIu64 "us tsft ", tsft);
2715 break;
2716 }
2717
2718 case IEEE80211_RADIOTAP_FLAGS: {
2719 uint8_t flagsval;
2720
2721 rc = nd_cpack_uint8(ndo, s, &flagsval);
2722 if (rc != 0)
2723 goto trunc;
2724 *flagsp = flagsval;
2725 if (flagsval & IEEE80211_RADIOTAP_F_CFP)
2726 ND_PRINT("cfp ");
2727 if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
2728 ND_PRINT("short preamble ");
2729 if (flagsval & IEEE80211_RADIOTAP_F_WEP)
2730 ND_PRINT("wep ");
2731 if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
2732 ND_PRINT("fragmented ");
2733 if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
2734 ND_PRINT("bad-fcs ");
2735 break;
2736 }
2737
2738 case IEEE80211_RADIOTAP_RATE: {
2739 uint8_t rate;
2740
2741 rc = nd_cpack_uint8(ndo, s, &rate);
2742 if (rc != 0)
2743 goto trunc;
2744 /*
2745 * XXX On FreeBSD rate & 0x80 means we have an MCS. On
2746 * Linux and AirPcap it does not. (What about
2747 * macOS, NetBSD, OpenBSD, and DragonFly BSD?)
2748 *
2749 * This is an issue either for proprietary extensions
2750 * to 11a or 11g, which do exist, or for 11n
2751 * implementations that stuff a rate value into
2752 * this field, which also appear to exist.
2753 *
2754 * We currently handle that by assuming that
2755 * if the 0x80 bit is set *and* the remaining
2756 * bits have a value between 0 and 15 it's
2757 * an MCS value, otherwise it's a rate. If
2758 * there are cases where systems that use
2759 * "0x80 + MCS index" for MCS indices > 15,
2760 * or stuff a rate value here between 64 and
2761 * 71.5 Mb/s in here, we'll need a preference
2762 * setting. Such rates do exist, e.g. 11n
2763 * MCS 7 at 20 MHz with a long guard interval.
2764 */
2765 if (rate >= 0x80 && rate <= 0x8f) {
2766 /*
2767 * XXX - we don't know the channel width
2768 * or guard interval length, so we can't
2769 * convert this to a data rate.
2770 *
2771 * If you want us to show a data rate,
2772 * use the MCS field, not the Rate field;
2773 * the MCS field includes not only the
2774 * MCS index, it also includes bandwidth
2775 * and guard interval information.
2776 *
2777 * XXX - can we get the channel width
2778 * from XChannel and the guard interval
2779 * information from Flags, at least on
2780 * FreeBSD?
2781 */
2782 ND_PRINT("MCS %u ", rate & 0x7f);
2783 } else
2784 ND_PRINT("%2.1f Mb/s ", .5 * rate);
2785 break;
2786 }
2787
2788 case IEEE80211_RADIOTAP_CHANNEL: {
2789 uint16_t frequency;
2790 uint16_t flags;
2791
2792 rc = nd_cpack_uint16(ndo, s, &frequency);
2793 if (rc != 0)
2794 goto trunc;
2795 rc = nd_cpack_uint16(ndo, s, &flags);
2796 if (rc != 0)
2797 goto trunc;
2798 /*
2799 * If CHANNEL and XCHANNEL are both present, skip
2800 * CHANNEL.
2801 */
2802 if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
2803 break;
2804 print_chaninfo(ndo, frequency, flags, presentflags);
2805 break;
2806 }
2807
2808 case IEEE80211_RADIOTAP_FHSS: {
2809 uint8_t hopset;
2810 uint8_t hoppat;
2811
2812 rc = nd_cpack_uint8(ndo, s, &hopset);
2813 if (rc != 0)
2814 goto trunc;
2815 rc = nd_cpack_uint8(ndo, s, &hoppat);
2816 if (rc != 0)
2817 goto trunc;
2818 ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
2819 break;
2820 }
2821
2822 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
2823 int8_t dbm_antsignal;
2824
2825 rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
2826 if (rc != 0)
2827 goto trunc;
2828 ND_PRINT("%ddBm signal ", dbm_antsignal);
2829 break;
2830 }
2831
2832 case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
2833 int8_t dbm_antnoise;
2834
2835 rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
2836 if (rc != 0)
2837 goto trunc;
2838 ND_PRINT("%ddBm noise ", dbm_antnoise);
2839 break;
2840 }
2841
2842 case IEEE80211_RADIOTAP_LOCK_QUALITY: {
2843 uint16_t lock_quality;
2844
2845 rc = nd_cpack_uint16(ndo, s, &lock_quality);
2846 if (rc != 0)
2847 goto trunc;
2848 ND_PRINT("%u sq ", lock_quality);
2849 break;
2850 }
2851
2852 case IEEE80211_RADIOTAP_TX_ATTENUATION: {
2853 int16_t tx_attenuation;
2854
2855 rc = nd_cpack_int16(ndo, s, &tx_attenuation);
2856 if (rc != 0)
2857 goto trunc;
2858 ND_PRINT("%d tx power ", -tx_attenuation);
2859 break;
2860 }
2861
2862 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
2863 int8_t db_tx_attenuation;
2864
2865 rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
2866 if (rc != 0)
2867 goto trunc;
2868 ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
2869 break;
2870 }
2871
2872 case IEEE80211_RADIOTAP_DBM_TX_POWER: {
2873 int8_t dbm_tx_power;
2874
2875 rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
2876 if (rc != 0)
2877 goto trunc;
2878 ND_PRINT("%ddBm tx power ", dbm_tx_power);
2879 break;
2880 }
2881
2882 case IEEE80211_RADIOTAP_ANTENNA: {
2883 uint8_t antenna;
2884
2885 rc = nd_cpack_uint8(ndo, s, &antenna);
2886 if (rc != 0)
2887 goto trunc;
2888 ND_PRINT("antenna %u ", antenna);
2889 break;
2890 }
2891
2892 case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
2893 uint8_t db_antsignal;
2894
2895 rc = nd_cpack_uint8(ndo, s, &db_antsignal);
2896 if (rc != 0)
2897 goto trunc;
2898 ND_PRINT("%udB signal ", db_antsignal);
2899 break;
2900 }
2901
2902 case IEEE80211_RADIOTAP_DB_ANTNOISE: {
2903 uint8_t db_antnoise;
2904
2905 rc = nd_cpack_uint8(ndo, s, &db_antnoise);
2906 if (rc != 0)
2907 goto trunc;
2908 ND_PRINT("%udB noise ", db_antnoise);
2909 break;
2910 }
2911
2912 case IEEE80211_RADIOTAP_RX_FLAGS: {
2913 uint16_t rx_flags;
2914
2915 rc = nd_cpack_uint16(ndo, s, &rx_flags);
2916 if (rc != 0)
2917 goto trunc;
2918 /* Do nothing for now */
2919 break;
2920 }
2921
2922 case IEEE80211_RADIOTAP_XCHANNEL: {
2923 uint32_t flags;
2924 uint16_t frequency;
2925 uint8_t channel;
2926 uint8_t maxpower;
2927
2928 rc = nd_cpack_uint32(ndo, s, &flags);
2929 if (rc != 0)
2930 goto trunc;
2931 rc = nd_cpack_uint16(ndo, s, &frequency);
2932 if (rc != 0)
2933 goto trunc;
2934 rc = nd_cpack_uint8(ndo, s, &channel);
2935 if (rc != 0)
2936 goto trunc;
2937 rc = nd_cpack_uint8(ndo, s, &maxpower);
2938 if (rc != 0)
2939 goto trunc;
2940 print_chaninfo(ndo, frequency, flags, presentflags);
2941 break;
2942 }
2943
2944 case IEEE80211_RADIOTAP_MCS: {
2945 uint8_t known;
2946 uint8_t flags;
2947 uint8_t mcs_index;
2948 static const char *ht_bandwidth[4] = {
2949 "20 MHz",
2950 "40 MHz",
2951 "20 MHz (L)",
2952 "20 MHz (U)"
2953 };
2954 float htrate;
2955
2956 rc = nd_cpack_uint8(ndo, s, &known);
2957 if (rc != 0)
2958 goto trunc;
2959 rc = nd_cpack_uint8(ndo, s, &flags);
2960 if (rc != 0)
2961 goto trunc;
2962 rc = nd_cpack_uint8(ndo, s, &mcs_index);
2963 if (rc != 0)
2964 goto trunc;
2965 if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
2966 /*
2967 * We know the MCS index.
2968 */
2969 if (mcs_index <= MAX_MCS_INDEX) {
2970 /*
2971 * And it's in-range.
2972 */
2973 if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
2974 /*
2975 * And we know both the bandwidth and
2976 * the guard interval, so we can look
2977 * up the rate.
2978 */
2979 htrate =
2980 ieee80211_float_htrates
2981 [mcs_index]
2982 [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
2983 [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
2984 } else {
2985 /*
2986 * We don't know both the bandwidth
2987 * and the guard interval, so we can
2988 * only report the MCS index.
2989 */
2990 htrate = 0.0;
2991 }
2992 } else {
2993 /*
2994 * The MCS value is out of range.
2995 */
2996 htrate = 0.0;
2997 }
2998 if (htrate != 0.0) {
2999 /*
3000 * We have the rate.
3001 * Print it.
3002 */
3003 ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
3004 } else {
3005 /*
3006 * We at least have the MCS index.
3007 * Print it.
3008 */
3009 ND_PRINT("MCS %u ", mcs_index);
3010 }
3011 }
3012 if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
3013 ND_PRINT("%s ",
3014 ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
3015 }
3016 if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
3017 ND_PRINT("%s GI ",
3018 (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
3019 "short" : "long");
3020 }
3021 if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
3022 ND_PRINT("%s ",
3023 (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
3024 "greenfield" : "mixed");
3025 }
3026 if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
3027 ND_PRINT("%s FEC ",
3028 (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
3029 "LDPC" : "BCC");
3030 }
3031 if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
3032 ND_PRINT("RX-STBC%u ",
3033 (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
3034 }
3035 break;
3036 }
3037
3038 case IEEE80211_RADIOTAP_AMPDU_STATUS: {
3039 uint32_t reference_num;
3040 uint16_t flags;
3041 uint8_t delim_crc;
3042 uint8_t reserved;
3043
3044 rc = nd_cpack_uint32(ndo, s, &reference_num);
3045 if (rc != 0)
3046 goto trunc;
3047 rc = nd_cpack_uint16(ndo, s, &flags);
3048 if (rc != 0)
3049 goto trunc;
3050 rc = nd_cpack_uint8(ndo, s, &delim_crc);
3051 if (rc != 0)
3052 goto trunc;
3053 rc = nd_cpack_uint8(ndo, s, &reserved);
3054 if (rc != 0)
3055 goto trunc;
3056 /* Do nothing for now */
3057 break;
3058 }
3059
3060 case IEEE80211_RADIOTAP_VHT: {
3061 uint16_t known;
3062 uint8_t flags;
3063 uint8_t bandwidth;
3064 uint8_t mcs_nss[4];
3065 uint8_t coding;
3066 uint8_t group_id;
3067 uint16_t partial_aid;
3068 static const char *vht_bandwidth[32] = {
3069 "20 MHz",
3070 "40 MHz",
3071 "20 MHz (L)",
3072 "20 MHz (U)",
3073 "80 MHz",
3074 "80 MHz (L)",
3075 "80 MHz (U)",
3076 "80 MHz (LL)",
3077 "80 MHz (LU)",
3078 "80 MHz (UL)",
3079 "80 MHz (UU)",
3080 "160 MHz",
3081 "160 MHz (L)",
3082 "160 MHz (U)",
3083 "160 MHz (LL)",
3084 "160 MHz (LU)",
3085 "160 MHz (UL)",
3086 "160 MHz (UU)",
3087 "160 MHz (LLL)",
3088 "160 MHz (LLU)",
3089 "160 MHz (LUL)",
3090 "160 MHz (UUU)",
3091 "160 MHz (ULL)",
3092 "160 MHz (ULU)",
3093 "160 MHz (UUL)",
3094 "160 MHz (UUU)",
3095 "unknown (26)",
3096 "unknown (27)",
3097 "unknown (28)",
3098 "unknown (29)",
3099 "unknown (30)",
3100 "unknown (31)"
3101 };
3102
3103 rc = nd_cpack_uint16(ndo, s, &known);
3104 if (rc != 0)
3105 goto trunc;
3106 rc = nd_cpack_uint8(ndo, s, &flags);
3107 if (rc != 0)
3108 goto trunc;
3109 rc = nd_cpack_uint8(ndo, s, &bandwidth);
3110 if (rc != 0)
3111 goto trunc;
3112 for (i = 0; i < 4; i++) {
3113 rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
3114 if (rc != 0)
3115 goto trunc;
3116 }
3117 rc = nd_cpack_uint8(ndo, s, &coding);
3118 if (rc != 0)
3119 goto trunc;
3120 rc = nd_cpack_uint8(ndo, s, &group_id);
3121 if (rc != 0)
3122 goto trunc;
3123 rc = nd_cpack_uint16(ndo, s, &partial_aid);
3124 if (rc != 0)
3125 goto trunc;
3126 for (i = 0; i < 4; i++) {
3127 u_int nss, mcs;
3128 nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
3129 mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
3130
3131 if (nss == 0)
3132 continue;
3133
3134 ND_PRINT("User %u MCS %u ", i, mcs);
3135 ND_PRINT("%s FEC ",
3136 (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
3137 "LDPC" : "BCC");
3138 }
3139 if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
3140 ND_PRINT("%s ",
3141 vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
3142 }
3143 if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
3144 ND_PRINT("%s GI ",
3145 (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
3146 "short" : "long");
3147 }
3148 break;
3149 }
3150
3151 default:
3152 /* this bit indicates a field whose
3153 * size we do not know, so we cannot
3154 * proceed. Just print the bit number.
3155 */
3156 ND_PRINT("[bit %u] ", bit);
3157 return -1;
3158 }
3159
3160 return 0;
3161
3162 trunc:
3163 nd_print_trunc(ndo);
3164 return rc;
3165 }
3166
3167
3168 static int
3169 print_in_radiotap_namespace(netdissect_options *ndo,
3170 struct cpack_state *s, uint8_t *flags,
3171 uint32_t presentflags, int bit0)
3172 {
3173 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
3174 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
3175 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
3176 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
3177 #define BITNO_2(x) (((x) & 2) ? 1 : 0)
3178 uint32_t present, next_present;
3179 int bitno;
3180 enum ieee80211_radiotap_type bit;
3181 int rc;
3182
3183 for (present = presentflags; present; present = next_present) {
3184 /*
3185 * Clear the least significant bit that is set.
3186 */
3187 next_present = present & (present - 1);
3188
3189 /*
3190 * Get the bit number, within this presence word,
3191 * of the remaining least significant bit that
3192 * is set.
3193 */
3194 bitno = BITNO_32(present ^ next_present);
3195
3196 /*
3197 * Stop if this is one of the "same meaning
3198 * in all presence flags" bits.
3199 */
3200 if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
3201 break;
3202
3203 /*
3204 * Get the radiotap bit number of that bit.
3205 */
3206 bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
3207
3208 rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
3209 if (rc != 0)
3210 return rc;
3211 }
3212
3213 return 0;
3214 }
3215
3216 u_int
3217 ieee802_11_radio_print(netdissect_options *ndo,
3218 const u_char *p, u_int length, u_int caplen)
3219 {
3220 #define BIT(n) (1U << n)
3221 #define IS_EXTENDED(__p) \
3222 (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
3223
3224 struct cpack_state cpacker;
3225 const struct ieee80211_radiotap_header *hdr;
3226 uint32_t presentflags;
3227 const nd_uint32_t *presentp, *last_presentp;
3228 int vendor_namespace;
3229 uint8_t vendor_oui[3];
3230 uint8_t vendor_subnamespace;
3231 uint16_t skip_length;
3232 int bit0;
3233 u_int len;
3234 uint8_t flags;
3235 int pad;
3236 u_int fcslen;
3237
3238 ndo->ndo_protocol = "802.11_radio";
3239 if (caplen < sizeof(*hdr)) {
3240 nd_print_trunc(ndo);
3241 return caplen;
3242 }
3243
3244 hdr = (const struct ieee80211_radiotap_header *)p;
3245
3246 len = GET_LE_U_2(hdr->it_len);
3247 if (len < sizeof(*hdr)) {
3248 /*
3249 * The length is the length of the entire header, so
3250 * it must be as large as the fixed-length part of
3251 * the header.
3252 */
3253 nd_print_trunc(ndo);
3254 return caplen;
3255 }
3256
3257 /*
3258 * If we don't have the entire radiotap header, just give up.
3259 */
3260 if (caplen < len) {
3261 nd_print_trunc(ndo);
3262 return caplen;
3263 }
3264 nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
3265 nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
3266 for (last_presentp = &hdr->it_present;
3267 (const u_char*)(last_presentp + 1) <= p + len &&
3268 IS_EXTENDED(last_presentp);
3269 last_presentp++)
3270 nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
3271
3272 /* are there more bitmap extensions than bytes in header? */
3273 if ((const u_char*)(last_presentp + 1) > p + len) {
3274 nd_print_trunc(ndo);
3275 return caplen;
3276 }
3277
3278 /*
3279 * Start out at the beginning of the default radiotap namespace.
3280 */
3281 bit0 = 0;
3282 vendor_namespace = 0;
3283 memset(vendor_oui, 0, 3);
3284 vendor_subnamespace = 0;
3285 skip_length = 0;
3286 /* Assume no flags */
3287 flags = 0;
3288 /* Assume no Atheros padding between 802.11 header and body */
3289 pad = 0;
3290 /* Assume no FCS at end of frame */
3291 fcslen = 0;
3292 for (presentp = &hdr->it_present; presentp <= last_presentp;
3293 presentp++) {
3294 presentflags = GET_LE_U_4(presentp);
3295
3296 /*
3297 * If this is a vendor namespace, we don't handle it.
3298 */
3299 if (vendor_namespace) {
3300 /*
3301 * Skip past the stuff we don't understand.
3302 * If we add support for any vendor namespaces,
3303 * it'd be added here; use vendor_oui and
3304 * vendor_subnamespace to interpret the fields.
3305 */
3306 if (nd_cpack_advance(&cpacker, skip_length) != 0) {
3307 /*
3308 * Ran out of space in the packet.
3309 */
3310 break;
3311 }
3312
3313 /*
3314 * We've skipped it all; nothing more to
3315 * skip.
3316 */
3317 skip_length = 0;
3318 } else {
3319 if (print_in_radiotap_namespace(ndo, &cpacker,
3320 &flags, presentflags, bit0) != 0) {
3321 /*
3322 * Fatal error - can't process anything
3323 * more in the radiotap header.
3324 */
3325 break;
3326 }
3327 }
3328
3329 /*
3330 * Handle the namespace switch bits; we've already handled
3331 * the extension bit in all but the last word above.
3332 */
3333 switch (presentflags &
3334 (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
3335
3336 case 0:
3337 /*
3338 * We're not changing namespaces.
3339 * advance to the next 32 bits in the current
3340 * namespace.
3341 */
3342 bit0 += 32;
3343 break;
3344
3345 case BIT(IEEE80211_RADIOTAP_NAMESPACE):
3346 /*
3347 * We're switching to the radiotap namespace.
3348 * Reset the presence-bitmap index to 0, and
3349 * reset the namespace to the default radiotap
3350 * namespace.
3351 */
3352 bit0 = 0;
3353 vendor_namespace = 0;
3354 memset(vendor_oui, 0, 3);
3355 vendor_subnamespace = 0;
3356 skip_length = 0;
3357 break;
3358
3359 case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
3360 /*
3361 * We're switching to a vendor namespace.
3362 * Reset the presence-bitmap index to 0,
3363 * note that we're in a vendor namespace,
3364 * and fetch the fields of the Vendor Namespace
3365 * item.
3366 */
3367 bit0 = 0;
3368 vendor_namespace = 1;
3369 if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
3370 nd_print_trunc(ndo);
3371 break;
3372 }
3373 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
3374 nd_print_trunc(ndo);
3375 break;
3376 }
3377 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
3378 nd_print_trunc(ndo);
3379 break;
3380 }
3381 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
3382 nd_print_trunc(ndo);
3383 break;
3384 }
3385 if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
3386 nd_print_trunc(ndo);
3387 break;
3388 }
3389 if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
3390 nd_print_trunc(ndo);
3391 break;
3392 }
3393 break;
3394
3395 default:
3396 /*
3397 * Illegal combination. The behavior in this
3398 * case is undefined by the radiotap spec; we
3399 * just ignore both bits.
3400 */
3401 break;
3402 }
3403 }
3404
3405 if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
3406 pad = 1; /* Atheros padding */
3407 if (flags & IEEE80211_RADIOTAP_F_FCS)
3408 fcslen = 4; /* FCS at end of packet */
3409 return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
3410 fcslen);
3411 #undef BITNO_32
3412 #undef BITNO_16
3413 #undef BITNO_8
3414 #undef BITNO_4
3415 #undef BITNO_2
3416 #undef BIT
3417 }
3418
3419 static u_int
3420 ieee802_11_radio_avs_print(netdissect_options *ndo,
3421 const u_char *p, u_int length, u_int caplen)
3422 {
3423 uint32_t caphdr_len;
3424
3425 ndo->ndo_protocol = "802.11_radio_avs";
3426 if (caplen < 8) {
3427 nd_print_trunc(ndo);
3428 return caplen;
3429 }
3430
3431 caphdr_len = GET_BE_U_4(p + 4);
3432 if (caphdr_len < 8) {
3433 /*
3434 * Yow! The capture header length is claimed not
3435 * to be large enough to include even the version
3436 * cookie or capture header length!
3437 */
3438 nd_print_trunc(ndo);
3439 return caplen;
3440 }
3441
3442 if (caplen < caphdr_len) {
3443 nd_print_trunc(ndo);
3444 return caplen;
3445 }
3446
3447 return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
3448 length - caphdr_len, caplen - caphdr_len, 0, 0);
3449 }
3450
3451 #define PRISM_HDR_LEN 144
3452
3453 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
3454 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
3455 #define WLANCAP_MAGIC_COOKIE_V2 0x80211002
3456
3457 /*
3458 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
3459 * containing information such as radio information, which we
3460 * currently ignore.
3461 *
3462 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
3463 * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
3464 * (currently, on Linux, there's no ARPHRD_ type for
3465 * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
3466 * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
3467 * the AVS header, and the first 4 bytes of the header are used to
3468 * indicate whether it's a Prism header or an AVS header).
3469 */
3470 void
3471 prism_if_print(netdissect_options *ndo,
3472 const struct pcap_pkthdr *h, const u_char *p)
3473 {
3474 u_int caplen = h->caplen;
3475 u_int length = h->len;
3476 uint32_t msgcode;
3477
3478 ndo->ndo_protocol = "prism";
3479 if (caplen < 4) {
3480 nd_print_trunc(ndo);
3481 ndo->ndo_ll_hdr_len += caplen;
3482 return;
3483 }
3484
3485 msgcode = GET_BE_U_4(p);
3486 if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
3487 msgcode == WLANCAP_MAGIC_COOKIE_V2) {
3488 ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
3489 return;
3490 }
3491
3492 if (caplen < PRISM_HDR_LEN) {
3493 nd_print_trunc(ndo);
3494 ndo->ndo_ll_hdr_len += caplen;
3495 return;
3496 }
3497
3498 p += PRISM_HDR_LEN;
3499 length -= PRISM_HDR_LEN;
3500 caplen -= PRISM_HDR_LEN;
3501 ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
3502 ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
3503 }
3504
3505 /*
3506 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
3507 * header, containing information such as radio information.
3508 */
3509 void
3510 ieee802_11_radio_if_print(netdissect_options *ndo,
3511 const struct pcap_pkthdr *h, const u_char *p)
3512 {
3513 ndo->ndo_protocol = "802.11_radio";
3514 ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
3515 }
3516
3517 /*
3518 * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
3519 * extra header, containing information such as radio information,
3520 * which we currently ignore.
3521 */
3522 void
3523 ieee802_11_radio_avs_if_print(netdissect_options *ndo,
3524 const struct pcap_pkthdr *h, const u_char *p)
3525 {
3526 ndo->ndo_protocol = "802.11_radio_avs";
3527 ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
3528 }