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