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