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