]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_11.c
Makefile: Run shellcheck for build_common.sh too. [skip ci]
[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 cf.count = GET_U_1(p + offset);
1281 offset += 1;
1282 length -= 1;
1283 cf.period = GET_U_1(p + offset);
1284 offset += 1;
1285 length -= 1;
1286 cf.max_duration = GET_LE_U_2(p + offset);
1287 offset += 2;
1288 length -= 2;
1289 cf.dur_remaining = GET_LE_U_2(p + offset);
1290 offset += 2;
1291 length -= 2;
1292 /*
1293 * Present and not truncated.
1294 *
1295 * If we haven't already seen a CF IE,
1296 * copy this one, otherwise ignore this one,
1297 * so we later report the first one we saw.
1298 */
1299 if (!pbody->cf_present) {
1300 pbody->cf = cf;
1301 pbody->cf_present = 1;
1302 }
1303 break;
1304 case E_TIM:
1305 tim.length = elementlen;
1306 offset += 2;
1307 length -= 2;
1308 if (tim.length <= 3U) {
1309 offset += tim.length;
1310 length -= tim.length;
1311 break;
1312 }
1313 if (tim.length - 3U > sizeof(tim.bitmap))
1314 return 0;
1315 tim.count = GET_U_1(p + offset);
1316 offset += 1;
1317 length -= 1;
1318 tim.period = GET_U_1(p + offset);
1319 offset += 1;
1320 length -= 1;
1321 tim.bitmap_control = GET_U_1(p + offset);
1322 offset += 1;
1323 length -= 1;
1324 memcpy(tim.bitmap, p + offset, tim.length - 3);
1325 offset += tim.length - 3;
1326 length -= tim.length - 3;
1327 /*
1328 * Present and not truncated.
1329 *
1330 * If we haven't already seen a TIM IE,
1331 * copy this one, otherwise ignore this one,
1332 * so we later report the first one we saw.
1333 */
1334 if (!pbody->tim_present) {
1335 pbody->tim = tim;
1336 pbody->tim_present = 1;
1337 }
1338 break;
1339 default:
1340 #if 0
1341 ND_PRINT("(1) unhandled element_id (%u) ",
1342 GET_U_1(p + offset));
1343 #endif
1344 offset += 2 + elementlen;
1345 length -= 2 + elementlen;
1346 break;
1347 }
1348 }
1349
1350 /* No problems found. */
1351 return 1;
1352 trunc:
1353 return 0;
1354 }
1355
1356 /*********************************************************************************
1357 * Print Handle functions for the management frame types
1358 *********************************************************************************/
1359
1360 static int
1361 handle_beacon(netdissect_options *ndo,
1362 const u_char *p, u_int length)
1363 {
1364 struct mgmt_body_t pbody;
1365 int offset = 0;
1366 int ret;
1367
1368 memset(&pbody, 0, sizeof(pbody));
1369
1370 ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1371 IEEE802_11_CAPINFO_LEN);
1372 if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1373 IEEE802_11_CAPINFO_LEN)
1374 goto trunc;
1375 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
1376 offset += IEEE802_11_TSTAMP_LEN;
1377 length -= IEEE802_11_TSTAMP_LEN;
1378 pbody.beacon_interval = GET_LE_U_2(p + offset);
1379 offset += IEEE802_11_BCNINT_LEN;
1380 length -= IEEE802_11_BCNINT_LEN;
1381 pbody.capability_info = GET_LE_U_2(p + offset);
1382 offset += IEEE802_11_CAPINFO_LEN;
1383 length -= IEEE802_11_CAPINFO_LEN;
1384
1385 ret = parse_elements(ndo, &pbody, p, offset, length);
1386
1387 PRINT_SSID(pbody);
1388 PRINT_RATES(pbody);
1389 ND_PRINT(" %s",
1390 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
1391 PRINT_DS_CHANNEL(pbody);
1392
1393 return ret;
1394 trunc:
1395 return 0;
1396 }
1397
1398 static int
1399 handle_assoc_request(netdissect_options *ndo,
1400 const u_char *p, u_int length)
1401 {
1402 struct mgmt_body_t pbody;
1403 int offset = 0;
1404 int ret;
1405
1406 memset(&pbody, 0, sizeof(pbody));
1407
1408 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
1409 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
1410 goto trunc;
1411 pbody.capability_info = GET_LE_U_2(p);
1412 offset += IEEE802_11_CAPINFO_LEN;
1413 length -= IEEE802_11_CAPINFO_LEN;
1414 pbody.listen_interval = GET_LE_U_2(p + offset);
1415 offset += IEEE802_11_LISTENINT_LEN;
1416 length -= IEEE802_11_LISTENINT_LEN;
1417
1418 ret = parse_elements(ndo, &pbody, p, offset, length);
1419
1420 PRINT_SSID(pbody);
1421 PRINT_RATES(pbody);
1422 return ret;
1423 trunc:
1424 return 0;
1425 }
1426
1427 static int
1428 handle_assoc_response(netdissect_options *ndo,
1429 const u_char *p, u_int length)
1430 {
1431 struct mgmt_body_t pbody;
1432 int offset = 0;
1433 int ret;
1434
1435 memset(&pbody, 0, sizeof(pbody));
1436
1437 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1438 IEEE802_11_AID_LEN);
1439 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1440 IEEE802_11_AID_LEN)
1441 goto trunc;
1442 pbody.capability_info = GET_LE_U_2(p);
1443 offset += IEEE802_11_CAPINFO_LEN;
1444 length -= IEEE802_11_CAPINFO_LEN;
1445 pbody.status_code = GET_LE_U_2(p + offset);
1446 offset += IEEE802_11_STATUS_LEN;
1447 length -= IEEE802_11_STATUS_LEN;
1448 pbody.aid = GET_LE_U_2(p + offset);
1449 offset += IEEE802_11_AID_LEN;
1450 length -= IEEE802_11_AID_LEN;
1451
1452 ret = parse_elements(ndo, &pbody, p, offset, length);
1453
1454 ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
1455 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
1456 (pbody.status_code < NUM_STATUSES
1457 ? status_text[pbody.status_code]
1458 : "n/a"));
1459
1460 return ret;
1461 trunc:
1462 return 0;
1463 }
1464
1465 static int
1466 handle_reassoc_request(netdissect_options *ndo,
1467 const u_char *p, u_int length)
1468 {
1469 struct mgmt_body_t pbody;
1470 int offset = 0;
1471 int ret;
1472
1473 memset(&pbody, 0, sizeof(pbody));
1474
1475 ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1476 IEEE802_11_AP_LEN);
1477 if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1478 IEEE802_11_AP_LEN)
1479 goto trunc;
1480 pbody.capability_info = GET_LE_U_2(p);
1481 offset += IEEE802_11_CAPINFO_LEN;
1482 length -= IEEE802_11_CAPINFO_LEN;
1483 pbody.listen_interval = GET_LE_U_2(p + offset);
1484 offset += IEEE802_11_LISTENINT_LEN;
1485 length -= IEEE802_11_LISTENINT_LEN;
1486 memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
1487 offset += IEEE802_11_AP_LEN;
1488 length -= IEEE802_11_AP_LEN;
1489
1490 ret = parse_elements(ndo, &pbody, p, offset, length);
1491
1492 PRINT_SSID(pbody);
1493 ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap ));
1494
1495 return ret;
1496 trunc:
1497 return 0;
1498 }
1499
1500 static int
1501 handle_reassoc_response(netdissect_options *ndo,
1502 const u_char *p, u_int length)
1503 {
1504 /* Same as a Association Response */
1505 return handle_assoc_response(ndo, p, length);
1506 }
1507
1508 static int
1509 handle_probe_request(netdissect_options *ndo,
1510 const u_char *p, u_int length)
1511 {
1512 struct mgmt_body_t pbody;
1513 int offset = 0;
1514 int ret;
1515
1516 memset(&pbody, 0, sizeof(pbody));
1517
1518 ret = parse_elements(ndo, &pbody, p, offset, length);
1519
1520 PRINT_SSID(pbody);
1521 PRINT_RATES(pbody);
1522
1523 return ret;
1524 }
1525
1526 static int
1527 handle_probe_response(netdissect_options *ndo,
1528 const u_char *p, u_int length)
1529 {
1530 struct mgmt_body_t pbody;
1531 int offset = 0;
1532 int ret;
1533
1534 memset(&pbody, 0, sizeof(pbody));
1535
1536 ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1537 IEEE802_11_CAPINFO_LEN);
1538 if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1539 IEEE802_11_CAPINFO_LEN)
1540 goto trunc;
1541 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
1542 offset += IEEE802_11_TSTAMP_LEN;
1543 length -= IEEE802_11_TSTAMP_LEN;
1544 pbody.beacon_interval = GET_LE_U_2(p + offset);
1545 offset += IEEE802_11_BCNINT_LEN;
1546 length -= IEEE802_11_BCNINT_LEN;
1547 pbody.capability_info = GET_LE_U_2(p + offset);
1548 offset += IEEE802_11_CAPINFO_LEN;
1549 length -= IEEE802_11_CAPINFO_LEN;
1550
1551 ret = parse_elements(ndo, &pbody, p, offset, length);
1552
1553 PRINT_SSID(pbody);
1554 PRINT_RATES(pbody);
1555 PRINT_DS_CHANNEL(pbody);
1556
1557 return ret;
1558 trunc:
1559 return 0;
1560 }
1561
1562 static int
1563 handle_atim(void)
1564 {
1565 /* the frame body for ATIM is null. */
1566 return 1;
1567 }
1568
1569 static int
1570 handle_disassoc(netdissect_options *ndo,
1571 const u_char *p, u_int length)
1572 {
1573 struct mgmt_body_t pbody;
1574
1575 memset(&pbody, 0, sizeof(pbody));
1576
1577 ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
1578 if (length < IEEE802_11_REASON_LEN)
1579 goto trunc;
1580 pbody.reason_code = GET_LE_U_2(p);
1581
1582 ND_PRINT(": %s",
1583 (pbody.reason_code < NUM_REASONS)
1584 ? reason_text[pbody.reason_code]
1585 : "Reserved");
1586
1587 return 1;
1588 trunc:
1589 return 0;
1590 }
1591
1592 static int
1593 handle_auth(netdissect_options *ndo,
1594 const u_char *p, u_int length)
1595 {
1596 struct mgmt_body_t pbody;
1597 int offset = 0;
1598 int ret;
1599
1600 memset(&pbody, 0, sizeof(pbody));
1601
1602 ND_TCHECK_6(p);
1603 if (length < 6)
1604 goto trunc;
1605 pbody.auth_alg = GET_LE_U_2(p);
1606 offset += 2;
1607 length -= 2;
1608 pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
1609 offset += 2;
1610 length -= 2;
1611 pbody.status_code = GET_LE_U_2(p + offset);
1612 offset += 2;
1613 length -= 2;
1614
1615 ret = parse_elements(ndo, &pbody, p, offset, length);
1616
1617 if ((pbody.auth_alg == 1) &&
1618 ((pbody.auth_trans_seq_num == 2) ||
1619 (pbody.auth_trans_seq_num == 3))) {
1620 ND_PRINT(" (%s)-%x [Challenge Text] %s",
1621 (pbody.auth_alg < NUM_AUTH_ALGS)
1622 ? auth_alg_text[pbody.auth_alg]
1623 : "Reserved",
1624 pbody.auth_trans_seq_num,
1625 ((pbody.auth_trans_seq_num % 2)
1626 ? ((pbody.status_code < NUM_STATUSES)
1627 ? status_text[pbody.status_code]
1628 : "n/a") : ""));
1629 return ret;
1630 }
1631 ND_PRINT(" (%s)-%x: %s",
1632 (pbody.auth_alg < NUM_AUTH_ALGS)
1633 ? auth_alg_text[pbody.auth_alg]
1634 : "Reserved",
1635 pbody.auth_trans_seq_num,
1636 (pbody.auth_trans_seq_num % 2)
1637 ? ((pbody.status_code < NUM_STATUSES)
1638 ? status_text[pbody.status_code]
1639 : "n/a")
1640 : "");
1641
1642 return ret;
1643 trunc:
1644 return 0;
1645 }
1646
1647 static int
1648 handle_deauth(netdissect_options *ndo,
1649 const uint8_t *src, const u_char *p, u_int length)
1650 {
1651 struct mgmt_body_t pbody;
1652 const char *reason = NULL;
1653
1654 memset(&pbody, 0, sizeof(pbody));
1655
1656 ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
1657 if (length < IEEE802_11_REASON_LEN)
1658 goto trunc;
1659 pbody.reason_code = GET_LE_U_2(p);
1660
1661 reason = (pbody.reason_code < NUM_REASONS)
1662 ? reason_text[pbody.reason_code]
1663 : "Reserved";
1664
1665 if (ndo->ndo_eflag) {
1666 ND_PRINT(": %s", reason);
1667 } else {
1668 ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
1669 }
1670 return 1;
1671 trunc:
1672 return 0;
1673 }
1674
1675 static const struct tok category_str[] = {
1676 { 0, "Spectrum Management" },
1677 { 1, "QoS" },
1678 { 2, "DLS" },
1679 { 3, "BA" },
1680 { 7, "HT" },
1681 { 13, "MeshAction" },
1682 { 14, "MultiohopAction" },
1683 { 15, "SelfprotectAction" },
1684 { 127, "Vendor" },
1685 { 0, NULL }
1686 };
1687
1688 static const struct tok act_ba_str[] = {
1689 { 0, "ADDBA Request" },
1690 { 1, "ADDBA Response" },
1691 { 2, "DELBA" },
1692 { 0, NULL }
1693 };
1694
1695 static const struct tok act_ht_str[] = {
1696 { 0, "TxChWidth" },
1697 { 1, "MIMOPwrSave" },
1698 { 0, NULL }
1699 };
1700
1701 static const struct tok act_mesh_str[] = {
1702 { 0, "MeshLink" },
1703 { 1, "HWMP" },
1704 { 2, "Gate Announcement" },
1705 { 3, "Congestion Control" },
1706 { 4, "MCCA Setup Request" },
1707 { 5, "MCCA Setup Reply" },
1708 { 6, "MCCA Advertisement Request" },
1709 { 7, "MCCA Advertisement" },
1710 { 8, "MCCA Teardown" },
1711 { 9, "TBTT Adjustment Request" },
1712 { 10, "TBTT Adjustment Response" },
1713 { 0, NULL }
1714 };
1715
1716 static const struct tok act_mhop_str[] = {
1717 { 0, "Proxy Update" },
1718 { 1, "Proxy Update Confirmation" },
1719 { 0, NULL }
1720 };
1721
1722 static const struct tok act_selfpr_str[] = {
1723 { 1, "Peering Open" },
1724 { 2, "Peering Confirm" },
1725 { 3, "Peering Close" },
1726 { 4, "Group Key Inform" },
1727 { 5, "Group Key Acknowledge" },
1728 { 0, NULL }
1729 };
1730
1731 static const struct uint_tokary category2tokary[] = {
1732 { 3, act_ba_str },
1733 { 7, act_ht_str },
1734 { 13, act_mesh_str },
1735 { 14, act_mhop_str },
1736 { 15, act_selfpr_str },
1737 /* uint2tokary() does not use array termination. */
1738 };
1739
1740 static int
1741 handle_action(netdissect_options *ndo,
1742 const uint8_t *src, const u_char *p, u_int length)
1743 {
1744 uint8_t category, action;
1745 const struct tok *action_str;
1746
1747 ND_TCHECK_2(p);
1748 if (length < 2)
1749 goto trunc;
1750 if (ndo->ndo_eflag) {
1751 ND_PRINT(": ");
1752 } else {
1753 ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
1754 }
1755 category = GET_U_1(p);
1756 ND_PRINT("%s ", tok2str(category_str, "Reserved(%u)", category));
1757 action = GET_U_1(p + 1);
1758 action_str = uint2tokary(category2tokary, category);
1759 if (!action_str)
1760 ND_PRINT("Act#%u", action);
1761 else
1762 ND_PRINT("%s", tok2str(action_str, "Act#%u", action));
1763
1764 return 1;
1765 trunc:
1766 return 0;
1767 }
1768
1769
1770 /*********************************************************************************
1771 * Print Body funcs
1772 *********************************************************************************/
1773
1774
1775 static int
1776 mgmt_body_print(netdissect_options *ndo,
1777 uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
1778 {
1779 ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
1780
1781 /* There may be a problem w/ AP not having this bit set */
1782 if (FC_PROTECTED(fc))
1783 return wep_print(ndo, p);
1784 switch (FC_SUBTYPE(fc)) {
1785 case ST_ASSOC_REQUEST:
1786 return handle_assoc_request(ndo, p, length);
1787 case ST_ASSOC_RESPONSE:
1788 return handle_assoc_response(ndo, p, length);
1789 case ST_REASSOC_REQUEST:
1790 return handle_reassoc_request(ndo, p, length);
1791 case ST_REASSOC_RESPONSE:
1792 return handle_reassoc_response(ndo, p, length);
1793 case ST_PROBE_REQUEST:
1794 return handle_probe_request(ndo, p, length);
1795 case ST_PROBE_RESPONSE:
1796 return handle_probe_response(ndo, p, length);
1797 case ST_BEACON:
1798 return handle_beacon(ndo, p, length);
1799 case ST_ATIM:
1800 return handle_atim();
1801 case ST_DISASSOC:
1802 return handle_disassoc(ndo, p, length);
1803 case ST_AUTH:
1804 return handle_auth(ndo, p, length);
1805 case ST_DEAUTH:
1806 return handle_deauth(ndo, src, p, length);
1807 case ST_ACTION:
1808 return handle_action(ndo, src, p, length);
1809 default:
1810 return 1;
1811 }
1812 }
1813
1814
1815 /*********************************************************************************
1816 * Handles printing all the control frame types
1817 *********************************************************************************/
1818
1819 static int
1820 ctrl_body_print(netdissect_options *ndo,
1821 uint16_t fc, const u_char *p)
1822 {
1823 ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
1824 switch (FC_SUBTYPE(fc)) {
1825 case CTRL_CONTROL_WRAPPER:
1826 /* XXX - requires special handling */
1827 break;
1828 case CTRL_BAR:
1829 ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
1830 if (!ndo->ndo_eflag)
1831 ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1832 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
1833 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
1834 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
1835 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
1836 break;
1837 case CTRL_BA:
1838 ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
1839 if (!ndo->ndo_eflag)
1840 ND_PRINT(" RA:%s ",
1841 GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
1842 break;
1843 case CTRL_PS_POLL:
1844 ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
1845 ND_PRINT(" AID(%x)",
1846 GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
1847 break;
1848 case CTRL_RTS:
1849 ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
1850 if (!ndo->ndo_eflag)
1851 ND_PRINT(" TA:%s ",
1852 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
1853 break;
1854 case CTRL_CTS:
1855 ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
1856 if (!ndo->ndo_eflag)
1857 ND_PRINT(" RA:%s ",
1858 GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
1859 break;
1860 case CTRL_ACK:
1861 ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
1862 if (!ndo->ndo_eflag)
1863 ND_PRINT(" RA:%s ",
1864 GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
1865 break;
1866 case CTRL_CF_END:
1867 ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
1868 if (!ndo->ndo_eflag)
1869 ND_PRINT(" RA:%s ",
1870 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
1871 break;
1872 case CTRL_END_ACK:
1873 ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
1874 if (!ndo->ndo_eflag)
1875 ND_PRINT(" RA:%s ",
1876 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
1877 break;
1878 }
1879 return 1;
1880 trunc:
1881 return 0;
1882 }
1883
1884 /*
1885 * Data Frame - Address field contents
1886 *
1887 * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
1888 * 0 | 0 | DA | SA | BSSID | n/a
1889 * 0 | 1 | DA | BSSID | SA | n/a
1890 * 1 | 0 | BSSID | SA | DA | n/a
1891 * 1 | 1 | RA | TA | DA | SA
1892 */
1893
1894 /*
1895 * Function to get source and destination MAC addresses for a data frame.
1896 */
1897 static void
1898 get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
1899 const uint8_t **dstp)
1900 {
1901 #define ADDR1 (p + 4)
1902 #define ADDR2 (p + 10)
1903 #define ADDR3 (p + 16)
1904 #define ADDR4 (p + 24)
1905
1906 if (!FC_TO_DS(fc)) {
1907 if (!FC_FROM_DS(fc)) {
1908 /* not To DS and not From DS */
1909 *srcp = ADDR2;
1910 *dstp = ADDR1;
1911 } else {
1912 /* not To DS and From DS */
1913 *srcp = ADDR3;
1914 *dstp = ADDR1;
1915 }
1916 } else {
1917 if (!FC_FROM_DS(fc)) {
1918 /* To DS and not From DS */
1919 *srcp = ADDR2;
1920 *dstp = ADDR3;
1921 } else {
1922 /* To DS and From DS */
1923 *srcp = ADDR4;
1924 *dstp = ADDR3;
1925 }
1926 }
1927
1928 #undef ADDR1
1929 #undef ADDR2
1930 #undef ADDR3
1931 #undef ADDR4
1932 }
1933
1934 static void
1935 get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
1936 {
1937 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
1938
1939 if (srcp != NULL)
1940 *srcp = hp->sa;
1941 if (dstp != NULL)
1942 *dstp = hp->da;
1943 }
1944
1945 /*
1946 * Print Header funcs
1947 */
1948
1949 static void
1950 data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1951 {
1952 u_int subtype = FC_SUBTYPE(fc);
1953
1954 if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
1955 DATA_FRAME_IS_QOS(subtype)) {
1956 ND_PRINT("CF ");
1957 if (DATA_FRAME_IS_CF_ACK(subtype)) {
1958 if (DATA_FRAME_IS_CF_POLL(subtype))
1959 ND_PRINT("Ack/Poll");
1960 else
1961 ND_PRINT("Ack");
1962 } else {
1963 if (DATA_FRAME_IS_CF_POLL(subtype))
1964 ND_PRINT("Poll");
1965 }
1966 if (DATA_FRAME_IS_QOS(subtype))
1967 ND_PRINT("+QoS");
1968 ND_PRINT(" ");
1969 }
1970
1971 #define ADDR1 (p + 4)
1972 #define ADDR2 (p + 10)
1973 #define ADDR3 (p + 16)
1974 #define ADDR4 (p + 24)
1975
1976 if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1977 ND_PRINT("DA:%s SA:%s BSSID:%s ",
1978 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1979 GET_ETHERADDR_STRING(ADDR3));
1980 } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1981 ND_PRINT("DA:%s BSSID:%s SA:%s ",
1982 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1983 GET_ETHERADDR_STRING(ADDR3));
1984 } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1985 ND_PRINT("BSSID:%s SA:%s DA:%s ",
1986 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1987 GET_ETHERADDR_STRING(ADDR3));
1988 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1989 ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
1990 GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1991 GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
1992 }
1993
1994 #undef ADDR1
1995 #undef ADDR2
1996 #undef ADDR3
1997 #undef ADDR4
1998 }
1999
2000 static void
2001 mgmt_header_print(netdissect_options *ndo, const u_char *p)
2002 {
2003 const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
2004
2005 ND_PRINT("BSSID:%s DA:%s SA:%s ",
2006 GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
2007 GET_ETHERADDR_STRING((hp)->sa));
2008 }
2009
2010 static void
2011 ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
2012 {
2013 switch (FC_SUBTYPE(fc)) {
2014 case CTRL_BAR:
2015 ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
2016 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
2017 GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
2018 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
2019 GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
2020 break;
2021 case CTRL_BA:
2022 ND_PRINT("RA:%s ",
2023 GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
2024 break;
2025 case CTRL_PS_POLL:
2026 ND_PRINT("BSSID:%s TA:%s ",
2027 GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
2028 GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
2029 break;
2030 case CTRL_RTS:
2031 ND_PRINT("RA:%s TA:%s ",
2032 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
2033 GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
2034 break;
2035 case CTRL_CTS:
2036 ND_PRINT("RA:%s ",
2037 GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
2038 break;
2039 case CTRL_ACK:
2040 ND_PRINT("RA:%s ",
2041 GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
2042 break;
2043 case CTRL_CF_END:
2044 ND_PRINT("RA:%s BSSID:%s ",
2045 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
2046 GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
2047 break;
2048 case CTRL_END_ACK:
2049 ND_PRINT("RA:%s BSSID:%s ",
2050 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
2051 GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
2052 break;
2053 default:
2054 /* We shouldn't get here - we should already have quit */
2055 break;
2056 }
2057 }
2058
2059 static int
2060 extract_header_length(netdissect_options *ndo,
2061 uint16_t fc)
2062 {
2063 int len;
2064
2065 switch (FC_TYPE(fc)) {
2066 case T_MGMT:
2067 return MGMT_HDRLEN;
2068 case T_CTRL:
2069 switch (FC_SUBTYPE(fc)) {
2070 case CTRL_CONTROL_WRAPPER:
2071 return CTRL_CONTROL_WRAPPER_HDRLEN;
2072 case CTRL_BAR:
2073 return CTRL_BAR_HDRLEN;
2074 case CTRL_BA:
2075 return CTRL_BA_HDRLEN;
2076 case CTRL_PS_POLL:
2077 return CTRL_PS_POLL_HDRLEN;
2078 case CTRL_RTS:
2079 return CTRL_RTS_HDRLEN;
2080 case CTRL_CTS:
2081 return CTRL_CTS_HDRLEN;
2082 case CTRL_ACK:
2083 return CTRL_ACK_HDRLEN;
2084 case CTRL_CF_END:
2085 return CTRL_END_HDRLEN;
2086 case CTRL_END_ACK:
2087 return CTRL_END_ACK_HDRLEN;
2088 default:
2089 ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
2090 return 0;
2091 }
2092 case T_DATA:
2093 len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
2094 if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
2095 len += 2;
2096 return len;
2097 default:
2098 ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
2099 return 0;
2100 }
2101 }
2102
2103 static int
2104 extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
2105 {
2106 return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
2107 }
2108
2109 /*
2110 * Print the 802.11 MAC header.
2111 */
2112 static void
2113 ieee_802_11_hdr_print(netdissect_options *ndo,
2114 uint16_t fc, const u_char *p, u_int hdrlen,
2115 u_int meshdrlen)
2116 {
2117 if (ndo->ndo_vflag) {
2118 if (FC_MORE_DATA(fc))
2119 ND_PRINT("More Data ");
2120 if (FC_MORE_FLAG(fc))
2121 ND_PRINT("More Fragments ");
2122 if (FC_POWER_MGMT(fc))
2123 ND_PRINT("Pwr Mgmt ");
2124 if (FC_RETRY(fc))
2125 ND_PRINT("Retry ");
2126 if (FC_ORDER(fc))
2127 ND_PRINT("Strictly Ordered ");
2128 if (FC_PROTECTED(fc))
2129 ND_PRINT("Protected ");
2130 if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
2131 ND_PRINT("%uus ",
2132 GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
2133 }
2134 if (meshdrlen != 0) {
2135 const struct meshcntl_t *mc =
2136 (const struct meshcntl_t *)(p + hdrlen - meshdrlen);
2137 u_int ae = GET_U_1(mc->flags) & 3;
2138
2139 ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
2140 GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
2141 if (ae > 0)
2142 ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
2143 if (ae > 1)
2144 ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
2145 if (ae > 2)
2146 ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
2147 ND_PRINT(") ");
2148 }
2149
2150 switch (FC_TYPE(fc)) {
2151 case T_MGMT:
2152 mgmt_header_print(ndo, p);
2153 break;
2154 case T_CTRL:
2155 ctrl_header_print(ndo, fc, p);
2156 break;
2157 case T_DATA:
2158 data_header_print(ndo, fc, p);
2159 break;
2160 default:
2161 break;
2162 }
2163 }
2164
2165 static u_int
2166 ieee802_11_print(netdissect_options *ndo,
2167 const u_char *p, u_int length, u_int orig_caplen, int pad,
2168 u_int fcslen)
2169 {
2170 uint16_t fc;
2171 u_int caplen, hdrlen, meshdrlen;
2172 struct lladdr_info src, dst;
2173 int llc_hdrlen;
2174
2175 ndo->ndo_protocol = "802.11";
2176 caplen = orig_caplen;
2177 /* Remove FCS, if present */
2178 if (length < fcslen) {
2179 nd_print_trunc(ndo);
2180 return caplen;
2181 }
2182 length -= fcslen;
2183 if (caplen > length) {
2184 /* Amount of FCS in actual packet data, if any */
2185 fcslen = caplen - length;
2186 caplen -= fcslen;
2187 ndo->ndo_snapend -= fcslen;
2188 }
2189
2190 if (caplen < IEEE802_11_FC_LEN) {
2191 nd_print_trunc(ndo);
2192 return orig_caplen;
2193 }
2194
2195 fc = GET_LE_U_2(p);
2196 hdrlen = extract_header_length(ndo, fc);
2197 if (hdrlen == 0) {
2198 /* Unknown frame type or control frame subtype; quit. */
2199 return (0);
2200 }
2201 if (pad)
2202 hdrlen = roundup2(hdrlen, 4);
2203 if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
2204 DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
2205 if(!ND_TTEST_1(p + hdrlen)) {
2206 nd_print_trunc(ndo);
2207 return hdrlen;
2208 }
2209 meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
2210 hdrlen += meshdrlen;
2211 } else
2212 meshdrlen = 0;
2213
2214 if (caplen < hdrlen) {
2215 nd_print_trunc(ndo);
2216 return hdrlen;
2217 }
2218
2219 if (ndo->ndo_eflag)
2220 ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
2221
2222 /*
2223 * Go past the 802.11 header.
2224 */
2225 length -= hdrlen;
2226 caplen -= hdrlen;
2227 p += hdrlen;
2228
2229 src.addr_string = etheraddr_string;
2230 dst.addr_string = etheraddr_string;
2231 switch (FC_TYPE(fc)) {
2232 case T_MGMT:
2233 get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
2234 if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
2235 nd_print_trunc(ndo);
2236 return hdrlen;
2237 }
2238 break;
2239 case T_CTRL:
2240 if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
2241 nd_print_trunc(ndo);
2242 return hdrlen;
2243 }
2244 break;
2245 case T_DATA:
2246 if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
2247 return hdrlen; /* no-data frame */
2248 /* There may be a problem w/ AP not having this bit set */
2249 if (FC_PROTECTED(fc)) {
2250 ND_PRINT("Data");
2251 if (!wep_print(ndo, p)) {
2252 nd_print_trunc(ndo);
2253 return hdrlen;
2254 }
2255 } else {
2256 get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
2257 llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
2258 if (llc_hdrlen < 0) {
2259 /*
2260 * Some kinds of LLC packet we cannot
2261 * handle intelligently
2262 */
2263 if (!ndo->ndo_suppress_default_print)
2264 ND_DEFAULTPRINT(p, caplen);
2265 llc_hdrlen = -llc_hdrlen;
2266 }
2267 hdrlen += llc_hdrlen;
2268 }
2269 break;
2270 default:
2271 /* We shouldn't get here - we should already have quit */
2272 break;
2273 }
2274
2275 return hdrlen;
2276 }
2277
2278 /*
2279 * This is the top level routine of the printer. 'p' points
2280 * to the 802.11 header of the packet, 'h->ts' is the timestamp,
2281 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
2282 * is the number of bytes actually captured.
2283 */
2284 void
2285 ieee802_11_if_print(netdissect_options *ndo,
2286 const struct pcap_pkthdr *h, const u_char *p)
2287 {
2288 ndo->ndo_protocol = "802.11";
2289 ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
2290 }
2291
2292
2293 /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
2294 /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */
2295
2296 /*-
2297 * Copyright (c) 2003, 2004 David Young. All rights reserved.
2298 *
2299 * Redistribution and use in source and binary forms, with or without
2300 * modification, are permitted provided that the following conditions
2301 * are met:
2302 * 1. Redistributions of source code must retain the above copyright
2303 * notice, this list of conditions and the following disclaimer.
2304 * 2. Redistributions in binary form must reproduce the above copyright
2305 * notice, this list of conditions and the following disclaimer in the
2306 * documentation and/or other materials provided with the distribution.
2307 * 3. The name of David Young may not be used to endorse or promote
2308 * products derived from this software without specific prior
2309 * written permission.
2310 *
2311 * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
2312 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2313 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2314 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
2315 * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2316 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2317 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2318 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2319 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2320 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2321 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2322 * OF SUCH DAMAGE.
2323 */
2324
2325 /* A generic radio capture format is desirable. It must be
2326 * rigidly defined (e.g., units for fields should be given),
2327 * and easily extensible.
2328 *
2329 * The following is an extensible radio capture format. It is
2330 * based on a bitmap indicating which fields are present.
2331 *
2332 * I am trying to describe precisely what the application programmer
2333 * should expect in the following, and for that reason I tell the
2334 * units and origin of each measurement (where it applies), or else I
2335 * use sufficiently weaselly language ("is a monotonically nondecreasing
2336 * function of...") that I cannot set false expectations for lawyerly
2337 * readers.
2338 */
2339
2340 /*
2341 * The radio capture header precedes the 802.11 header.
2342 *
2343 * Note well: all radiotap fields are little-endian.
2344 */
2345 struct ieee80211_radiotap_header {
2346 nd_uint8_t it_version; /* Version 0. Only increases
2347 * for drastic changes,
2348 * introduction of compatible
2349 * new fields does not count.
2350 */
2351 nd_uint8_t it_pad;
2352 nd_uint16_t it_len; /* length of the whole
2353 * header in bytes, including
2354 * it_version, it_pad,
2355 * it_len, and data fields.
2356 */
2357 nd_uint32_t it_present; /* A bitmap telling which
2358 * fields are present. Set bit 31
2359 * (0x80000000) to extend the
2360 * bitmap by another 32 bits.
2361 * Additional extensions are made
2362 * by setting bit 31.
2363 */
2364 };
2365
2366 /* Name Data type Units
2367 * ---- --------- -----
2368 *
2369 * IEEE80211_RADIOTAP_TSFT uint64_t microseconds
2370 *
2371 * Value in microseconds of the MAC's 64-bit 802.11 Time
2372 * Synchronization Function timer when the first bit of the
2373 * MPDU arrived at the MAC. For received frames, only.
2374 *
2375 * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
2376 *
2377 * Tx/Rx frequency in MHz, followed by flags (see below).
2378 * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
2379 * represent an HT channel as there is not enough room in
2380 * the flags word.
2381 *
2382 * IEEE80211_RADIOTAP_FHSS uint16_t see below
2383 *
2384 * For frequency-hopping radios, the hop set (first byte)
2385 * and pattern (second byte).
2386 *
2387 * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index
2388 *
2389 * Tx/Rx data rate. If bit 0x80 is set then it represents an
2390 * an MCS index and not an IEEE rate.
2391 *
2392 * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
2393 * one milliwatt (dBm)
2394 *
2395 * RF signal power at the antenna, decibel difference from
2396 * one milliwatt.
2397 *
2398 * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from
2399 * one milliwatt (dBm)
2400 *
2401 * RF noise power at the antenna, decibel difference from one
2402 * milliwatt.
2403 *
2404 * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
2405 *
2406 * RF signal power at the antenna, decibel difference from an
2407 * arbitrary, fixed reference.
2408 *
2409 * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
2410 *
2411 * RF noise power at the antenna, decibel difference from an
2412 * arbitrary, fixed reference point.
2413 *
2414 * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
2415 *
2416 * Quality of Barker code lock. Unitless. Monotonically
2417 * nondecreasing with "better" lock strength. Called "Signal
2418 * Quality" in datasheets. (Is there a standard way to measure
2419 * this?)
2420 *
2421 * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
2422 *
2423 * Transmit power expressed as unitless distance from max
2424 * power set at factory calibration. 0 is max power.
2425 * Monotonically nondecreasing with lower power levels.
2426 *
2427 * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
2428 *
2429 * Transmit power expressed as decibel distance from max power
2430 * set at factory calibration. 0 is max power. Monotonically
2431 * nondecreasing with lower power levels.
2432 *
2433 * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from
2434 * one milliwatt (dBm)
2435 *
2436 * Transmit power expressed as dBm (decibels from a 1 milliwatt
2437 * reference). This is the absolute power level measured at
2438 * the antenna port.
2439 *
2440 * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
2441 *
2442 * Properties of transmitted and received frames. See flags
2443 * defined below.
2444 *
2445 * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
2446 *
2447 * Unitless indication of the Rx/Tx antenna for this packet.
2448 * The first antenna is antenna 0.
2449 *
2450 * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
2451 *
2452 * Properties of received frames. See flags defined below.
2453 *
2454 * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap
2455 * uint16_t MHz
2456 * uint8_t channel number
2457 * uint8_t .5 dBm
2458 *
2459 * Extended channel specification: flags (see below) followed by
2460 * frequency in MHz, the corresponding IEEE channel number, and
2461 * finally the maximum regulatory transmit power cap in .5 dBm
2462 * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL
2463 * and only one of the two should be present.
2464 *
2465 * IEEE80211_RADIOTAP_MCS uint8_t known
2466 * uint8_t flags
2467 * uint8_t mcs
2468 *
2469 * Bitset indicating which fields have known values, followed
2470 * by bitset of flag values, followed by the MCS rate index as
2471 * in IEEE 802.11n.
2472 *
2473 *
2474 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
2475 *
2476 * Contains the AMPDU information for the subframe.
2477 *
2478 * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
2479 *
2480 * Contains VHT information about this frame.
2481 *
2482 * IEEE80211_RADIOTAP_VENDOR_NAMESPACE
2483 * uint8_t OUI[3]
2484 * uint8_t subspace
2485 * uint16_t length
2486 *
2487 * The Vendor Namespace Field contains three sub-fields. The first
2488 * sub-field is 3 bytes long. It contains the vendor's IEEE 802
2489 * Organizationally Unique Identifier (OUI). The fourth byte is a
2490 * vendor-specific "namespace selector."
2491 *
2492 */
2493 enum ieee80211_radiotap_type {
2494 IEEE80211_RADIOTAP_TSFT = 0,
2495 IEEE80211_RADIOTAP_FLAGS = 1,
2496 IEEE80211_RADIOTAP_RATE = 2,
2497 IEEE80211_RADIOTAP_CHANNEL = 3,
2498 IEEE80211_RADIOTAP_FHSS = 4,
2499 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
2500 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
2501 IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
2502 IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
2503 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
2504 IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
2505 IEEE80211_RADIOTAP_ANTENNA = 11,
2506 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
2507 IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
2508 IEEE80211_RADIOTAP_RX_FLAGS = 14,
2509 /* NB: gap for netbsd definitions */
2510 IEEE80211_RADIOTAP_XCHANNEL = 18,
2511 IEEE80211_RADIOTAP_MCS = 19,
2512 IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
2513 IEEE80211_RADIOTAP_VHT = 21,
2514 IEEE80211_RADIOTAP_NAMESPACE = 29,
2515 IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
2516 IEEE80211_RADIOTAP_EXT = 31
2517 };
2518
2519 /* channel attributes */
2520 #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */
2521 #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */
2522 #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */
2523 #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */
2524 #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */
2525 #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */
2526 #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */
2527 #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */
2528 #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */
2529 #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */
2530 #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */
2531 #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */
2532 #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */
2533 #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */
2534 #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */
2535
2536 /* Useful combinations of channel characteristics, borrowed from Ethereal */
2537 #define IEEE80211_CHAN_A \
2538 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2539 #define IEEE80211_CHAN_B \
2540 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2541 #define IEEE80211_CHAN_G \
2542 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2543 #define IEEE80211_CHAN_TA \
2544 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
2545 #define IEEE80211_CHAN_TG \
2546 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO)
2547
2548
2549 /* For IEEE80211_RADIOTAP_FLAGS */
2550 #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
2551 * during CFP
2552 */
2553 #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
2554 * with short
2555 * preamble
2556 */
2557 #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
2558 * with WEP encryption
2559 */
2560 #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
2561 * with fragmentation
2562 */
2563 #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
2564 #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
2565 * 802.11 header and payload
2566 * (to 32-bit boundary)
2567 */
2568 #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */
2569
2570 /* For IEEE80211_RADIOTAP_RX_FLAGS */
2571 #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
2572 #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */
2573
2574 /* For IEEE80211_RADIOTAP_MCS known */
2575 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01
2576 #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */
2577 #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04
2578 #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08
2579 #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10
2580 #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20
2581 #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40
2582 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80
2583
2584 /* For IEEE80211_RADIOTAP_MCS flags */
2585 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03
2586 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0
2587 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1
2588 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2
2589 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3
2590 #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */
2591 #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08
2592 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
2593 #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
2594 #define IEEE80211_RADIOTAP_MCS_STBC_1 1
2595 #define IEEE80211_RADIOTAP_MCS_STBC_2 2
2596 #define IEEE80211_RADIOTAP_MCS_STBC_3 3
2597 #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
2598 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80
2599
2600 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
2601 #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
2602 #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
2603 #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
2604 #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
2605 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
2606 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
2607
2608 /* For IEEE80211_RADIOTAP_VHT known */
2609 #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001
2610 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002
2611 #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004
2612 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008
2613 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010
2614 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020
2615 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040
2616 #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080
2617 #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100
2618
2619 /* For IEEE80211_RADIOTAP_VHT flags */
2620 #define IEEE80211_RADIOTAP_VHT_STBC 0x01
2621 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02
2622 #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04
2623 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08
2624 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10
2625 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20
2626
2627 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f
2628
2629 #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f
2630 #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0
2631 #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4
2632
2633 #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01
2634
2635 #define IEEE80211_CHAN_FHSS \
2636 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
2637 #define IEEE80211_CHAN_A \
2638 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2639 #define IEEE80211_CHAN_B \
2640 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2641 #define IEEE80211_CHAN_PUREG \
2642 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
2643 #define IEEE80211_CHAN_G \
2644 (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2645
2646 #define IS_CHAN_FHSS(flags) \
2647 ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
2648 #define IS_CHAN_A(flags) \
2649 ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
2650 #define IS_CHAN_B(flags) \
2651 ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
2652 #define IS_CHAN_PUREG(flags) \
2653 ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
2654 #define IS_CHAN_G(flags) \
2655 ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
2656 #define IS_CHAN_ANYG(flags) \
2657 (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
2658
2659 static void
2660 print_chaninfo(netdissect_options *ndo,
2661 uint16_t freq, uint32_t flags, uint32_t presentflags)
2662 {
2663 ND_PRINT("%u MHz", freq);
2664 if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
2665 /*
2666 * We have the MCS field, so this is 11n, regardless
2667 * of what the channel flags say.
2668 */
2669 ND_PRINT(" 11n");
2670 } else {
2671 if (IS_CHAN_FHSS(flags))
2672 ND_PRINT(" FHSS");
2673 if (IS_CHAN_A(flags)) {
2674 if (flags & IEEE80211_CHAN_HALF)
2675 ND_PRINT(" 11a/10Mhz");
2676 else if (flags & IEEE80211_CHAN_QUARTER)
2677 ND_PRINT(" 11a/5Mhz");
2678 else
2679 ND_PRINT(" 11a");
2680 }
2681 if (IS_CHAN_ANYG(flags)) {
2682 if (flags & IEEE80211_CHAN_HALF)
2683 ND_PRINT(" 11g/10Mhz");
2684 else if (flags & IEEE80211_CHAN_QUARTER)
2685 ND_PRINT(" 11g/5Mhz");
2686 else
2687 ND_PRINT(" 11g");
2688 } else if (IS_CHAN_B(flags))
2689 ND_PRINT(" 11b");
2690 if (flags & IEEE80211_CHAN_TURBO)
2691 ND_PRINT(" Turbo");
2692 }
2693 /*
2694 * These apply to 11n.
2695 */
2696 if (flags & IEEE80211_CHAN_HT20)
2697 ND_PRINT(" ht/20");
2698 else if (flags & IEEE80211_CHAN_HT40D)
2699 ND_PRINT(" ht/40-");
2700 else if (flags & IEEE80211_CHAN_HT40U)
2701 ND_PRINT(" ht/40+");
2702 ND_PRINT(" ");
2703 }
2704
2705 static int
2706 print_radiotap_field(netdissect_options *ndo,
2707 struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
2708 uint32_t presentflags)
2709 {
2710 u_int i;
2711 int rc;
2712
2713 switch (bit) {
2714
2715 case IEEE80211_RADIOTAP_TSFT: {
2716 uint64_t tsft;
2717
2718 rc = nd_cpack_uint64(ndo, s, &tsft);
2719 if (rc != 0)
2720 goto trunc;
2721 ND_PRINT("%" PRIu64 "us tsft ", tsft);
2722 break;
2723 }
2724
2725 case IEEE80211_RADIOTAP_FLAGS: {
2726 uint8_t flagsval;
2727
2728 rc = nd_cpack_uint8(ndo, s, &flagsval);
2729 if (rc != 0)
2730 goto trunc;
2731 *flagsp = flagsval;
2732 if (flagsval & IEEE80211_RADIOTAP_F_CFP)
2733 ND_PRINT("cfp ");
2734 if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
2735 ND_PRINT("short preamble ");
2736 if (flagsval & IEEE80211_RADIOTAP_F_WEP)
2737 ND_PRINT("wep ");
2738 if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
2739 ND_PRINT("fragmented ");
2740 if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
2741 ND_PRINT("bad-fcs ");
2742 break;
2743 }
2744
2745 case IEEE80211_RADIOTAP_RATE: {
2746 uint8_t rate;
2747
2748 rc = nd_cpack_uint8(ndo, s, &rate);
2749 if (rc != 0)
2750 goto trunc;
2751 /*
2752 * XXX On FreeBSD rate & 0x80 means we have an MCS. On
2753 * Linux and AirPcap it does not. (What about
2754 * macOS, NetBSD, OpenBSD, and DragonFly BSD?)
2755 *
2756 * This is an issue either for proprietary extensions
2757 * to 11a or 11g, which do exist, or for 11n
2758 * implementations that stuff a rate value into
2759 * this field, which also appear to exist.
2760 *
2761 * We currently handle that by assuming that
2762 * if the 0x80 bit is set *and* the remaining
2763 * bits have a value between 0 and 15 it's
2764 * an MCS value, otherwise it's a rate. If
2765 * there are cases where systems that use
2766 * "0x80 + MCS index" for MCS indices > 15,
2767 * or stuff a rate value here between 64 and
2768 * 71.5 Mb/s in here, we'll need a preference
2769 * setting. Such rates do exist, e.g. 11n
2770 * MCS 7 at 20 MHz with a long guard interval.
2771 */
2772 if (rate >= 0x80 && rate <= 0x8f) {
2773 /*
2774 * XXX - we don't know the channel width
2775 * or guard interval length, so we can't
2776 * convert this to a data rate.
2777 *
2778 * If you want us to show a data rate,
2779 * use the MCS field, not the Rate field;
2780 * the MCS field includes not only the
2781 * MCS index, it also includes bandwidth
2782 * and guard interval information.
2783 *
2784 * XXX - can we get the channel width
2785 * from XChannel and the guard interval
2786 * information from Flags, at least on
2787 * FreeBSD?
2788 */
2789 ND_PRINT("MCS %u ", rate & 0x7f);
2790 } else
2791 ND_PRINT("%2.1f Mb/s ", .5 * rate);
2792 break;
2793 }
2794
2795 case IEEE80211_RADIOTAP_CHANNEL: {
2796 uint16_t frequency;
2797 uint16_t flags;
2798
2799 rc = nd_cpack_uint16(ndo, s, &frequency);
2800 if (rc != 0)
2801 goto trunc;
2802 rc = nd_cpack_uint16(ndo, s, &flags);
2803 if (rc != 0)
2804 goto trunc;
2805 /*
2806 * If CHANNEL and XCHANNEL are both present, skip
2807 * CHANNEL.
2808 */
2809 if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
2810 break;
2811 print_chaninfo(ndo, frequency, flags, presentflags);
2812 break;
2813 }
2814
2815 case IEEE80211_RADIOTAP_FHSS: {
2816 uint8_t hopset;
2817 uint8_t hoppat;
2818
2819 rc = nd_cpack_uint8(ndo, s, &hopset);
2820 if (rc != 0)
2821 goto trunc;
2822 rc = nd_cpack_uint8(ndo, s, &hoppat);
2823 if (rc != 0)
2824 goto trunc;
2825 ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
2826 break;
2827 }
2828
2829 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
2830 int8_t dbm_antsignal;
2831
2832 rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
2833 if (rc != 0)
2834 goto trunc;
2835 ND_PRINT("%ddBm signal ", dbm_antsignal);
2836 break;
2837 }
2838
2839 case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
2840 int8_t dbm_antnoise;
2841
2842 rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
2843 if (rc != 0)
2844 goto trunc;
2845 ND_PRINT("%ddBm noise ", dbm_antnoise);
2846 break;
2847 }
2848
2849 case IEEE80211_RADIOTAP_LOCK_QUALITY: {
2850 uint16_t lock_quality;
2851
2852 rc = nd_cpack_uint16(ndo, s, &lock_quality);
2853 if (rc != 0)
2854 goto trunc;
2855 ND_PRINT("%u sq ", lock_quality);
2856 break;
2857 }
2858
2859 case IEEE80211_RADIOTAP_TX_ATTENUATION: {
2860 int16_t tx_attenuation;
2861
2862 rc = nd_cpack_int16(ndo, s, &tx_attenuation);
2863 if (rc != 0)
2864 goto trunc;
2865 ND_PRINT("%d tx power ", -tx_attenuation);
2866 break;
2867 }
2868
2869 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
2870 int8_t db_tx_attenuation;
2871
2872 rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
2873 if (rc != 0)
2874 goto trunc;
2875 ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
2876 break;
2877 }
2878
2879 case IEEE80211_RADIOTAP_DBM_TX_POWER: {
2880 int8_t dbm_tx_power;
2881
2882 rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
2883 if (rc != 0)
2884 goto trunc;
2885 ND_PRINT("%ddBm tx power ", dbm_tx_power);
2886 break;
2887 }
2888
2889 case IEEE80211_RADIOTAP_ANTENNA: {
2890 uint8_t antenna;
2891
2892 rc = nd_cpack_uint8(ndo, s, &antenna);
2893 if (rc != 0)
2894 goto trunc;
2895 ND_PRINT("antenna %u ", antenna);
2896 break;
2897 }
2898
2899 case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
2900 uint8_t db_antsignal;
2901
2902 rc = nd_cpack_uint8(ndo, s, &db_antsignal);
2903 if (rc != 0)
2904 goto trunc;
2905 ND_PRINT("%udB signal ", db_antsignal);
2906 break;
2907 }
2908
2909 case IEEE80211_RADIOTAP_DB_ANTNOISE: {
2910 uint8_t db_antnoise;
2911
2912 rc = nd_cpack_uint8(ndo, s, &db_antnoise);
2913 if (rc != 0)
2914 goto trunc;
2915 ND_PRINT("%udB noise ", db_antnoise);
2916 break;
2917 }
2918
2919 case IEEE80211_RADIOTAP_RX_FLAGS: {
2920 uint16_t rx_flags;
2921
2922 rc = nd_cpack_uint16(ndo, s, &rx_flags);
2923 if (rc != 0)
2924 goto trunc;
2925 /* Do nothing for now */
2926 break;
2927 }
2928
2929 case IEEE80211_RADIOTAP_XCHANNEL: {
2930 uint32_t flags;
2931 uint16_t frequency;
2932 uint8_t channel;
2933 uint8_t maxpower;
2934
2935 rc = nd_cpack_uint32(ndo, s, &flags);
2936 if (rc != 0)
2937 goto trunc;
2938 rc = nd_cpack_uint16(ndo, s, &frequency);
2939 if (rc != 0)
2940 goto trunc;
2941 rc = nd_cpack_uint8(ndo, s, &channel);
2942 if (rc != 0)
2943 goto trunc;
2944 rc = nd_cpack_uint8(ndo, s, &maxpower);
2945 if (rc != 0)
2946 goto trunc;
2947 print_chaninfo(ndo, frequency, flags, presentflags);
2948 break;
2949 }
2950
2951 case IEEE80211_RADIOTAP_MCS: {
2952 uint8_t known;
2953 uint8_t flags;
2954 uint8_t mcs_index;
2955 static const char *ht_bandwidth[4] = {
2956 "20 MHz",
2957 "40 MHz",
2958 "20 MHz (L)",
2959 "20 MHz (U)"
2960 };
2961 float htrate;
2962
2963 rc = nd_cpack_uint8(ndo, s, &known);
2964 if (rc != 0)
2965 goto trunc;
2966 rc = nd_cpack_uint8(ndo, s, &flags);
2967 if (rc != 0)
2968 goto trunc;
2969 rc = nd_cpack_uint8(ndo, s, &mcs_index);
2970 if (rc != 0)
2971 goto trunc;
2972 if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
2973 /*
2974 * We know the MCS index.
2975 */
2976 if (mcs_index <= MAX_MCS_INDEX) {
2977 /*
2978 * And it's in-range.
2979 */
2980 if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
2981 /*
2982 * And we know both the bandwidth and
2983 * the guard interval, so we can look
2984 * up the rate.
2985 */
2986 htrate =
2987 ieee80211_float_htrates
2988 [mcs_index]
2989 [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
2990 [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
2991 } else {
2992 /*
2993 * We don't know both the bandwidth
2994 * and the guard interval, so we can
2995 * only report the MCS index.
2996 */
2997 htrate = 0.0;
2998 }
2999 } else {
3000 /*
3001 * The MCS value is out of range.
3002 */
3003 htrate = 0.0;
3004 }
3005 if (htrate != 0.0) {
3006 /*
3007 * We have the rate.
3008 * Print it.
3009 */
3010 ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
3011 } else {
3012 /*
3013 * We at least have the MCS index.
3014 * Print it.
3015 */
3016 ND_PRINT("MCS %u ", mcs_index);
3017 }
3018 }
3019 if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
3020 ND_PRINT("%s ",
3021 ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
3022 }
3023 if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
3024 ND_PRINT("%s GI ",
3025 (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
3026 "short" : "long");
3027 }
3028 if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
3029 ND_PRINT("%s ",
3030 (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
3031 "greenfield" : "mixed");
3032 }
3033 if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
3034 ND_PRINT("%s FEC ",
3035 (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
3036 "LDPC" : "BCC");
3037 }
3038 if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
3039 ND_PRINT("RX-STBC%u ",
3040 (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
3041 }
3042 break;
3043 }
3044
3045 case IEEE80211_RADIOTAP_AMPDU_STATUS: {
3046 uint32_t reference_num;
3047 uint16_t flags;
3048 uint8_t delim_crc;
3049 uint8_t reserved;
3050
3051 rc = nd_cpack_uint32(ndo, s, &reference_num);
3052 if (rc != 0)
3053 goto trunc;
3054 rc = nd_cpack_uint16(ndo, s, &flags);
3055 if (rc != 0)
3056 goto trunc;
3057 rc = nd_cpack_uint8(ndo, s, &delim_crc);
3058 if (rc != 0)
3059 goto trunc;
3060 rc = nd_cpack_uint8(ndo, s, &reserved);
3061 if (rc != 0)
3062 goto trunc;
3063 /* Do nothing for now */
3064 break;
3065 }
3066
3067 case IEEE80211_RADIOTAP_VHT: {
3068 uint16_t known;
3069 uint8_t flags;
3070 uint8_t bandwidth;
3071 uint8_t mcs_nss[4];
3072 uint8_t coding;
3073 uint8_t group_id;
3074 uint16_t partial_aid;
3075 static const char *vht_bandwidth[32] = {
3076 "20 MHz",
3077 "40 MHz",
3078 "20 MHz (L)",
3079 "20 MHz (U)",
3080 "80 MHz",
3081 "80 MHz (L)",
3082 "80 MHz (U)",
3083 "80 MHz (LL)",
3084 "80 MHz (LU)",
3085 "80 MHz (UL)",
3086 "80 MHz (UU)",
3087 "160 MHz",
3088 "160 MHz (L)",
3089 "160 MHz (U)",
3090 "160 MHz (LL)",
3091 "160 MHz (LU)",
3092 "160 MHz (UL)",
3093 "160 MHz (UU)",
3094 "160 MHz (LLL)",
3095 "160 MHz (LLU)",
3096 "160 MHz (LUL)",
3097 "160 MHz (UUU)",
3098 "160 MHz (ULL)",
3099 "160 MHz (ULU)",
3100 "160 MHz (UUL)",
3101 "160 MHz (UUU)",
3102 "unknown (26)",
3103 "unknown (27)",
3104 "unknown (28)",
3105 "unknown (29)",
3106 "unknown (30)",
3107 "unknown (31)"
3108 };
3109
3110 rc = nd_cpack_uint16(ndo, s, &known);
3111 if (rc != 0)
3112 goto trunc;
3113 rc = nd_cpack_uint8(ndo, s, &flags);
3114 if (rc != 0)
3115 goto trunc;
3116 rc = nd_cpack_uint8(ndo, s, &bandwidth);
3117 if (rc != 0)
3118 goto trunc;
3119 for (i = 0; i < 4; i++) {
3120 rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
3121 if (rc != 0)
3122 goto trunc;
3123 }
3124 rc = nd_cpack_uint8(ndo, s, &coding);
3125 if (rc != 0)
3126 goto trunc;
3127 rc = nd_cpack_uint8(ndo, s, &group_id);
3128 if (rc != 0)
3129 goto trunc;
3130 rc = nd_cpack_uint16(ndo, s, &partial_aid);
3131 if (rc != 0)
3132 goto trunc;
3133 for (i = 0; i < 4; i++) {
3134 u_int nss, mcs;
3135 nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
3136 mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
3137
3138 if (nss == 0)
3139 continue;
3140
3141 ND_PRINT("User %u MCS %u ", i, mcs);
3142 ND_PRINT("%s FEC ",
3143 (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
3144 "LDPC" : "BCC");
3145 }
3146 if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
3147 ND_PRINT("%s ",
3148 vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
3149 }
3150 if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
3151 ND_PRINT("%s GI ",
3152 (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
3153 "short" : "long");
3154 }
3155 break;
3156 }
3157
3158 default:
3159 /* this bit indicates a field whose
3160 * size we do not know, so we cannot
3161 * proceed. Just print the bit number.
3162 */
3163 ND_PRINT("[bit %u] ", bit);
3164 return -1;
3165 }
3166
3167 return 0;
3168
3169 trunc:
3170 nd_print_trunc(ndo);
3171 return rc;
3172 }
3173
3174
3175 static int
3176 print_in_radiotap_namespace(netdissect_options *ndo,
3177 struct cpack_state *s, uint8_t *flags,
3178 uint32_t presentflags, int bit0)
3179 {
3180 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
3181 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
3182 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
3183 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
3184 #define BITNO_2(x) (((x) & 2) ? 1 : 0)
3185 uint32_t present, next_present;
3186 int bitno;
3187 enum ieee80211_radiotap_type bit;
3188 int rc;
3189
3190 for (present = presentflags; present; present = next_present) {
3191 /*
3192 * Clear the least significant bit that is set.
3193 */
3194 next_present = present & (present - 1);
3195
3196 /*
3197 * Get the bit number, within this presence word,
3198 * of the remaining least significant bit that
3199 * is set.
3200 */
3201 bitno = BITNO_32(present ^ next_present);
3202
3203 /*
3204 * Stop if this is one of the "same meaning
3205 * in all presence flags" bits.
3206 */
3207 if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
3208 break;
3209
3210 /*
3211 * Get the radiotap bit number of that bit.
3212 */
3213 bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
3214
3215 rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
3216 if (rc != 0)
3217 return rc;
3218 }
3219
3220 return 0;
3221 }
3222
3223 u_int
3224 ieee802_11_radio_print(netdissect_options *ndo,
3225 const u_char *p, u_int length, u_int caplen)
3226 {
3227 #define BIT(n) (1U << n)
3228 #define IS_EXTENDED(__p) \
3229 (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
3230
3231 struct cpack_state cpacker;
3232 const struct ieee80211_radiotap_header *hdr;
3233 uint32_t presentflags;
3234 const nd_uint32_t *presentp, *last_presentp;
3235 int vendor_namespace;
3236 uint8_t vendor_oui[3];
3237 uint8_t vendor_subnamespace;
3238 uint16_t skip_length;
3239 int bit0;
3240 u_int len;
3241 uint8_t flags;
3242 int pad;
3243 u_int fcslen;
3244
3245 ndo->ndo_protocol = "802.11_radio";
3246 if (caplen < sizeof(*hdr)) {
3247 nd_print_trunc(ndo);
3248 return caplen;
3249 }
3250
3251 hdr = (const struct ieee80211_radiotap_header *)p;
3252
3253 len = GET_LE_U_2(hdr->it_len);
3254 if (len < sizeof(*hdr)) {
3255 /*
3256 * The length is the length of the entire header, so
3257 * it must be as large as the fixed-length part of
3258 * the header.
3259 */
3260 nd_print_trunc(ndo);
3261 return caplen;
3262 }
3263
3264 /*
3265 * If we don't have the entire radiotap header, just give up.
3266 */
3267 if (caplen < len) {
3268 nd_print_trunc(ndo);
3269 return caplen;
3270 }
3271 nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
3272 nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
3273 for (last_presentp = &hdr->it_present;
3274 (const u_char*)(last_presentp + 1) <= p + len &&
3275 IS_EXTENDED(last_presentp);
3276 last_presentp++)
3277 nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
3278
3279 /* are there more bitmap extensions than bytes in header? */
3280 if ((const u_char*)(last_presentp + 1) > p + len) {
3281 nd_print_trunc(ndo);
3282 return caplen;
3283 }
3284
3285 /*
3286 * Start out at the beginning of the default radiotap namespace.
3287 */
3288 bit0 = 0;
3289 vendor_namespace = 0;
3290 memset(vendor_oui, 0, 3);
3291 vendor_subnamespace = 0;
3292 skip_length = 0;
3293 /* Assume no flags */
3294 flags = 0;
3295 /* Assume no Atheros padding between 802.11 header and body */
3296 pad = 0;
3297 /* Assume no FCS at end of frame */
3298 fcslen = 0;
3299 for (presentp = &hdr->it_present; presentp <= last_presentp;
3300 presentp++) {
3301 presentflags = GET_LE_U_4(presentp);
3302
3303 /*
3304 * If this is a vendor namespace, we don't handle it.
3305 */
3306 if (vendor_namespace) {
3307 /*
3308 * Skip past the stuff we don't understand.
3309 * If we add support for any vendor namespaces,
3310 * it'd be added here; use vendor_oui and
3311 * vendor_subnamespace to interpret the fields.
3312 */
3313 if (nd_cpack_advance(&cpacker, skip_length) != 0) {
3314 /*
3315 * Ran out of space in the packet.
3316 */
3317 break;
3318 }
3319
3320 /*
3321 * We've skipped it all; nothing more to
3322 * skip.
3323 */
3324 skip_length = 0;
3325 } else {
3326 if (print_in_radiotap_namespace(ndo, &cpacker,
3327 &flags, presentflags, bit0) != 0) {
3328 /*
3329 * Fatal error - can't process anything
3330 * more in the radiotap header.
3331 */
3332 break;
3333 }
3334 }
3335
3336 /*
3337 * Handle the namespace switch bits; we've already handled
3338 * the extension bit in all but the last word above.
3339 */
3340 switch (presentflags &
3341 (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
3342
3343 case 0:
3344 /*
3345 * We're not changing namespaces.
3346 * advance to the next 32 bits in the current
3347 * namespace.
3348 */
3349 bit0 += 32;
3350 break;
3351
3352 case BIT(IEEE80211_RADIOTAP_NAMESPACE):
3353 /*
3354 * We're switching to the radiotap namespace.
3355 * Reset the presence-bitmap index to 0, and
3356 * reset the namespace to the default radiotap
3357 * namespace.
3358 */
3359 bit0 = 0;
3360 vendor_namespace = 0;
3361 memset(vendor_oui, 0, 3);
3362 vendor_subnamespace = 0;
3363 skip_length = 0;
3364 break;
3365
3366 case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
3367 /*
3368 * We're switching to a vendor namespace.
3369 * Reset the presence-bitmap index to 0,
3370 * note that we're in a vendor namespace,
3371 * and fetch the fields of the Vendor Namespace
3372 * item.
3373 */
3374 bit0 = 0;
3375 vendor_namespace = 1;
3376 if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
3377 nd_print_trunc(ndo);
3378 break;
3379 }
3380 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
3381 nd_print_trunc(ndo);
3382 break;
3383 }
3384 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
3385 nd_print_trunc(ndo);
3386 break;
3387 }
3388 if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
3389 nd_print_trunc(ndo);
3390 break;
3391 }
3392 if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
3393 nd_print_trunc(ndo);
3394 break;
3395 }
3396 if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
3397 nd_print_trunc(ndo);
3398 break;
3399 }
3400 break;
3401
3402 default:
3403 /*
3404 * Illegal combination. The behavior in this
3405 * case is undefined by the radiotap spec; we
3406 * just ignore both bits.
3407 */
3408 break;
3409 }
3410 }
3411
3412 if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
3413 pad = 1; /* Atheros padding */
3414 if (flags & IEEE80211_RADIOTAP_F_FCS)
3415 fcslen = 4; /* FCS at end of packet */
3416 return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
3417 fcslen);
3418 #undef BITNO_32
3419 #undef BITNO_16
3420 #undef BITNO_8
3421 #undef BITNO_4
3422 #undef BITNO_2
3423 #undef BIT
3424 }
3425
3426 static u_int
3427 ieee802_11_radio_avs_print(netdissect_options *ndo,
3428 const u_char *p, u_int length, u_int caplen)
3429 {
3430 uint32_t caphdr_len;
3431
3432 ndo->ndo_protocol = "802.11_radio_avs";
3433 if (caplen < 8) {
3434 nd_print_trunc(ndo);
3435 return caplen;
3436 }
3437
3438 caphdr_len = GET_BE_U_4(p + 4);
3439 if (caphdr_len < 8) {
3440 /*
3441 * Yow! The capture header length is claimed not
3442 * to be large enough to include even the version
3443 * cookie or capture header length!
3444 */
3445 nd_print_trunc(ndo);
3446 return caplen;
3447 }
3448
3449 if (caplen < caphdr_len) {
3450 nd_print_trunc(ndo);
3451 return caplen;
3452 }
3453
3454 return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
3455 length - caphdr_len, caplen - caphdr_len, 0, 0);
3456 }
3457
3458 #define PRISM_HDR_LEN 144
3459
3460 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
3461 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
3462 #define WLANCAP_MAGIC_COOKIE_V2 0x80211002
3463
3464 /*
3465 * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
3466 * containing information such as radio information, which we
3467 * currently ignore.
3468 *
3469 * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
3470 * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
3471 * (currently, on Linux, there's no ARPHRD_ type for
3472 * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
3473 * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
3474 * the AVS header, and the first 4 bytes of the header are used to
3475 * indicate whether it's a Prism header or an AVS header).
3476 */
3477 void
3478 prism_if_print(netdissect_options *ndo,
3479 const struct pcap_pkthdr *h, const u_char *p)
3480 {
3481 u_int caplen = h->caplen;
3482 u_int length = h->len;
3483 uint32_t msgcode;
3484
3485 ndo->ndo_protocol = "prism";
3486 if (caplen < 4) {
3487 nd_print_trunc(ndo);
3488 ndo->ndo_ll_hdr_len += caplen;
3489 return;
3490 }
3491
3492 msgcode = GET_BE_U_4(p);
3493 if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
3494 msgcode == WLANCAP_MAGIC_COOKIE_V2) {
3495 ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
3496 return;
3497 }
3498
3499 if (caplen < PRISM_HDR_LEN) {
3500 nd_print_trunc(ndo);
3501 ndo->ndo_ll_hdr_len += caplen;
3502 return;
3503 }
3504
3505 p += PRISM_HDR_LEN;
3506 length -= PRISM_HDR_LEN;
3507 caplen -= PRISM_HDR_LEN;
3508 ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
3509 ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
3510 }
3511
3512 /*
3513 * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
3514 * header, containing information such as radio information.
3515 */
3516 void
3517 ieee802_11_radio_if_print(netdissect_options *ndo,
3518 const struct pcap_pkthdr *h, const u_char *p)
3519 {
3520 ndo->ndo_protocol = "802.11_radio";
3521 ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
3522 }
3523
3524 /*
3525 * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
3526 * extra header, containing information such as radio information,
3527 * which we currently ignore.
3528 */
3529 void
3530 ieee802_11_radio_avs_if_print(netdissect_options *ndo,
3531 const struct pcap_pkthdr *h, const u_char *p)
3532 {
3533 ndo->ndo_protocol = "802.11_radio_avs";
3534 ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
3535 }