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