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