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