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