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