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