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