141c99275SPeter Avalos /*
241c99275SPeter Avalos * Copyright (c) 2001
341c99275SPeter Avalos * Fortress Technologies, Inc. All rights reserved.
441c99275SPeter Avalos * Charlie Lenahan (clenahan@fortresstech.com)
541c99275SPeter Avalos *
641c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
741c99275SPeter Avalos * modification, are permitted provided that: (1) source code distributions
841c99275SPeter Avalos * retain the above copyright notice and this paragraph in its entirety, (2)
941c99275SPeter Avalos * distributions including binary code include the above copyright notice and
1041c99275SPeter Avalos * this paragraph in its entirety in the documentation or other materials
1141c99275SPeter Avalos * provided with the distribution, and (3) all advertising materials mentioning
1241c99275SPeter Avalos * features or use of this software display the following acknowledgement:
1341c99275SPeter Avalos * ``This product includes software developed by the University of California,
1441c99275SPeter Avalos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1541c99275SPeter Avalos * the University nor the names of its contributors may be used to endorse
1641c99275SPeter Avalos * or promote products derived from this software without specific prior
1741c99275SPeter Avalos * written permission.
1841c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1941c99275SPeter Avalos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
2041c99275SPeter Avalos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2141c99275SPeter Avalos */
2241c99275SPeter Avalos
23411677aeSAaron LI /* \summary: IEEE 802.11 printer */
2441c99275SPeter Avalos
2541c99275SPeter Avalos #ifdef HAVE_CONFIG_H
26*ed775ee7SAntonio Huete Jimenez #include <config.h>
2741c99275SPeter Avalos #endif
2841c99275SPeter Avalos
29*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3041c99275SPeter Avalos
3141c99275SPeter Avalos #include <string.h>
3241c99275SPeter Avalos
33411677aeSAaron LI #include "netdissect.h"
3441c99275SPeter Avalos #include "addrtoname.h"
3541c99275SPeter Avalos
3641c99275SPeter Avalos #include "extract.h"
3741c99275SPeter Avalos
3841c99275SPeter Avalos #include "cpack.h"
3941c99275SPeter Avalos
4041c99275SPeter Avalos
41411677aeSAaron LI /* Lengths of 802.11 header components. */
42411677aeSAaron LI #define IEEE802_11_FC_LEN 2
43411677aeSAaron LI #define IEEE802_11_DUR_LEN 2
44411677aeSAaron LI #define IEEE802_11_DA_LEN 6
45411677aeSAaron LI #define IEEE802_11_SA_LEN 6
46411677aeSAaron LI #define IEEE802_11_BSSID_LEN 6
47411677aeSAaron LI #define IEEE802_11_RA_LEN 6
48411677aeSAaron LI #define IEEE802_11_TA_LEN 6
49411677aeSAaron LI #define IEEE802_11_ADDR1_LEN 6
50411677aeSAaron LI #define IEEE802_11_SEQ_LEN 2
51411677aeSAaron LI #define IEEE802_11_CTL_LEN 2
52411677aeSAaron LI #define IEEE802_11_CARRIED_FC_LEN 2
53411677aeSAaron LI #define IEEE802_11_HT_CONTROL_LEN 4
54411677aeSAaron LI #define IEEE802_11_IV_LEN 3
55411677aeSAaron LI #define IEEE802_11_KID_LEN 1
5627bfbee1SPeter Avalos
57411677aeSAaron LI /* Frame check sequence length. */
58411677aeSAaron LI #define IEEE802_11_FCS_LEN 4
59411677aeSAaron LI
60411677aeSAaron LI /* Lengths of beacon components. */
61411677aeSAaron LI #define IEEE802_11_TSTAMP_LEN 8
62411677aeSAaron LI #define IEEE802_11_BCNINT_LEN 2
63411677aeSAaron LI #define IEEE802_11_CAPINFO_LEN 2
64411677aeSAaron LI #define IEEE802_11_LISTENINT_LEN 2
65411677aeSAaron LI
66411677aeSAaron LI #define IEEE802_11_AID_LEN 2
67411677aeSAaron LI #define IEEE802_11_STATUS_LEN 2
68411677aeSAaron LI #define IEEE802_11_REASON_LEN 2
69411677aeSAaron LI
70411677aeSAaron LI /* Length of previous AP in reassocation frame */
71411677aeSAaron LI #define IEEE802_11_AP_LEN 6
72411677aeSAaron LI
73411677aeSAaron LI #define T_MGMT 0x0 /* management */
74411677aeSAaron LI #define T_CTRL 0x1 /* control */
75411677aeSAaron LI #define T_DATA 0x2 /* data */
76411677aeSAaron LI #define T_RESV 0x3 /* reserved */
77411677aeSAaron LI
78411677aeSAaron LI #define ST_ASSOC_REQUEST 0x0
79411677aeSAaron LI #define ST_ASSOC_RESPONSE 0x1
80411677aeSAaron LI #define ST_REASSOC_REQUEST 0x2
81411677aeSAaron LI #define ST_REASSOC_RESPONSE 0x3
82411677aeSAaron LI #define ST_PROBE_REQUEST 0x4
83411677aeSAaron LI #define ST_PROBE_RESPONSE 0x5
84411677aeSAaron LI /* RESERVED 0x6 */
85411677aeSAaron LI /* RESERVED 0x7 */
86411677aeSAaron LI #define ST_BEACON 0x8
87411677aeSAaron LI #define ST_ATIM 0x9
88411677aeSAaron LI #define ST_DISASSOC 0xA
89411677aeSAaron LI #define ST_AUTH 0xB
90411677aeSAaron LI #define ST_DEAUTH 0xC
91411677aeSAaron LI #define ST_ACTION 0xD
92411677aeSAaron LI /* RESERVED 0xE */
93411677aeSAaron LI /* RESERVED 0xF */
94411677aeSAaron LI
95411677aeSAaron LI static const struct tok st_str[] = {
96411677aeSAaron LI { ST_ASSOC_REQUEST, "Assoc Request" },
97411677aeSAaron LI { ST_ASSOC_RESPONSE, "Assoc Response" },
98411677aeSAaron LI { ST_REASSOC_REQUEST, "ReAssoc Request" },
99411677aeSAaron LI { ST_REASSOC_RESPONSE, "ReAssoc Response" },
100411677aeSAaron LI { ST_PROBE_REQUEST, "Probe Request" },
101411677aeSAaron LI { ST_PROBE_RESPONSE, "Probe Response" },
102411677aeSAaron LI { ST_BEACON, "Beacon" },
103411677aeSAaron LI { ST_ATIM, "ATIM" },
104411677aeSAaron LI { ST_DISASSOC, "Disassociation" },
105411677aeSAaron LI { ST_AUTH, "Authentication" },
106411677aeSAaron LI { ST_DEAUTH, "DeAuthentication" },
107411677aeSAaron LI { ST_ACTION, "Action" },
108411677aeSAaron LI { 0, NULL }
10927bfbee1SPeter Avalos };
11027bfbee1SPeter Avalos
111411677aeSAaron LI #define CTRL_CONTROL_WRAPPER 0x7
112411677aeSAaron LI #define CTRL_BAR 0x8
113411677aeSAaron LI #define CTRL_BA 0x9
114411677aeSAaron LI #define CTRL_PS_POLL 0xA
115411677aeSAaron LI #define CTRL_RTS 0xB
116411677aeSAaron LI #define CTRL_CTS 0xC
117411677aeSAaron LI #define CTRL_ACK 0xD
118411677aeSAaron LI #define CTRL_CF_END 0xE
119411677aeSAaron LI #define CTRL_END_ACK 0xF
120411677aeSAaron LI
121411677aeSAaron LI static const struct tok ctrl_str[] = {
122411677aeSAaron LI { CTRL_CONTROL_WRAPPER, "Control Wrapper" },
123411677aeSAaron LI { CTRL_BAR, "BAR" },
124411677aeSAaron LI { CTRL_BA, "BA" },
125411677aeSAaron LI { CTRL_PS_POLL, "Power Save-Poll" },
126411677aeSAaron LI { CTRL_RTS, "Request-To-Send" },
127411677aeSAaron LI { CTRL_CTS, "Clear-To-Send" },
128411677aeSAaron LI { CTRL_ACK, "Acknowledgment" },
129411677aeSAaron LI { CTRL_CF_END, "CF-End" },
130411677aeSAaron LI { CTRL_END_ACK, "CF-End+CF-Ack" },
131411677aeSAaron LI { 0, NULL }
132411677aeSAaron LI };
133411677aeSAaron LI
134411677aeSAaron LI #define DATA_DATA 0x0
135411677aeSAaron LI #define DATA_DATA_CF_ACK 0x1
136411677aeSAaron LI #define DATA_DATA_CF_POLL 0x2
137411677aeSAaron LI #define DATA_DATA_CF_ACK_POLL 0x3
138411677aeSAaron LI #define DATA_NODATA 0x4
139411677aeSAaron LI #define DATA_NODATA_CF_ACK 0x5
140411677aeSAaron LI #define DATA_NODATA_CF_POLL 0x6
141411677aeSAaron LI #define DATA_NODATA_CF_ACK_POLL 0x7
142411677aeSAaron LI
143411677aeSAaron LI #define DATA_QOS_DATA 0x8
144411677aeSAaron LI #define DATA_QOS_DATA_CF_ACK 0x9
145411677aeSAaron LI #define DATA_QOS_DATA_CF_POLL 0xA
146411677aeSAaron LI #define DATA_QOS_DATA_CF_ACK_POLL 0xB
147411677aeSAaron LI #define DATA_QOS_NODATA 0xC
148411677aeSAaron LI #define DATA_QOS_CF_POLL_NODATA 0xE
149411677aeSAaron LI #define DATA_QOS_CF_ACK_POLL_NODATA 0xF
150411677aeSAaron LI
151411677aeSAaron LI /*
152411677aeSAaron LI * The subtype field of a data frame is, in effect, composed of 4 flag
153411677aeSAaron LI * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
154411677aeSAaron LI * any data), and QoS.
155411677aeSAaron LI */
156411677aeSAaron LI #define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01)
157411677aeSAaron LI #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02)
158411677aeSAaron LI #define DATA_FRAME_IS_NULL(x) ((x) & 0x04)
159411677aeSAaron LI #define DATA_FRAME_IS_QOS(x) ((x) & 0x08)
160411677aeSAaron LI
161411677aeSAaron LI /*
162411677aeSAaron LI * Bits in the frame control field.
163411677aeSAaron LI */
164411677aeSAaron LI #define FC_VERSION(fc) ((fc) & 0x3)
165411677aeSAaron LI #define FC_TYPE(fc) (((fc) >> 2) & 0x3)
166411677aeSAaron LI #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF)
167411677aeSAaron LI #define FC_TO_DS(fc) ((fc) & 0x0100)
168411677aeSAaron LI #define FC_FROM_DS(fc) ((fc) & 0x0200)
169411677aeSAaron LI #define FC_MORE_FLAG(fc) ((fc) & 0x0400)
170411677aeSAaron LI #define FC_RETRY(fc) ((fc) & 0x0800)
171411677aeSAaron LI #define FC_POWER_MGMT(fc) ((fc) & 0x1000)
172411677aeSAaron LI #define FC_MORE_DATA(fc) ((fc) & 0x2000)
173411677aeSAaron LI #define FC_PROTECTED(fc) ((fc) & 0x4000)
174411677aeSAaron LI #define FC_ORDER(fc) ((fc) & 0x8000)
175411677aeSAaron LI
176411677aeSAaron LI struct mgmt_header_t {
177*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
178*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
179*ed775ee7SAntonio Huete Jimenez nd_mac_addr da;
180*ed775ee7SAntonio Huete Jimenez nd_mac_addr sa;
181*ed775ee7SAntonio Huete Jimenez nd_mac_addr bssid;
182*ed775ee7SAntonio Huete Jimenez nd_uint16_t seq_ctrl;
183411677aeSAaron LI };
184411677aeSAaron LI
185411677aeSAaron LI #define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
186411677aeSAaron LI IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\
187411677aeSAaron LI IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN)
188411677aeSAaron LI
189411677aeSAaron LI #define CAPABILITY_ESS(cap) ((cap) & 0x0001)
190411677aeSAaron LI #define CAPABILITY_IBSS(cap) ((cap) & 0x0002)
191411677aeSAaron LI #define CAPABILITY_CFP(cap) ((cap) & 0x0004)
192411677aeSAaron LI #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008)
193411677aeSAaron LI #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010)
194411677aeSAaron LI
195411677aeSAaron LI struct ssid_t {
196411677aeSAaron LI uint8_t element_id;
197411677aeSAaron LI uint8_t length;
198411677aeSAaron LI u_char ssid[33]; /* 32 + 1 for null */
199411677aeSAaron LI };
200411677aeSAaron LI
201411677aeSAaron LI struct rates_t {
202411677aeSAaron LI uint8_t element_id;
203411677aeSAaron LI uint8_t length;
204411677aeSAaron LI uint8_t rate[16];
205411677aeSAaron LI };
206411677aeSAaron LI
207411677aeSAaron LI struct challenge_t {
208411677aeSAaron LI uint8_t element_id;
209411677aeSAaron LI uint8_t length;
210411677aeSAaron LI uint8_t text[254]; /* 1-253 + 1 for null */
211411677aeSAaron LI };
212411677aeSAaron LI
213411677aeSAaron LI struct fh_t {
214411677aeSAaron LI uint8_t element_id;
215411677aeSAaron LI uint8_t length;
216411677aeSAaron LI uint16_t dwell_time;
217411677aeSAaron LI uint8_t hop_set;
218411677aeSAaron LI uint8_t hop_pattern;
219411677aeSAaron LI uint8_t hop_index;
220411677aeSAaron LI };
221411677aeSAaron LI
222411677aeSAaron LI struct ds_t {
223411677aeSAaron LI uint8_t element_id;
224411677aeSAaron LI uint8_t length;
225411677aeSAaron LI uint8_t channel;
226411677aeSAaron LI };
227411677aeSAaron LI
228411677aeSAaron LI struct cf_t {
229411677aeSAaron LI uint8_t element_id;
230411677aeSAaron LI uint8_t length;
231411677aeSAaron LI uint8_t count;
232411677aeSAaron LI uint8_t period;
233411677aeSAaron LI uint16_t max_duration;
234*ed775ee7SAntonio Huete Jimenez uint16_t dur_remaining;
235411677aeSAaron LI };
236411677aeSAaron LI
237411677aeSAaron LI struct tim_t {
238411677aeSAaron LI uint8_t element_id;
239411677aeSAaron LI uint8_t length;
240411677aeSAaron LI uint8_t count;
241411677aeSAaron LI uint8_t period;
242411677aeSAaron LI uint8_t bitmap_control;
243411677aeSAaron LI uint8_t bitmap[251];
244411677aeSAaron LI };
245411677aeSAaron LI
246411677aeSAaron LI #define E_SSID 0
247411677aeSAaron LI #define E_RATES 1
248411677aeSAaron LI #define E_FH 2
249411677aeSAaron LI #define E_DS 3
250411677aeSAaron LI #define E_CF 4
251411677aeSAaron LI #define E_TIM 5
252411677aeSAaron LI #define E_IBSS 6
253411677aeSAaron LI /* reserved 7 */
254411677aeSAaron LI /* reserved 8 */
255411677aeSAaron LI /* reserved 9 */
256411677aeSAaron LI /* reserved 10 */
257411677aeSAaron LI /* reserved 11 */
258411677aeSAaron LI /* reserved 12 */
259411677aeSAaron LI /* reserved 13 */
260411677aeSAaron LI /* reserved 14 */
261411677aeSAaron LI /* reserved 15 */
262411677aeSAaron LI /* reserved 16 */
263411677aeSAaron LI
264411677aeSAaron LI #define E_CHALLENGE 16
265411677aeSAaron LI /* reserved 17 */
266411677aeSAaron LI /* reserved 18 */
267411677aeSAaron LI /* reserved 19 */
268411677aeSAaron LI /* reserved 16 */
269411677aeSAaron LI /* reserved 16 */
270411677aeSAaron LI
271411677aeSAaron LI
272411677aeSAaron LI struct mgmt_body_t {
273411677aeSAaron LI uint8_t timestamp[IEEE802_11_TSTAMP_LEN];
274411677aeSAaron LI uint16_t beacon_interval;
275411677aeSAaron LI uint16_t listen_interval;
276411677aeSAaron LI uint16_t status_code;
277411677aeSAaron LI uint16_t aid;
278411677aeSAaron LI u_char ap[IEEE802_11_AP_LEN];
279411677aeSAaron LI uint16_t reason_code;
280411677aeSAaron LI uint16_t auth_alg;
281411677aeSAaron LI uint16_t auth_trans_seq_num;
282411677aeSAaron LI int challenge_present;
283411677aeSAaron LI struct challenge_t challenge;
284411677aeSAaron LI uint16_t capability_info;
285411677aeSAaron LI int ssid_present;
286411677aeSAaron LI struct ssid_t ssid;
287411677aeSAaron LI int rates_present;
288411677aeSAaron LI struct rates_t rates;
289411677aeSAaron LI int ds_present;
290411677aeSAaron LI struct ds_t ds;
291411677aeSAaron LI int cf_present;
292411677aeSAaron LI struct cf_t cf;
293411677aeSAaron LI int fh_present;
294411677aeSAaron LI struct fh_t fh;
295411677aeSAaron LI int tim_present;
296411677aeSAaron LI struct tim_t tim;
297411677aeSAaron LI };
298411677aeSAaron LI
299411677aeSAaron LI struct ctrl_control_wrapper_hdr_t {
300*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
301*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
302*ed775ee7SAntonio Huete Jimenez nd_mac_addr addr1;
303*ed775ee7SAntonio Huete Jimenez nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN];
304*ed775ee7SAntonio Huete Jimenez nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN];
305411677aeSAaron LI };
306411677aeSAaron LI
307411677aeSAaron LI #define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
308411677aeSAaron LI IEEE802_11_ADDR1_LEN+\
309411677aeSAaron LI IEEE802_11_CARRIED_FC_LEN+\
310411677aeSAaron LI IEEE802_11_HT_CONTROL_LEN)
311411677aeSAaron LI
312411677aeSAaron LI struct ctrl_rts_hdr_t {
313*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
314*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
315*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
316*ed775ee7SAntonio Huete Jimenez nd_mac_addr ta;
317411677aeSAaron LI };
318411677aeSAaron LI
319411677aeSAaron LI #define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
320411677aeSAaron LI IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
321411677aeSAaron LI
322411677aeSAaron LI struct ctrl_cts_hdr_t {
323*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
324*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
325*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
326411677aeSAaron LI };
327411677aeSAaron LI
328411677aeSAaron LI #define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
329411677aeSAaron LI
330411677aeSAaron LI struct ctrl_ack_hdr_t {
331*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
332*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
333*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
334411677aeSAaron LI };
335411677aeSAaron LI
336411677aeSAaron LI #define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
337411677aeSAaron LI
338411677aeSAaron LI struct ctrl_ps_poll_hdr_t {
339*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
340*ed775ee7SAntonio Huete Jimenez nd_uint16_t aid;
341*ed775ee7SAntonio Huete Jimenez nd_mac_addr bssid;
342*ed775ee7SAntonio Huete Jimenez nd_mac_addr ta;
343411677aeSAaron LI };
344411677aeSAaron LI
345411677aeSAaron LI #define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
346411677aeSAaron LI IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN)
347411677aeSAaron LI
348411677aeSAaron LI struct ctrl_end_hdr_t {
349*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
350*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
351*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
352*ed775ee7SAntonio Huete Jimenez nd_mac_addr bssid;
353411677aeSAaron LI };
354411677aeSAaron LI
355411677aeSAaron LI #define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
356411677aeSAaron LI IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
357411677aeSAaron LI
358411677aeSAaron LI struct ctrl_end_ack_hdr_t {
359*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
360*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
361*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
362*ed775ee7SAntonio Huete Jimenez nd_mac_addr bssid;
363411677aeSAaron LI };
364411677aeSAaron LI
365411677aeSAaron LI #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
366411677aeSAaron LI IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
367411677aeSAaron LI
368411677aeSAaron LI struct ctrl_ba_hdr_t {
369*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
370*ed775ee7SAntonio Huete Jimenez nd_uint16_t duration;
371*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
372411677aeSAaron LI };
373411677aeSAaron LI
374411677aeSAaron LI #define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
375411677aeSAaron LI
376411677aeSAaron LI struct ctrl_bar_hdr_t {
377*ed775ee7SAntonio Huete Jimenez nd_uint16_t fc;
378*ed775ee7SAntonio Huete Jimenez nd_uint16_t dur;
379*ed775ee7SAntonio Huete Jimenez nd_mac_addr ra;
380*ed775ee7SAntonio Huete Jimenez nd_mac_addr ta;
381*ed775ee7SAntonio Huete Jimenez nd_uint16_t ctl;
382*ed775ee7SAntonio Huete Jimenez nd_uint16_t seq;
383411677aeSAaron LI };
384411677aeSAaron LI
385411677aeSAaron LI #define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
386411677aeSAaron LI IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\
387411677aeSAaron LI IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN)
388411677aeSAaron LI
389411677aeSAaron LI struct meshcntl_t {
390*ed775ee7SAntonio Huete Jimenez nd_uint8_t flags;
391*ed775ee7SAntonio Huete Jimenez nd_uint8_t ttl;
392*ed775ee7SAntonio Huete Jimenez nd_uint32_t seq;
393*ed775ee7SAntonio Huete Jimenez nd_mac_addr addr4;
394*ed775ee7SAntonio Huete Jimenez nd_mac_addr addr5;
395*ed775ee7SAntonio Huete Jimenez nd_mac_addr addr6;
396411677aeSAaron LI };
397411677aeSAaron LI
398411677aeSAaron LI #define IV_IV(iv) ((iv) & 0xFFFFFF)
399411677aeSAaron LI #define IV_PAD(iv) (((iv) >> 24) & 0x3F)
400411677aeSAaron LI #define IV_KEYID(iv) (((iv) >> 30) & 0x03)
401411677aeSAaron LI
40241c99275SPeter Avalos #define PRINT_SSID(p) \
40327bfbee1SPeter Avalos if (p.ssid_present) { \
404*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ("); \
405*ed775ee7SAntonio Huete Jimenez fn_print_str(ndo, p.ssid.ssid); \
406*ed775ee7SAntonio Huete Jimenez ND_PRINT(")"); \
40741c99275SPeter Avalos }
40841c99275SPeter Avalos
40941c99275SPeter Avalos #define PRINT_RATE(_sep, _r, _suf) \
410*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
41141c99275SPeter Avalos #define PRINT_RATES(p) \
41227bfbee1SPeter Avalos if (p.rates_present) { \
41341c99275SPeter Avalos int z; \
41441c99275SPeter Avalos const char *sep = " ["; \
41541c99275SPeter Avalos for (z = 0; z < p.rates.length ; z++) { \
41641c99275SPeter Avalos PRINT_RATE(sep, p.rates.rate[z], \
41741c99275SPeter Avalos (p.rates.rate[z] & 0x80 ? "*" : "")); \
41841c99275SPeter Avalos sep = " "; \
41941c99275SPeter Avalos } \
42041c99275SPeter Avalos if (p.rates.length != 0) \
421*ed775ee7SAntonio Huete Jimenez ND_PRINT(" Mbit]"); \
42241c99275SPeter Avalos }
42341c99275SPeter Avalos
42441c99275SPeter Avalos #define PRINT_DS_CHANNEL(p) \
42527bfbee1SPeter Avalos if (p.ds_present) \
426*ed775ee7SAntonio Huete Jimenez ND_PRINT(" CH: %u", p.ds.channel); \
427*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", \
428*ed775ee7SAntonio Huete Jimenez CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
42941c99275SPeter Avalos
43027bfbee1SPeter Avalos #define MAX_MCS_INDEX 76
43127bfbee1SPeter Avalos
43227bfbee1SPeter Avalos /*
43327bfbee1SPeter Avalos * Indices are:
43427bfbee1SPeter Avalos *
43527bfbee1SPeter Avalos * the MCS index (0-76);
43627bfbee1SPeter Avalos *
43727bfbee1SPeter Avalos * 0 for 20 MHz, 1 for 40 MHz;
43827bfbee1SPeter Avalos *
43927bfbee1SPeter Avalos * 0 for a long guard interval, 1 for a short guard interval.
44027bfbee1SPeter Avalos */
44127bfbee1SPeter Avalos static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
44227bfbee1SPeter Avalos /* MCS 0 */
443*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, },
444*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, },
44527bfbee1SPeter Avalos },
44627bfbee1SPeter Avalos
44727bfbee1SPeter Avalos /* MCS 1 */
448*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
449*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
45027bfbee1SPeter Avalos },
45127bfbee1SPeter Avalos
45227bfbee1SPeter Avalos /* MCS 2 */
453*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
454*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
45527bfbee1SPeter Avalos },
45627bfbee1SPeter Avalos
45727bfbee1SPeter Avalos /* MCS 3 */
458*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
459*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
46027bfbee1SPeter Avalos },
46127bfbee1SPeter Avalos
46227bfbee1SPeter Avalos /* MCS 4 */
463*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
464*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
46527bfbee1SPeter Avalos },
46627bfbee1SPeter Avalos
46727bfbee1SPeter Avalos /* MCS 5 */
468*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
469*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
47027bfbee1SPeter Avalos },
47127bfbee1SPeter Avalos
47227bfbee1SPeter Avalos /* MCS 6 */
473*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
474*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
47527bfbee1SPeter Avalos },
47627bfbee1SPeter Avalos
47727bfbee1SPeter Avalos /* MCS 7 */
478*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
479*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
48027bfbee1SPeter Avalos },
48127bfbee1SPeter Avalos
48227bfbee1SPeter Avalos /* MCS 8 */
483*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
484*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
48527bfbee1SPeter Avalos },
48627bfbee1SPeter Avalos
48727bfbee1SPeter Avalos /* MCS 9 */
488*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
489*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
49027bfbee1SPeter Avalos },
49127bfbee1SPeter Avalos
49227bfbee1SPeter Avalos /* MCS 10 */
493*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
494*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
49527bfbee1SPeter Avalos },
49627bfbee1SPeter Avalos
49727bfbee1SPeter Avalos /* MCS 11 */
498*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
499*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
50027bfbee1SPeter Avalos },
50127bfbee1SPeter Avalos
50227bfbee1SPeter Avalos /* MCS 12 */
503*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
504*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
50527bfbee1SPeter Avalos },
50627bfbee1SPeter Avalos
50727bfbee1SPeter Avalos /* MCS 13 */
508*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
509*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
51027bfbee1SPeter Avalos },
51127bfbee1SPeter Avalos
51227bfbee1SPeter Avalos /* MCS 14 */
513*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
514*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
51527bfbee1SPeter Avalos },
51627bfbee1SPeter Avalos
51727bfbee1SPeter Avalos /* MCS 15 */
518*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
519*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
52027bfbee1SPeter Avalos },
52127bfbee1SPeter Avalos
52227bfbee1SPeter Avalos /* MCS 16 */
523*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
524*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
52527bfbee1SPeter Avalos },
52627bfbee1SPeter Avalos
52727bfbee1SPeter Avalos /* MCS 17 */
528*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
529*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
53027bfbee1SPeter Avalos },
53127bfbee1SPeter Avalos
53227bfbee1SPeter Avalos /* MCS 18 */
533*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
534*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
53527bfbee1SPeter Avalos },
53627bfbee1SPeter Avalos
53727bfbee1SPeter Avalos /* MCS 19 */
538*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
539*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
54027bfbee1SPeter Avalos },
54127bfbee1SPeter Avalos
54227bfbee1SPeter Avalos /* MCS 20 */
543*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
544*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
54527bfbee1SPeter Avalos },
54627bfbee1SPeter Avalos
54727bfbee1SPeter Avalos /* MCS 21 */
548*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
549*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
55027bfbee1SPeter Avalos },
55127bfbee1SPeter Avalos
55227bfbee1SPeter Avalos /* MCS 22 */
553*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
554*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
55527bfbee1SPeter Avalos },
55627bfbee1SPeter Avalos
55727bfbee1SPeter Avalos /* MCS 23 */
558*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
559*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
56027bfbee1SPeter Avalos },
56127bfbee1SPeter Avalos
56227bfbee1SPeter Avalos /* MCS 24 */
563*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
564*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
56527bfbee1SPeter Avalos },
56627bfbee1SPeter Avalos
56727bfbee1SPeter Avalos /* MCS 25 */
568*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
569*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
57027bfbee1SPeter Avalos },
57127bfbee1SPeter Avalos
57227bfbee1SPeter Avalos /* MCS 26 */
573*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
574*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
57527bfbee1SPeter Avalos },
57627bfbee1SPeter Avalos
57727bfbee1SPeter Avalos /* MCS 27 */
578*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
579*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
58027bfbee1SPeter Avalos },
58127bfbee1SPeter Avalos
58227bfbee1SPeter Avalos /* MCS 28 */
583*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
584*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
58527bfbee1SPeter Avalos },
58627bfbee1SPeter Avalos
58727bfbee1SPeter Avalos /* MCS 29 */
588*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, },
589*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, },
59027bfbee1SPeter Avalos },
59127bfbee1SPeter Avalos
59227bfbee1SPeter Avalos /* MCS 30 */
593*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, },
594*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, },
59527bfbee1SPeter Avalos },
59627bfbee1SPeter Avalos
59727bfbee1SPeter Avalos /* MCS 31 */
598*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, },
599*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, },
60027bfbee1SPeter Avalos },
60127bfbee1SPeter Avalos
60227bfbee1SPeter Avalos /* MCS 32 */
603*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */
604*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, },
60527bfbee1SPeter Avalos },
60627bfbee1SPeter Avalos
60727bfbee1SPeter Avalos /* MCS 33 */
608*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
609*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
61027bfbee1SPeter Avalos },
61127bfbee1SPeter Avalos
61227bfbee1SPeter Avalos /* MCS 34 */
613*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
614*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
61527bfbee1SPeter Avalos },
61627bfbee1SPeter Avalos
61727bfbee1SPeter Avalos /* MCS 35 */
618*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
619*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
62027bfbee1SPeter Avalos },
62127bfbee1SPeter Avalos
62227bfbee1SPeter Avalos /* MCS 36 */
623*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
624*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
62527bfbee1SPeter Avalos },
62627bfbee1SPeter Avalos
62727bfbee1SPeter Avalos /* MCS 37 */
628*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
629*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
63027bfbee1SPeter Avalos },
63127bfbee1SPeter Avalos
63227bfbee1SPeter Avalos /* MCS 38 */
633*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
634*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
63527bfbee1SPeter Avalos },
63627bfbee1SPeter Avalos
63727bfbee1SPeter Avalos /* MCS 39 */
638*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
639*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
64027bfbee1SPeter Avalos },
64127bfbee1SPeter Avalos
64227bfbee1SPeter Avalos /* MCS 40 */
643*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
644*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
64527bfbee1SPeter Avalos },
64627bfbee1SPeter Avalos
64727bfbee1SPeter Avalos /* MCS 41 */
648*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
649*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
65027bfbee1SPeter Avalos },
65127bfbee1SPeter Avalos
65227bfbee1SPeter Avalos /* MCS 42 */
653*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
654*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
65527bfbee1SPeter Avalos },
65627bfbee1SPeter Avalos
65727bfbee1SPeter Avalos /* MCS 43 */
658*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
659*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
66027bfbee1SPeter Avalos },
66127bfbee1SPeter Avalos
66227bfbee1SPeter Avalos /* MCS 44 */
663*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
664*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
66527bfbee1SPeter Avalos },
66627bfbee1SPeter Avalos
66727bfbee1SPeter Avalos /* MCS 45 */
668*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
669*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
67027bfbee1SPeter Avalos },
67127bfbee1SPeter Avalos
67227bfbee1SPeter Avalos /* MCS 46 */
673*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
674*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
67527bfbee1SPeter Avalos },
67627bfbee1SPeter Avalos
67727bfbee1SPeter Avalos /* MCS 47 */
678*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
679*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
68027bfbee1SPeter Avalos },
68127bfbee1SPeter Avalos
68227bfbee1SPeter Avalos /* MCS 48 */
683*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
684*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
68527bfbee1SPeter Avalos },
68627bfbee1SPeter Avalos
68727bfbee1SPeter Avalos /* MCS 49 */
688*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
689*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
69027bfbee1SPeter Avalos },
69127bfbee1SPeter Avalos
69227bfbee1SPeter Avalos /* MCS 50 */
693*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
694*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
69527bfbee1SPeter Avalos },
69627bfbee1SPeter Avalos
69727bfbee1SPeter Avalos /* MCS 51 */
698*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
699*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
70027bfbee1SPeter Avalos },
70127bfbee1SPeter Avalos
70227bfbee1SPeter Avalos /* MCS 52 */
703*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
704*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
70527bfbee1SPeter Avalos },
70627bfbee1SPeter Avalos
70727bfbee1SPeter Avalos /* MCS 53 */
708*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
709*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
71027bfbee1SPeter Avalos },
71127bfbee1SPeter Avalos
71227bfbee1SPeter Avalos /* MCS 54 */
713*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
714*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
71527bfbee1SPeter Avalos },
71627bfbee1SPeter Avalos
71727bfbee1SPeter Avalos /* MCS 55 */
718*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
719*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
72027bfbee1SPeter Avalos },
72127bfbee1SPeter Avalos
72227bfbee1SPeter Avalos /* MCS 56 */
723*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
724*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
72527bfbee1SPeter Avalos },
72627bfbee1SPeter Avalos
72727bfbee1SPeter Avalos /* MCS 57 */
728*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
729*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
73027bfbee1SPeter Avalos },
73127bfbee1SPeter Avalos
73227bfbee1SPeter Avalos /* MCS 58 */
733*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
734*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
73527bfbee1SPeter Avalos },
73627bfbee1SPeter Avalos
73727bfbee1SPeter Avalos /* MCS 59 */
738*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
739*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
74027bfbee1SPeter Avalos },
74127bfbee1SPeter Avalos
74227bfbee1SPeter Avalos /* MCS 60 */
743*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
744*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
74527bfbee1SPeter Avalos },
74627bfbee1SPeter Avalos
74727bfbee1SPeter Avalos /* MCS 61 */
748*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
749*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
75027bfbee1SPeter Avalos },
75127bfbee1SPeter Avalos
75227bfbee1SPeter Avalos /* MCS 62 */
753*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
754*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
75527bfbee1SPeter Avalos },
75627bfbee1SPeter Avalos
75727bfbee1SPeter Avalos /* MCS 63 */
758*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
759*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
76027bfbee1SPeter Avalos },
76127bfbee1SPeter Avalos
76227bfbee1SPeter Avalos /* MCS 64 */
763*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, },
764*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, },
76527bfbee1SPeter Avalos },
76627bfbee1SPeter Avalos
76727bfbee1SPeter Avalos /* MCS 65 */
768*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
769*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
77027bfbee1SPeter Avalos },
77127bfbee1SPeter Avalos
77227bfbee1SPeter Avalos /* MCS 66 */
773*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
774*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
77527bfbee1SPeter Avalos },
77627bfbee1SPeter Avalos
77727bfbee1SPeter Avalos /* MCS 67 */
778*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
779*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
78027bfbee1SPeter Avalos },
78127bfbee1SPeter Avalos
78227bfbee1SPeter Avalos /* MCS 68 */
783*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
784*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
78527bfbee1SPeter Avalos },
78627bfbee1SPeter Avalos
78727bfbee1SPeter Avalos /* MCS 69 */
788*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
789*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
79027bfbee1SPeter Avalos },
79127bfbee1SPeter Avalos
79227bfbee1SPeter Avalos /* MCS 70 */
793*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
794*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
79527bfbee1SPeter Avalos },
79627bfbee1SPeter Avalos
79727bfbee1SPeter Avalos /* MCS 71 */
798*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
799*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
80027bfbee1SPeter Avalos },
80127bfbee1SPeter Avalos
80227bfbee1SPeter Avalos /* MCS 72 */
803*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
804*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
80527bfbee1SPeter Avalos },
80627bfbee1SPeter Avalos
80727bfbee1SPeter Avalos /* MCS 73 */
808*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
809*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
81027bfbee1SPeter Avalos },
81127bfbee1SPeter Avalos
81227bfbee1SPeter Avalos /* MCS 74 */
813*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
814*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
81527bfbee1SPeter Avalos },
81627bfbee1SPeter Avalos
81727bfbee1SPeter Avalos /* MCS 75 */
818*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
819*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
82027bfbee1SPeter Avalos },
82127bfbee1SPeter Avalos
82227bfbee1SPeter Avalos /* MCS 76 */
823*ed775ee7SAntonio Huete Jimenez { /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, },
824*ed775ee7SAntonio Huete Jimenez /* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, },
82527bfbee1SPeter Avalos },
82627bfbee1SPeter Avalos };
82727bfbee1SPeter Avalos
82841c99275SPeter Avalos static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
829*ed775ee7SAntonio Huete Jimenez #define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0]))
83041c99275SPeter Avalos
83141c99275SPeter Avalos static const char *status_text[] = {
8326263709fSPeter Avalos "Successful", /* 0 */
83341c99275SPeter Avalos "Unspecified failure", /* 1 */
834*ed775ee7SAntonio Huete Jimenez "TDLS wakeup schedule rejected but alternative schedule "
835*ed775ee7SAntonio Huete Jimenez "provided", /* 2 */
836*ed775ee7SAntonio Huete Jimenez "TDLS wakeup schedule rejected",/* 3 */
83741c99275SPeter Avalos "Reserved", /* 4 */
838*ed775ee7SAntonio Huete Jimenez "Security disabled", /* 5 */
839*ed775ee7SAntonio Huete Jimenez "Unacceptable lifetime", /* 6 */
840*ed775ee7SAntonio Huete Jimenez "Not in same BSS", /* 7 */
84141c99275SPeter Avalos "Reserved", /* 8 */
84241c99275SPeter Avalos "Reserved", /* 9 */
84327bfbee1SPeter Avalos "Cannot Support all requested capabilities in the Capability "
84427bfbee1SPeter Avalos "Information field", /* 10 */
84527bfbee1SPeter Avalos "Reassociation denied due to inability to confirm that association "
84627bfbee1SPeter Avalos "exists", /* 11 */
847*ed775ee7SAntonio Huete Jimenez "Association denied due to reason outside the scope of this "
84827bfbee1SPeter Avalos "standard", /* 12 */
849*ed775ee7SAntonio Huete Jimenez "Responding STA does not support the specified authentication "
85027bfbee1SPeter Avalos "algorithm", /* 13 */
85127bfbee1SPeter Avalos "Received an Authentication frame with authentication transaction "
85241c99275SPeter Avalos "sequence number out of expected sequence", /* 14 */
85341c99275SPeter Avalos "Authentication rejected because of challenge failure", /* 15 */
85427bfbee1SPeter Avalos "Authentication rejected due to timeout waiting for next frame in "
85527bfbee1SPeter Avalos "sequence", /* 16 */
856*ed775ee7SAntonio Huete Jimenez "Association denied because AP is unable to handle "
857*ed775ee7SAntonio Huete Jimenez "additional associated STAs", /* 17 */
858*ed775ee7SAntonio Huete Jimenez "Association denied due to requesting STA not supporting "
859*ed775ee7SAntonio Huete Jimenez "all of the data rates in the BSSBasicRateSet parameter, "
860*ed775ee7SAntonio Huete Jimenez "the Basic HT-MCS Set field of the HT Operation "
861*ed775ee7SAntonio Huete Jimenez "parameter, or the Basic VHT-MCS and NSS Set field in "
862*ed775ee7SAntonio Huete Jimenez "the VHT Operation parameter", /* 18 */
863*ed775ee7SAntonio Huete Jimenez "Association denied due to requesting STA not supporting "
864*ed775ee7SAntonio Huete Jimenez "the short preamble option", /* 19 */
865*ed775ee7SAntonio Huete Jimenez "Reserved", /* 20 */
866*ed775ee7SAntonio Huete Jimenez "Reserved", /* 21 */
86727bfbee1SPeter Avalos "Association request rejected because Spectrum Management "
86827bfbee1SPeter Avalos "capability is required", /* 22 */
86927bfbee1SPeter Avalos "Association request rejected because the information in the "
87027bfbee1SPeter Avalos "Power Capability element is unacceptable", /* 23 */
87127bfbee1SPeter Avalos "Association request rejected because the information in the "
87227bfbee1SPeter Avalos "Supported Channels element is unacceptable", /* 24 */
873*ed775ee7SAntonio Huete Jimenez "Association denied due to requesting STA not supporting "
874*ed775ee7SAntonio Huete Jimenez "the Short Slot Time option", /* 25 */
875*ed775ee7SAntonio Huete Jimenez "Reserved", /* 26 */
87627bfbee1SPeter Avalos "Association denied because the requested STA does not support HT "
87727bfbee1SPeter Avalos "features", /* 27 */
878*ed775ee7SAntonio Huete Jimenez "R0KH unreachable", /* 28 */
879*ed775ee7SAntonio Huete Jimenez "Association denied because the requesting STA does not "
880*ed775ee7SAntonio Huete Jimenez "support the phased coexistence operation (PCO) "
881*ed775ee7SAntonio Huete Jimenez "transition time required by the AP", /* 29 */
882*ed775ee7SAntonio Huete Jimenez "Association request rejected temporarily; try again "
883*ed775ee7SAntonio Huete Jimenez "later", /* 30 */
884*ed775ee7SAntonio Huete Jimenez "Robust management frame policy violation", /* 31 */
88527bfbee1SPeter Avalos "Unspecified, QoS-related failure", /* 32 */
886*ed775ee7SAntonio Huete Jimenez "Association denied because QoS AP or PCP has "
887*ed775ee7SAntonio Huete Jimenez "insufficient bandwidth to handle another QoS "
888*ed775ee7SAntonio Huete Jimenez "STA", /* 33 */
88927bfbee1SPeter Avalos "Association denied due to excessive frame loss rates and/or "
89027bfbee1SPeter Avalos "poor conditions on current operating channel", /* 34 */
891*ed775ee7SAntonio Huete Jimenez "Association (with QoS BSS) denied because the requesting STA "
892*ed775ee7SAntonio Huete Jimenez "does not support the QoS facility", /* 35 */
893*ed775ee7SAntonio Huete Jimenez "Reserved", /* 36 */
89427bfbee1SPeter Avalos "The request has been declined", /* 37 */
89527bfbee1SPeter Avalos "The request has not been successful as one or more parameters "
89627bfbee1SPeter Avalos "have invalid values", /* 38 */
897*ed775ee7SAntonio Huete Jimenez "The allocation or TS has not been created because the request "
898*ed775ee7SAntonio Huete Jimenez "cannot be honored; however, a suggested TSPEC/DMG TSPEC is "
899*ed775ee7SAntonio Huete Jimenez "provided so that the initiating STA can attempt to set "
900*ed775ee7SAntonio Huete Jimenez "another allocation or TS with the suggested changes to the "
901*ed775ee7SAntonio Huete Jimenez "TSPEC/DMG TSPEC", /* 39 */
902*ed775ee7SAntonio Huete Jimenez "Invalid element, i.e., an element defined in this standard "
903*ed775ee7SAntonio Huete Jimenez "for which the content does not meet the specifications in "
904*ed775ee7SAntonio Huete Jimenez "Clause 9", /* 40 */
905*ed775ee7SAntonio Huete Jimenez "Invalid group cipher", /* 41 */
906*ed775ee7SAntonio Huete Jimenez "Invalid pairwise cipher", /* 42 */
907*ed775ee7SAntonio Huete Jimenez "Invalid AKMP", /* 43 */
908*ed775ee7SAntonio Huete Jimenez "Unsupported RSNE version", /* 44 */
909*ed775ee7SAntonio Huete Jimenez "Invalid RSNE capabilities", /* 45 */
910*ed775ee7SAntonio Huete Jimenez "Cipher suite rejected because of security policy", /* 46 */
911*ed775ee7SAntonio Huete Jimenez "The TS or allocation has not been created; however, the "
912*ed775ee7SAntonio Huete Jimenez "HC or PCP might be capable of creating a TS or "
913*ed775ee7SAntonio Huete Jimenez "allocation, in response to a request, after the time "
914*ed775ee7SAntonio Huete Jimenez "indicated in the TS Delay element", /* 47 */
91527bfbee1SPeter Avalos "Direct Link is not allowed in the BSS by policy", /* 48 */
916*ed775ee7SAntonio Huete Jimenez "The Destination STA is not present within this BSS", /* 49 */
917*ed775ee7SAntonio Huete Jimenez "The Destination STA is not a QoS STA", /* 50 */
91827bfbee1SPeter Avalos
919*ed775ee7SAntonio Huete Jimenez "Association denied because the listen interval is "
920*ed775ee7SAntonio Huete Jimenez "too large", /* 51 */
921*ed775ee7SAntonio Huete Jimenez "Invalid FT Action frame count", /* 52 */
922*ed775ee7SAntonio Huete Jimenez "Invalid pairwise master key identifier (PMKID)", /* 53 */
923*ed775ee7SAntonio Huete Jimenez "Invalid MDE", /* 54 */
924*ed775ee7SAntonio Huete Jimenez "Invalid FTE", /* 55 */
925*ed775ee7SAntonio Huete Jimenez "Requested TCLAS processing is not supported by the AP "
926*ed775ee7SAntonio Huete Jimenez "or PCP", /* 56 */
927*ed775ee7SAntonio Huete Jimenez "The AP or PCP has insufficient TCLAS processing "
928*ed775ee7SAntonio Huete Jimenez "resources to satisfy the request", /* 57 */
929*ed775ee7SAntonio Huete Jimenez "The TS has not been created because the request "
930*ed775ee7SAntonio Huete Jimenez "cannot be honored; however, the HC or PCP suggests "
931*ed775ee7SAntonio Huete Jimenez "that the STA transition to a different BSS to set up "
932*ed775ee7SAntonio Huete Jimenez "the TS", /* 58 */
933*ed775ee7SAntonio Huete Jimenez "GAS Advertisement Protocol not supported", /* 59 */
934*ed775ee7SAntonio Huete Jimenez "No outstanding GAS request", /* 60 */
935*ed775ee7SAntonio Huete Jimenez "GAS Response not received from the Advertisement "
936*ed775ee7SAntonio Huete Jimenez "Server", /* 61 */
937*ed775ee7SAntonio Huete Jimenez "STA timed out waiting for GAS Query Response", /* 62 */
938*ed775ee7SAntonio Huete Jimenez "LARGE GAS Response is larger than query response "
939*ed775ee7SAntonio Huete Jimenez "length limit", /* 63 */
940*ed775ee7SAntonio Huete Jimenez "Request refused because home network does not support "
941*ed775ee7SAntonio Huete Jimenez "request", /* 64 */
942*ed775ee7SAntonio Huete Jimenez "Advertisement Server in the network is not currently "
943*ed775ee7SAntonio Huete Jimenez "reachable", /* 65 */
944*ed775ee7SAntonio Huete Jimenez "Reserved", /* 66 */
945*ed775ee7SAntonio Huete Jimenez "Request refused due to permissions received via SSPN "
946*ed775ee7SAntonio Huete Jimenez "interface", /* 67 */
947*ed775ee7SAntonio Huete Jimenez "Request refused because the AP or PCP does not "
948*ed775ee7SAntonio Huete Jimenez "support unauthenticated access", /* 68 */
949*ed775ee7SAntonio Huete Jimenez "Reserved", /* 69 */
950*ed775ee7SAntonio Huete Jimenez "Reserved", /* 70 */
951*ed775ee7SAntonio Huete Jimenez "Reserved", /* 71 */
952*ed775ee7SAntonio Huete Jimenez "Invalid contents of RSNE", /* 72 */
953*ed775ee7SAntonio Huete Jimenez "U-APSD coexistence is not supported", /* 73 */
954*ed775ee7SAntonio Huete Jimenez "Requested U-APSD coexistence mode is not supported", /* 74 */
955*ed775ee7SAntonio Huete Jimenez "Requested Interval/Duration value cannot be "
956*ed775ee7SAntonio Huete Jimenez "supported with U-APSD coexistence", /* 75 */
957*ed775ee7SAntonio Huete Jimenez "Authentication is rejected because an Anti-Clogging "
958*ed775ee7SAntonio Huete Jimenez "Token is required", /* 76 */
959*ed775ee7SAntonio Huete Jimenez "Authentication is rejected because the offered "
960*ed775ee7SAntonio Huete Jimenez "finite cyclic group is not supported", /* 77 */
961*ed775ee7SAntonio Huete Jimenez "The TBTT adjustment request has not been successful "
962*ed775ee7SAntonio Huete Jimenez "because the STA could not find an alternative TBTT", /* 78 */
963*ed775ee7SAntonio Huete Jimenez "Transmission failure", /* 79 */
964*ed775ee7SAntonio Huete Jimenez "Requested TCLAS Not Supported", /* 80 */
965*ed775ee7SAntonio Huete Jimenez "TCLAS Resources Exhausted", /* 81 */
966*ed775ee7SAntonio Huete Jimenez "Rejected with Suggested BSS transition", /* 82 */
967*ed775ee7SAntonio Huete Jimenez "Reject with recommended schedule", /* 83 */
968*ed775ee7SAntonio Huete Jimenez "Reject because no wakeup schedule specified", /* 84 */
969*ed775ee7SAntonio Huete Jimenez "Success, the destination STA is in power save mode", /* 85 */
970*ed775ee7SAntonio Huete Jimenez "FST pending, in process of admitting FST session", /* 86 */
971*ed775ee7SAntonio Huete Jimenez "Performing FST now", /* 87 */
972*ed775ee7SAntonio Huete Jimenez "FST pending, gap(s) in block ack window", /* 88 */
973*ed775ee7SAntonio Huete Jimenez "Reject because of U-PID setting", /* 89 */
974*ed775ee7SAntonio Huete Jimenez "Reserved", /* 90 */
975*ed775ee7SAntonio Huete Jimenez "Reserved", /* 91 */
976*ed775ee7SAntonio Huete Jimenez "(Re)Association refused for some external reason", /* 92 */
977*ed775ee7SAntonio Huete Jimenez "(Re)Association refused because of memory limits "
978*ed775ee7SAntonio Huete Jimenez "at the AP", /* 93 */
979*ed775ee7SAntonio Huete Jimenez "(Re)Association refused because emergency services "
980*ed775ee7SAntonio Huete Jimenez "are not supported at the AP", /* 94 */
981*ed775ee7SAntonio Huete Jimenez "GAS query response not yet received", /* 95 */
982*ed775ee7SAntonio Huete Jimenez "Reject since the request is for transition to a "
983*ed775ee7SAntonio Huete Jimenez "frequency band subject to DSE procedures and "
984*ed775ee7SAntonio Huete Jimenez "FST Initiator is a dependent STA", /* 96 */
985*ed775ee7SAntonio Huete Jimenez "Requested TCLAS processing has been terminated by "
986*ed775ee7SAntonio Huete Jimenez "the AP", /* 97 */
987*ed775ee7SAntonio Huete Jimenez "The TS schedule conflicts with an existing "
988*ed775ee7SAntonio Huete Jimenez "schedule; an alternative schedule is provided", /* 98 */
989*ed775ee7SAntonio Huete Jimenez "The association has been denied; however, one or "
990*ed775ee7SAntonio Huete Jimenez "more Multi-band elements are included that can "
991*ed775ee7SAntonio Huete Jimenez "be used by the receiving STA to join the BSS", /* 99 */
992*ed775ee7SAntonio Huete Jimenez "The request failed due to a reservation conflict", /* 100 */
993*ed775ee7SAntonio Huete Jimenez "The request failed due to exceeded MAF limit", /* 101 */
994*ed775ee7SAntonio Huete Jimenez "The request failed due to exceeded MCCA track "
995*ed775ee7SAntonio Huete Jimenez "limit", /* 102 */
996*ed775ee7SAntonio Huete Jimenez "Association denied because the information in the"
997*ed775ee7SAntonio Huete Jimenez "Spectrum Management field is unacceptable", /* 103 */
998*ed775ee7SAntonio Huete Jimenez "Association denied because the requesting STA "
999*ed775ee7SAntonio Huete Jimenez "does not support VHT features", /* 104 */
1000*ed775ee7SAntonio Huete Jimenez "Enablement denied", /* 105 */
1001*ed775ee7SAntonio Huete Jimenez "Enablement denied due to restriction from an "
1002*ed775ee7SAntonio Huete Jimenez "authorized GDB", /* 106 */
1003*ed775ee7SAntonio Huete Jimenez "Authorization deenabled", /* 107 */
100441c99275SPeter Avalos };
1005*ed775ee7SAntonio Huete Jimenez #define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0]))
100641c99275SPeter Avalos
100741c99275SPeter Avalos static const char *reason_text[] = {
100841c99275SPeter Avalos "Reserved", /* 0 */
100941c99275SPeter Avalos "Unspecified reason", /* 1 */
101041c99275SPeter Avalos "Previous authentication no longer valid", /* 2 */
1011*ed775ee7SAntonio Huete Jimenez "Deauthenticated because sending STA is leaving (or has left) "
101227bfbee1SPeter Avalos "IBSS or ESS", /* 3 */
101341c99275SPeter Avalos "Disassociated due to inactivity", /* 4 */
101427bfbee1SPeter Avalos "Disassociated because AP is unable to handle all currently "
1015*ed775ee7SAntonio Huete Jimenez " associated STAs", /* 5 */
1016*ed775ee7SAntonio Huete Jimenez "Class 2 frame received from nonauthenticated STA", /* 6 */
1017*ed775ee7SAntonio Huete Jimenez "Class 3 frame received from nonassociated STA", /* 7 */
1018*ed775ee7SAntonio Huete Jimenez "Disassociated because sending STA is leaving "
101927bfbee1SPeter Avalos "(or has left) BSS", /* 8 */
1020*ed775ee7SAntonio Huete Jimenez "STA requesting (re)association is not authenticated with "
1021*ed775ee7SAntonio Huete Jimenez "responding STA", /* 9 */
102227bfbee1SPeter Avalos "Disassociated because the information in the Power Capability "
102327bfbee1SPeter Avalos "element is unacceptable", /* 10 */
102427bfbee1SPeter Avalos "Disassociated because the information in the Supported Channels "
102527bfbee1SPeter Avalos "element is unacceptable", /* 11 */
1026*ed775ee7SAntonio Huete Jimenez "Disassociated due to BSS transition management", /* 12 */
1027*ed775ee7SAntonio Huete Jimenez "Invalid element, i.e., an element defined in this standard for "
1028*ed775ee7SAntonio Huete Jimenez "which the content does not meet the specifications "
1029*ed775ee7SAntonio Huete Jimenez "in Clause 9", /* 13 */
1030*ed775ee7SAntonio Huete Jimenez "Message integrity code (MIC) failure", /* 14 */
103127bfbee1SPeter Avalos "4-Way Handshake timeout", /* 15 */
1032*ed775ee7SAntonio Huete Jimenez "Group key handshake timeout", /* 16 */
103327bfbee1SPeter Avalos "Information element in 4-Way Handshake different from (Re)Association"
1034*ed775ee7SAntonio Huete Jimenez "Request/Probe Response/Beacon frame", /* 17 */
1035*ed775ee7SAntonio Huete Jimenez "Invalid group cipher", /* 18 */
1036*ed775ee7SAntonio Huete Jimenez "Invalid pairwise cipher", /* 19 */
1037*ed775ee7SAntonio Huete Jimenez "Invalid AKMP", /* 20 */
1038*ed775ee7SAntonio Huete Jimenez "Unsupported RSNE version", /* 21 */
1039*ed775ee7SAntonio Huete Jimenez "Invalid RSNE capabilities", /* 22 */
1040*ed775ee7SAntonio Huete Jimenez "IEEE 802.1X authentication failed", /* 23 */
1041*ed775ee7SAntonio Huete Jimenez "Cipher suite rejected because of the security policy", /* 24 */
1042*ed775ee7SAntonio Huete Jimenez "TDLS direct-link teardown due to TDLS peer STA "
1043*ed775ee7SAntonio Huete Jimenez "unreachable via the TDLS direct link", /* 25 */
1044*ed775ee7SAntonio Huete Jimenez "TDLS direct-link teardown for unspecified reason", /* 26 */
1045*ed775ee7SAntonio Huete Jimenez "Disassociated because session terminated by SSP request",/* 27 */
1046*ed775ee7SAntonio Huete Jimenez "Disassociated because of lack of SSP roaming agreement",/* 28 */
1047*ed775ee7SAntonio Huete Jimenez "Requested service rejected because of SSP cipher suite or "
1048*ed775ee7SAntonio Huete Jimenez "AKM requirement", /* 29 */
1049*ed775ee7SAntonio Huete Jimenez "Requested service not authorized in this location", /* 30 */
105027bfbee1SPeter Avalos "TS deleted because QoS AP lacks sufficient bandwidth for this "
105127bfbee1SPeter Avalos "QoS STA due to a change in BSS service characteristics or "
105227bfbee1SPeter Avalos "operational mode (e.g. an HT BSS change from 40 MHz channel "
105327bfbee1SPeter Avalos "to 20 MHz channel)", /* 31 */
105427bfbee1SPeter Avalos "Disassociated for unspecified, QoS-related reason", /* 32 */
105527bfbee1SPeter Avalos "Disassociated because QoS AP lacks sufficient bandwidth for this "
105627bfbee1SPeter Avalos "QoS STA", /* 33 */
105727bfbee1SPeter Avalos "Disassociated because of excessive number of frames that need to be "
1058*ed775ee7SAntonio Huete Jimenez "acknowledged, but are not acknowledged due to AP transmissions "
105927bfbee1SPeter Avalos "and/or poor channel conditions", /* 34 */
106027bfbee1SPeter Avalos "Disassociated because STA is transmitting outside the limits "
106127bfbee1SPeter Avalos "of its TXOPs", /* 35 */
106227bfbee1SPeter Avalos "Requested from peer STA as the STA is leaving the BSS "
106327bfbee1SPeter Avalos "(or resetting)", /* 36 */
106427bfbee1SPeter Avalos "Requested from peer STA as it does not want to use the "
106527bfbee1SPeter Avalos "mechanism", /* 37 */
106627bfbee1SPeter Avalos "Requested from peer STA as the STA received frames using the "
106727bfbee1SPeter Avalos "mechanism for which a set up is required", /* 38 */
106827bfbee1SPeter Avalos "Requested from peer STA due to time out", /* 39 */
106927bfbee1SPeter Avalos "Reserved", /* 40 */
107027bfbee1SPeter Avalos "Reserved", /* 41 */
107127bfbee1SPeter Avalos "Reserved", /* 42 */
107227bfbee1SPeter Avalos "Reserved", /* 43 */
107327bfbee1SPeter Avalos "Reserved", /* 44 */
107427bfbee1SPeter Avalos "Peer STA does not support the requested cipher suite", /* 45 */
1075*ed775ee7SAntonio Huete Jimenez "In a DLS Teardown frame: The teardown was initiated by the "
1076*ed775ee7SAntonio Huete Jimenez "DLS peer. In a Disassociation frame: Disassociated because "
1077*ed775ee7SAntonio Huete Jimenez "authorized access limit reached", /* 46 */
1078*ed775ee7SAntonio Huete Jimenez "In a DLS Teardown frame: The teardown was initiated by the "
1079*ed775ee7SAntonio Huete Jimenez "AP. In a Disassociation frame: Disassociated due to external "
1080*ed775ee7SAntonio Huete Jimenez "service requirements", /* 47 */
1081*ed775ee7SAntonio Huete Jimenez "Invalid FT Action frame count", /* 48 */
1082*ed775ee7SAntonio Huete Jimenez "Invalid pairwise master key identifier (PMKID)", /* 49 */
1083*ed775ee7SAntonio Huete Jimenez "Invalid MDE", /* 50 */
1084*ed775ee7SAntonio Huete Jimenez "Invalid FTE", /* 51 */
1085*ed775ee7SAntonio Huete Jimenez "Mesh peering canceled for unknown reasons", /* 52 */
1086*ed775ee7SAntonio Huete Jimenez "The mesh STA has reached the supported maximum number of "
1087*ed775ee7SAntonio Huete Jimenez "peer mesh STAs", /* 53 */
1088*ed775ee7SAntonio Huete Jimenez "The received information violates the Mesh Configuration "
1089*ed775ee7SAntonio Huete Jimenez "policy configured in the mesh STA profile", /* 54 */
1090*ed775ee7SAntonio Huete Jimenez "The mesh STA has received a Mesh Peering Close frame "
1091*ed775ee7SAntonio Huete Jimenez "requesting to close the mesh peering", /* 55 */
1092*ed775ee7SAntonio Huete Jimenez "The mesh STA has resent dot11MeshMaxRetries Mesh "
1093*ed775ee7SAntonio Huete Jimenez "Peering Open frames, without receiving a Mesh Peering "
1094*ed775ee7SAntonio Huete Jimenez "Confirm frame", /* 56 */
1095*ed775ee7SAntonio Huete Jimenez "The confirmTimer for the mesh peering instance times out", /* 57 */
1096*ed775ee7SAntonio Huete Jimenez "The mesh STA fails to unwrap the GTK or the values in the "
1097*ed775ee7SAntonio Huete Jimenez "wrapped contents do not match", /* 58 */
1098*ed775ee7SAntonio Huete Jimenez "The mesh STA receives inconsistent information about the "
1099*ed775ee7SAntonio Huete Jimenez "mesh parameters between mesh peering Management frames", /* 59 */
1100*ed775ee7SAntonio Huete Jimenez "The mesh STA fails the authenticated mesh peering exchange "
1101*ed775ee7SAntonio Huete Jimenez "because due to failure in selecting either the pairwise "
1102*ed775ee7SAntonio Huete Jimenez "ciphersuite or group ciphersuite", /* 60 */
1103*ed775ee7SAntonio Huete Jimenez "The mesh STA does not have proxy information for this "
1104*ed775ee7SAntonio Huete Jimenez "external destination", /* 61 */
1105*ed775ee7SAntonio Huete Jimenez "The mesh STA does not have forwarding information for this "
1106*ed775ee7SAntonio Huete Jimenez "destination", /* 62 */
1107*ed775ee7SAntonio Huete Jimenez "The mesh STA determines that the link to the next hop of an "
1108*ed775ee7SAntonio Huete Jimenez "active path in its forwarding information is no longer "
1109*ed775ee7SAntonio Huete Jimenez "usable", /* 63 */
1110*ed775ee7SAntonio Huete Jimenez "The Deauthentication frame was sent because the MAC "
1111*ed775ee7SAntonio Huete Jimenez "address of the STA already exists in the mesh BSS", /* 64 */
1112*ed775ee7SAntonio Huete Jimenez "The mesh STA performs channel switch to meet regulatory "
1113*ed775ee7SAntonio Huete Jimenez "requirements", /* 65 */
1114*ed775ee7SAntonio Huete Jimenez "The mesh STA performs channel switching with unspecified "
1115*ed775ee7SAntonio Huete Jimenez "reason", /* 66 */
111641c99275SPeter Avalos };
1117*ed775ee7SAntonio Huete Jimenez #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0]))
111841c99275SPeter Avalos
111941c99275SPeter Avalos static int
wep_print(netdissect_options * ndo,const u_char * p)1120411677aeSAaron LI wep_print(netdissect_options *ndo,
1121411677aeSAaron LI const u_char *p)
112241c99275SPeter Avalos {
1123411677aeSAaron LI uint32_t iv;
112441c99275SPeter Avalos
1125*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN);
1126*ed775ee7SAntonio Huete Jimenez iv = GET_LE_U_4(p);
112741c99275SPeter Avalos
1128*ed775ee7SAntonio Huete Jimenez ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
1129*ed775ee7SAntonio Huete Jimenez IV_KEYID(iv));
113041c99275SPeter Avalos
113141c99275SPeter Avalos return 1;
1132*ed775ee7SAntonio Huete Jimenez trunc:
1133*ed775ee7SAntonio Huete Jimenez return 0;
113441c99275SPeter Avalos }
113541c99275SPeter Avalos
113627bfbee1SPeter Avalos static int
parse_elements(netdissect_options * ndo,struct mgmt_body_t * pbody,const u_char * p,int offset,u_int length)1137411677aeSAaron LI parse_elements(netdissect_options *ndo,
1138411677aeSAaron LI struct mgmt_body_t *pbody, const u_char *p, int offset,
113927bfbee1SPeter Avalos u_int length)
114041c99275SPeter Avalos {
114127bfbee1SPeter Avalos u_int elementlen;
114227bfbee1SPeter Avalos struct ssid_t ssid;
114327bfbee1SPeter Avalos struct challenge_t challenge;
114427bfbee1SPeter Avalos struct rates_t rates;
114527bfbee1SPeter Avalos struct ds_t ds;
114627bfbee1SPeter Avalos struct cf_t cf;
114727bfbee1SPeter Avalos struct tim_t tim;
114827bfbee1SPeter Avalos
114941c99275SPeter Avalos /*
115041c99275SPeter Avalos * We haven't seen any elements yet.
115141c99275SPeter Avalos */
115227bfbee1SPeter Avalos pbody->challenge_present = 0;
115327bfbee1SPeter Avalos pbody->ssid_present = 0;
115427bfbee1SPeter Avalos pbody->rates_present = 0;
115527bfbee1SPeter Avalos pbody->ds_present = 0;
115627bfbee1SPeter Avalos pbody->cf_present = 0;
115727bfbee1SPeter Avalos pbody->tim_present = 0;
115841c99275SPeter Avalos
115927bfbee1SPeter Avalos while (length != 0) {
1160411677aeSAaron LI /* Make sure we at least have the element ID and length. */
1161*ed775ee7SAntonio Huete Jimenez ND_TCHECK_2(p + offset);
116227bfbee1SPeter Avalos if (length < 2)
1163*ed775ee7SAntonio Huete Jimenez goto trunc;
1164*ed775ee7SAntonio Huete Jimenez elementlen = GET_U_1(p + offset + 1);
1165411677aeSAaron LI
1166411677aeSAaron LI /* Make sure we have the entire element. */
1167*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p + offset + 2, elementlen);
1168411677aeSAaron LI if (length < elementlen + 2)
1169*ed775ee7SAntonio Huete Jimenez goto trunc;
1170411677aeSAaron LI
1171*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(p + offset)) {
1172411677aeSAaron LI case E_SSID:
117327bfbee1SPeter Avalos memcpy(&ssid, p + offset, 2);
117441c99275SPeter Avalos offset += 2;
117527bfbee1SPeter Avalos length -= 2;
117627bfbee1SPeter Avalos if (ssid.length != 0) {
117727bfbee1SPeter Avalos if (ssid.length > sizeof(ssid.ssid) - 1)
117827bfbee1SPeter Avalos return 0;
117927bfbee1SPeter Avalos memcpy(&ssid.ssid, p + offset, ssid.length);
118027bfbee1SPeter Avalos offset += ssid.length;
118127bfbee1SPeter Avalos length -= ssid.length;
118241c99275SPeter Avalos }
118327bfbee1SPeter Avalos ssid.ssid[ssid.length] = '\0';
118427bfbee1SPeter Avalos /*
118527bfbee1SPeter Avalos * Present and not truncated.
118627bfbee1SPeter Avalos *
118727bfbee1SPeter Avalos * If we haven't already seen an SSID IE,
118827bfbee1SPeter Avalos * copy this one, otherwise ignore this one,
118927bfbee1SPeter Avalos * so we later report the first one we saw.
119027bfbee1SPeter Avalos */
119127bfbee1SPeter Avalos if (!pbody->ssid_present) {
119227bfbee1SPeter Avalos pbody->ssid = ssid;
119327bfbee1SPeter Avalos pbody->ssid_present = 1;
119427bfbee1SPeter Avalos }
119541c99275SPeter Avalos break;
119641c99275SPeter Avalos case E_CHALLENGE:
119727bfbee1SPeter Avalos memcpy(&challenge, p + offset, 2);
119841c99275SPeter Avalos offset += 2;
119927bfbee1SPeter Avalos length -= 2;
120027bfbee1SPeter Avalos if (challenge.length != 0) {
120127bfbee1SPeter Avalos if (challenge.length >
120227bfbee1SPeter Avalos sizeof(challenge.text) - 1)
120327bfbee1SPeter Avalos return 0;
120427bfbee1SPeter Avalos memcpy(&challenge.text, p + offset,
120527bfbee1SPeter Avalos challenge.length);
120627bfbee1SPeter Avalos offset += challenge.length;
120727bfbee1SPeter Avalos length -= challenge.length;
120841c99275SPeter Avalos }
120927bfbee1SPeter Avalos challenge.text[challenge.length] = '\0';
121027bfbee1SPeter Avalos /*
121127bfbee1SPeter Avalos * Present and not truncated.
121227bfbee1SPeter Avalos *
121327bfbee1SPeter Avalos * If we haven't already seen a challenge IE,
121427bfbee1SPeter Avalos * copy this one, otherwise ignore this one,
121527bfbee1SPeter Avalos * so we later report the first one we saw.
121627bfbee1SPeter Avalos */
121727bfbee1SPeter Avalos if (!pbody->challenge_present) {
121827bfbee1SPeter Avalos pbody->challenge = challenge;
121927bfbee1SPeter Avalos pbody->challenge_present = 1;
122027bfbee1SPeter Avalos }
122141c99275SPeter Avalos break;
122241c99275SPeter Avalos case E_RATES:
122327bfbee1SPeter Avalos memcpy(&rates, p + offset, 2);
122441c99275SPeter Avalos offset += 2;
122527bfbee1SPeter Avalos length -= 2;
122627bfbee1SPeter Avalos if (rates.length != 0) {
1227*ed775ee7SAntonio Huete Jimenez if (rates.length > sizeof(rates.rate))
122827bfbee1SPeter Avalos return 0;
122927bfbee1SPeter Avalos memcpy(&rates.rate, p + offset, rates.length);
123027bfbee1SPeter Avalos offset += rates.length;
123127bfbee1SPeter Avalos length -= rates.length;
123241c99275SPeter Avalos }
123327bfbee1SPeter Avalos /*
123427bfbee1SPeter Avalos * Present and not truncated.
123527bfbee1SPeter Avalos *
123627bfbee1SPeter Avalos * If we haven't already seen a rates IE,
123727bfbee1SPeter Avalos * copy this one if it's not zero-length,
123827bfbee1SPeter Avalos * otherwise ignore this one, so we later
123927bfbee1SPeter Avalos * report the first one we saw.
124027bfbee1SPeter Avalos *
124127bfbee1SPeter Avalos * We ignore zero-length rates IEs as some
124227bfbee1SPeter Avalos * devices seem to put a zero-length rates
124327bfbee1SPeter Avalos * IE, followed by an SSID IE, followed by
124427bfbee1SPeter Avalos * a non-zero-length rates IE into frames,
124527bfbee1SPeter Avalos * even though IEEE Std 802.11-2007 doesn't
124627bfbee1SPeter Avalos * seem to indicate that a zero-length rates
124727bfbee1SPeter Avalos * IE is valid.
124827bfbee1SPeter Avalos */
124927bfbee1SPeter Avalos if (!pbody->rates_present && rates.length != 0) {
125027bfbee1SPeter Avalos pbody->rates = rates;
125127bfbee1SPeter Avalos pbody->rates_present = 1;
125227bfbee1SPeter Avalos }
125341c99275SPeter Avalos break;
125441c99275SPeter Avalos case E_DS:
1255411677aeSAaron LI memcpy(&ds, p + offset, 2);
1256411677aeSAaron LI offset += 2;
1257411677aeSAaron LI length -= 2;
1258411677aeSAaron LI if (ds.length != 1) {
1259411677aeSAaron LI offset += ds.length;
1260411677aeSAaron LI length -= ds.length;
1261411677aeSAaron LI break;
1262411677aeSAaron LI }
1263*ed775ee7SAntonio Huete Jimenez ds.channel = GET_U_1(p + offset);
1264411677aeSAaron LI offset += 1;
1265411677aeSAaron LI length -= 1;
126627bfbee1SPeter Avalos /*
126727bfbee1SPeter Avalos * Present and not truncated.
126827bfbee1SPeter Avalos *
126927bfbee1SPeter Avalos * If we haven't already seen a DS IE,
127027bfbee1SPeter Avalos * copy this one, otherwise ignore this one,
127127bfbee1SPeter Avalos * so we later report the first one we saw.
127227bfbee1SPeter Avalos */
127327bfbee1SPeter Avalos if (!pbody->ds_present) {
127427bfbee1SPeter Avalos pbody->ds = ds;
127527bfbee1SPeter Avalos pbody->ds_present = 1;
127627bfbee1SPeter Avalos }
127741c99275SPeter Avalos break;
127841c99275SPeter Avalos case E_CF:
1279411677aeSAaron LI memcpy(&cf, p + offset, 2);
1280411677aeSAaron LI offset += 2;
1281411677aeSAaron LI length -= 2;
1282411677aeSAaron LI if (cf.length != 6) {
1283411677aeSAaron LI offset += cf.length;
1284411677aeSAaron LI length -= cf.length;
1285411677aeSAaron LI break;
1286411677aeSAaron LI }
1287411677aeSAaron LI memcpy(&cf.count, p + offset, 6);
1288411677aeSAaron LI offset += 6;
1289411677aeSAaron LI length -= 6;
129027bfbee1SPeter Avalos /*
129127bfbee1SPeter Avalos * Present and not truncated.
129227bfbee1SPeter Avalos *
129327bfbee1SPeter Avalos * If we haven't already seen a CF IE,
129427bfbee1SPeter Avalos * copy this one, otherwise ignore this one,
129527bfbee1SPeter Avalos * so we later report the first one we saw.
129627bfbee1SPeter Avalos */
129727bfbee1SPeter Avalos if (!pbody->cf_present) {
129827bfbee1SPeter Avalos pbody->cf = cf;
129927bfbee1SPeter Avalos pbody->cf_present = 1;
130027bfbee1SPeter Avalos }
130141c99275SPeter Avalos break;
130241c99275SPeter Avalos case E_TIM:
130327bfbee1SPeter Avalos memcpy(&tim, p + offset, 2);
130441c99275SPeter Avalos offset += 2;
130527bfbee1SPeter Avalos length -= 2;
1306*ed775ee7SAntonio Huete Jimenez if (tim.length <= 3U) {
1307411677aeSAaron LI offset += tim.length;
1308411677aeSAaron LI length -= tim.length;
1309411677aeSAaron LI break;
1310411677aeSAaron LI }
1311*ed775ee7SAntonio Huete Jimenez if (tim.length - 3U > sizeof(tim.bitmap))
131227bfbee1SPeter Avalos return 0;
131327bfbee1SPeter Avalos memcpy(&tim.count, p + offset, 3);
131441c99275SPeter Avalos offset += 3;
131527bfbee1SPeter Avalos length -= 3;
131641c99275SPeter Avalos
1317411677aeSAaron LI memcpy(tim.bitmap, p + offset, tim.length - 3);
131827bfbee1SPeter Avalos offset += tim.length - 3;
131927bfbee1SPeter Avalos length -= tim.length - 3;
132027bfbee1SPeter Avalos /*
132127bfbee1SPeter Avalos * Present and not truncated.
132227bfbee1SPeter Avalos *
132327bfbee1SPeter Avalos * If we haven't already seen a TIM IE,
132427bfbee1SPeter Avalos * copy this one, otherwise ignore this one,
132527bfbee1SPeter Avalos * so we later report the first one we saw.
132627bfbee1SPeter Avalos */
132727bfbee1SPeter Avalos if (!pbody->tim_present) {
132827bfbee1SPeter Avalos pbody->tim = tim;
132927bfbee1SPeter Avalos pbody->tim_present = 1;
133027bfbee1SPeter Avalos }
133141c99275SPeter Avalos break;
133241c99275SPeter Avalos default:
133341c99275SPeter Avalos #if 0
1334*ed775ee7SAntonio Huete Jimenez ND_PRINT("(1) unhandled element_id (%u) ",
1335*ed775ee7SAntonio Huete Jimenez GET_U_1(p + offset));
133641c99275SPeter Avalos #endif
1337411677aeSAaron LI offset += 2 + elementlen;
1338411677aeSAaron LI length -= 2 + elementlen;
133941c99275SPeter Avalos break;
134041c99275SPeter Avalos }
134141c99275SPeter Avalos }
134227bfbee1SPeter Avalos
134327bfbee1SPeter Avalos /* No problems found. */
134427bfbee1SPeter Avalos return 1;
1345*ed775ee7SAntonio Huete Jimenez trunc:
1346*ed775ee7SAntonio Huete Jimenez return 0;
134741c99275SPeter Avalos }
134841c99275SPeter Avalos
134941c99275SPeter Avalos /*********************************************************************************
135041c99275SPeter Avalos * Print Handle functions for the management frame types
135141c99275SPeter Avalos *********************************************************************************/
135241c99275SPeter Avalos
135341c99275SPeter Avalos static int
handle_beacon(netdissect_options * ndo,const u_char * p,u_int length)1354411677aeSAaron LI handle_beacon(netdissect_options *ndo,
1355411677aeSAaron LI const u_char *p, u_int length)
135641c99275SPeter Avalos {
135741c99275SPeter Avalos struct mgmt_body_t pbody;
135841c99275SPeter Avalos int offset = 0;
135927bfbee1SPeter Avalos int ret;
136041c99275SPeter Avalos
136141c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
136241c99275SPeter Avalos
1363*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1364*ed775ee7SAntonio Huete Jimenez IEEE802_11_CAPINFO_LEN);
136527bfbee1SPeter Avalos if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
136627bfbee1SPeter Avalos IEEE802_11_CAPINFO_LEN)
1367*ed775ee7SAntonio Huete Jimenez goto trunc;
136841c99275SPeter Avalos memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
136941c99275SPeter Avalos offset += IEEE802_11_TSTAMP_LEN;
137027bfbee1SPeter Avalos length -= IEEE802_11_TSTAMP_LEN;
1371*ed775ee7SAntonio Huete Jimenez pbody.beacon_interval = GET_LE_U_2(p + offset);
137241c99275SPeter Avalos offset += IEEE802_11_BCNINT_LEN;
137327bfbee1SPeter Avalos length -= IEEE802_11_BCNINT_LEN;
1374*ed775ee7SAntonio Huete Jimenez pbody.capability_info = GET_LE_U_2(p + offset);
137541c99275SPeter Avalos offset += IEEE802_11_CAPINFO_LEN;
137627bfbee1SPeter Avalos length -= IEEE802_11_CAPINFO_LEN;
137741c99275SPeter Avalos
1378411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
137941c99275SPeter Avalos
138041c99275SPeter Avalos PRINT_SSID(pbody);
138141c99275SPeter Avalos PRINT_RATES(pbody);
1382*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s",
1383*ed775ee7SAntonio Huete Jimenez CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
138441c99275SPeter Avalos PRINT_DS_CHANNEL(pbody);
138541c99275SPeter Avalos
138627bfbee1SPeter Avalos return ret;
1387*ed775ee7SAntonio Huete Jimenez trunc:
1388*ed775ee7SAntonio Huete Jimenez return 0;
138941c99275SPeter Avalos }
139041c99275SPeter Avalos
139141c99275SPeter Avalos static int
handle_assoc_request(netdissect_options * ndo,const u_char * p,u_int length)1392411677aeSAaron LI handle_assoc_request(netdissect_options *ndo,
1393411677aeSAaron LI const u_char *p, u_int length)
139441c99275SPeter Avalos {
139541c99275SPeter Avalos struct mgmt_body_t pbody;
139641c99275SPeter Avalos int offset = 0;
139727bfbee1SPeter Avalos int ret;
139841c99275SPeter Avalos
139941c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
140041c99275SPeter Avalos
1401*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
140227bfbee1SPeter Avalos if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
1403*ed775ee7SAntonio Huete Jimenez goto trunc;
1404*ed775ee7SAntonio Huete Jimenez pbody.capability_info = GET_LE_U_2(p);
140541c99275SPeter Avalos offset += IEEE802_11_CAPINFO_LEN;
140627bfbee1SPeter Avalos length -= IEEE802_11_CAPINFO_LEN;
1407*ed775ee7SAntonio Huete Jimenez pbody.listen_interval = GET_LE_U_2(p + offset);
140841c99275SPeter Avalos offset += IEEE802_11_LISTENINT_LEN;
140927bfbee1SPeter Avalos length -= IEEE802_11_LISTENINT_LEN;
141041c99275SPeter Avalos
1411411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
141241c99275SPeter Avalos
141341c99275SPeter Avalos PRINT_SSID(pbody);
141441c99275SPeter Avalos PRINT_RATES(pbody);
141527bfbee1SPeter Avalos return ret;
1416*ed775ee7SAntonio Huete Jimenez trunc:
1417*ed775ee7SAntonio Huete Jimenez return 0;
141841c99275SPeter Avalos }
141941c99275SPeter Avalos
142041c99275SPeter Avalos static int
handle_assoc_response(netdissect_options * ndo,const u_char * p,u_int length)1421411677aeSAaron LI handle_assoc_response(netdissect_options *ndo,
1422411677aeSAaron LI const u_char *p, u_int length)
142341c99275SPeter Avalos {
142441c99275SPeter Avalos struct mgmt_body_t pbody;
142541c99275SPeter Avalos int offset = 0;
142627bfbee1SPeter Avalos int ret;
142741c99275SPeter Avalos
142841c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
142941c99275SPeter Avalos
1430*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
1431*ed775ee7SAntonio Huete Jimenez IEEE802_11_AID_LEN);
143227bfbee1SPeter Avalos if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
143327bfbee1SPeter Avalos IEEE802_11_AID_LEN)
1434*ed775ee7SAntonio Huete Jimenez goto trunc;
1435*ed775ee7SAntonio Huete Jimenez pbody.capability_info = GET_LE_U_2(p);
143641c99275SPeter Avalos offset += IEEE802_11_CAPINFO_LEN;
143727bfbee1SPeter Avalos length -= IEEE802_11_CAPINFO_LEN;
1438*ed775ee7SAntonio Huete Jimenez pbody.status_code = GET_LE_U_2(p + offset);
143941c99275SPeter Avalos offset += IEEE802_11_STATUS_LEN;
144027bfbee1SPeter Avalos length -= IEEE802_11_STATUS_LEN;
1441*ed775ee7SAntonio Huete Jimenez pbody.aid = GET_LE_U_2(p + offset);
144241c99275SPeter Avalos offset += IEEE802_11_AID_LEN;
144327bfbee1SPeter Avalos length -= IEEE802_11_AID_LEN;
144441c99275SPeter Avalos
1445411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
144641c99275SPeter Avalos
1447*ed775ee7SAntonio Huete Jimenez ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
144841c99275SPeter Avalos CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
144941c99275SPeter Avalos (pbody.status_code < NUM_STATUSES
145041c99275SPeter Avalos ? status_text[pbody.status_code]
1451*ed775ee7SAntonio Huete Jimenez : "n/a"));
145241c99275SPeter Avalos
145327bfbee1SPeter Avalos return ret;
1454*ed775ee7SAntonio Huete Jimenez trunc:
1455*ed775ee7SAntonio Huete Jimenez return 0;
145641c99275SPeter Avalos }
145741c99275SPeter Avalos
145841c99275SPeter Avalos static int
handle_reassoc_request(netdissect_options * ndo,const u_char * p,u_int length)1459411677aeSAaron LI handle_reassoc_request(netdissect_options *ndo,
1460411677aeSAaron LI const u_char *p, u_int length)
146141c99275SPeter Avalos {
146241c99275SPeter Avalos struct mgmt_body_t pbody;
146341c99275SPeter Avalos int offset = 0;
146427bfbee1SPeter Avalos int ret;
146541c99275SPeter Avalos
146641c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
146741c99275SPeter Avalos
1468*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
1469*ed775ee7SAntonio Huete Jimenez IEEE802_11_AP_LEN);
147027bfbee1SPeter Avalos if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
147127bfbee1SPeter Avalos IEEE802_11_AP_LEN)
1472*ed775ee7SAntonio Huete Jimenez goto trunc;
1473*ed775ee7SAntonio Huete Jimenez pbody.capability_info = GET_LE_U_2(p);
147441c99275SPeter Avalos offset += IEEE802_11_CAPINFO_LEN;
147527bfbee1SPeter Avalos length -= IEEE802_11_CAPINFO_LEN;
1476*ed775ee7SAntonio Huete Jimenez pbody.listen_interval = GET_LE_U_2(p + offset);
147741c99275SPeter Avalos offset += IEEE802_11_LISTENINT_LEN;
147827bfbee1SPeter Avalos length -= IEEE802_11_LISTENINT_LEN;
147941c99275SPeter Avalos memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
148041c99275SPeter Avalos offset += IEEE802_11_AP_LEN;
148127bfbee1SPeter Avalos length -= IEEE802_11_AP_LEN;
148241c99275SPeter Avalos
1483411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
148441c99275SPeter Avalos
148541c99275SPeter Avalos PRINT_SSID(pbody);
1486*ed775ee7SAntonio Huete Jimenez ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap ));
148741c99275SPeter Avalos
148827bfbee1SPeter Avalos return ret;
1489*ed775ee7SAntonio Huete Jimenez trunc:
1490*ed775ee7SAntonio Huete Jimenez return 0;
149141c99275SPeter Avalos }
149241c99275SPeter Avalos
149341c99275SPeter Avalos static int
handle_reassoc_response(netdissect_options * ndo,const u_char * p,u_int length)1494411677aeSAaron LI handle_reassoc_response(netdissect_options *ndo,
1495411677aeSAaron LI const u_char *p, u_int length)
149641c99275SPeter Avalos {
1497*ed775ee7SAntonio Huete Jimenez /* Same as a Association Response */
1498411677aeSAaron LI return handle_assoc_response(ndo, p, length);
149941c99275SPeter Avalos }
150041c99275SPeter Avalos
150141c99275SPeter Avalos static int
handle_probe_request(netdissect_options * ndo,const u_char * p,u_int length)1502411677aeSAaron LI handle_probe_request(netdissect_options *ndo,
1503411677aeSAaron LI const u_char *p, u_int length)
150441c99275SPeter Avalos {
150541c99275SPeter Avalos struct mgmt_body_t pbody;
150641c99275SPeter Avalos int offset = 0;
150727bfbee1SPeter Avalos int ret;
150841c99275SPeter Avalos
150941c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
151041c99275SPeter Avalos
1511411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
151241c99275SPeter Avalos
151341c99275SPeter Avalos PRINT_SSID(pbody);
151441c99275SPeter Avalos PRINT_RATES(pbody);
151541c99275SPeter Avalos
151627bfbee1SPeter Avalos return ret;
151741c99275SPeter Avalos }
151841c99275SPeter Avalos
151941c99275SPeter Avalos static int
handle_probe_response(netdissect_options * ndo,const u_char * p,u_int length)1520411677aeSAaron LI handle_probe_response(netdissect_options *ndo,
1521411677aeSAaron LI const u_char *p, u_int length)
152241c99275SPeter Avalos {
152341c99275SPeter Avalos struct mgmt_body_t pbody;
152441c99275SPeter Avalos int offset = 0;
152527bfbee1SPeter Avalos int ret;
152641c99275SPeter Avalos
152741c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
152841c99275SPeter Avalos
1529*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
1530*ed775ee7SAntonio Huete Jimenez IEEE802_11_CAPINFO_LEN);
153127bfbee1SPeter Avalos if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
153227bfbee1SPeter Avalos IEEE802_11_CAPINFO_LEN)
1533*ed775ee7SAntonio Huete Jimenez goto trunc;
153441c99275SPeter Avalos memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
153541c99275SPeter Avalos offset += IEEE802_11_TSTAMP_LEN;
153627bfbee1SPeter Avalos length -= IEEE802_11_TSTAMP_LEN;
1537*ed775ee7SAntonio Huete Jimenez pbody.beacon_interval = GET_LE_U_2(p + offset);
153841c99275SPeter Avalos offset += IEEE802_11_BCNINT_LEN;
153927bfbee1SPeter Avalos length -= IEEE802_11_BCNINT_LEN;
1540*ed775ee7SAntonio Huete Jimenez pbody.capability_info = GET_LE_U_2(p + offset);
154141c99275SPeter Avalos offset += IEEE802_11_CAPINFO_LEN;
154227bfbee1SPeter Avalos length -= IEEE802_11_CAPINFO_LEN;
154341c99275SPeter Avalos
1544411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
154541c99275SPeter Avalos
154641c99275SPeter Avalos PRINT_SSID(pbody);
154741c99275SPeter Avalos PRINT_RATES(pbody);
154841c99275SPeter Avalos PRINT_DS_CHANNEL(pbody);
154941c99275SPeter Avalos
155027bfbee1SPeter Avalos return ret;
1551*ed775ee7SAntonio Huete Jimenez trunc:
1552*ed775ee7SAntonio Huete Jimenez return 0;
155341c99275SPeter Avalos }
155441c99275SPeter Avalos
155541c99275SPeter Avalos static int
handle_atim(void)155641c99275SPeter Avalos handle_atim(void)
155741c99275SPeter Avalos {
155841c99275SPeter Avalos /* the frame body for ATIM is null. */
155941c99275SPeter Avalos return 1;
156041c99275SPeter Avalos }
156141c99275SPeter Avalos
156241c99275SPeter Avalos static int
handle_disassoc(netdissect_options * ndo,const u_char * p,u_int length)1563411677aeSAaron LI handle_disassoc(netdissect_options *ndo,
1564411677aeSAaron LI const u_char *p, u_int length)
156541c99275SPeter Avalos {
156641c99275SPeter Avalos struct mgmt_body_t pbody;
156741c99275SPeter Avalos
156841c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
156941c99275SPeter Avalos
1570*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
157127bfbee1SPeter Avalos if (length < IEEE802_11_REASON_LEN)
1572*ed775ee7SAntonio Huete Jimenez goto trunc;
1573*ed775ee7SAntonio Huete Jimenez pbody.reason_code = GET_LE_U_2(p);
157441c99275SPeter Avalos
1575*ed775ee7SAntonio Huete Jimenez ND_PRINT(": %s",
157641c99275SPeter Avalos (pbody.reason_code < NUM_REASONS)
157741c99275SPeter Avalos ? reason_text[pbody.reason_code]
1578*ed775ee7SAntonio Huete Jimenez : "Reserved");
157941c99275SPeter Avalos
158041c99275SPeter Avalos return 1;
1581*ed775ee7SAntonio Huete Jimenez trunc:
1582*ed775ee7SAntonio Huete Jimenez return 0;
158341c99275SPeter Avalos }
158441c99275SPeter Avalos
158541c99275SPeter Avalos static int
handle_auth(netdissect_options * ndo,const u_char * p,u_int length)1586411677aeSAaron LI handle_auth(netdissect_options *ndo,
1587411677aeSAaron LI const u_char *p, u_int length)
158841c99275SPeter Avalos {
158941c99275SPeter Avalos struct mgmt_body_t pbody;
159041c99275SPeter Avalos int offset = 0;
159127bfbee1SPeter Avalos int ret;
159241c99275SPeter Avalos
159341c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
159441c99275SPeter Avalos
1595*ed775ee7SAntonio Huete Jimenez ND_TCHECK_6(p);
159627bfbee1SPeter Avalos if (length < 6)
1597*ed775ee7SAntonio Huete Jimenez goto trunc;
1598*ed775ee7SAntonio Huete Jimenez pbody.auth_alg = GET_LE_U_2(p);
159941c99275SPeter Avalos offset += 2;
160027bfbee1SPeter Avalos length -= 2;
1601*ed775ee7SAntonio Huete Jimenez pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
160241c99275SPeter Avalos offset += 2;
160327bfbee1SPeter Avalos length -= 2;
1604*ed775ee7SAntonio Huete Jimenez pbody.status_code = GET_LE_U_2(p + offset);
160541c99275SPeter Avalos offset += 2;
160627bfbee1SPeter Avalos length -= 2;
160741c99275SPeter Avalos
1608411677aeSAaron LI ret = parse_elements(ndo, &pbody, p, offset, length);
160941c99275SPeter Avalos
161041c99275SPeter Avalos if ((pbody.auth_alg == 1) &&
161141c99275SPeter Avalos ((pbody.auth_trans_seq_num == 2) ||
161241c99275SPeter Avalos (pbody.auth_trans_seq_num == 3))) {
1613*ed775ee7SAntonio Huete Jimenez ND_PRINT(" (%s)-%x [Challenge Text] %s",
161441c99275SPeter Avalos (pbody.auth_alg < NUM_AUTH_ALGS)
161541c99275SPeter Avalos ? auth_alg_text[pbody.auth_alg]
161641c99275SPeter Avalos : "Reserved",
161741c99275SPeter Avalos pbody.auth_trans_seq_num,
161841c99275SPeter Avalos ((pbody.auth_trans_seq_num % 2)
161941c99275SPeter Avalos ? ((pbody.status_code < NUM_STATUSES)
162041c99275SPeter Avalos ? status_text[pbody.status_code]
1621*ed775ee7SAntonio Huete Jimenez : "n/a") : ""));
162227bfbee1SPeter Avalos return ret;
162341c99275SPeter Avalos }
1624*ed775ee7SAntonio Huete Jimenez ND_PRINT(" (%s)-%x: %s",
162541c99275SPeter Avalos (pbody.auth_alg < NUM_AUTH_ALGS)
162641c99275SPeter Avalos ? auth_alg_text[pbody.auth_alg]
162741c99275SPeter Avalos : "Reserved",
162841c99275SPeter Avalos pbody.auth_trans_seq_num,
162941c99275SPeter Avalos (pbody.auth_trans_seq_num % 2)
163041c99275SPeter Avalos ? ((pbody.status_code < NUM_STATUSES)
163141c99275SPeter Avalos ? status_text[pbody.status_code]
163241c99275SPeter Avalos : "n/a")
1633*ed775ee7SAntonio Huete Jimenez : "");
163441c99275SPeter Avalos
163527bfbee1SPeter Avalos return ret;
1636*ed775ee7SAntonio Huete Jimenez trunc:
1637*ed775ee7SAntonio Huete Jimenez return 0;
163841c99275SPeter Avalos }
163941c99275SPeter Avalos
164041c99275SPeter Avalos static int
handle_deauth(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)1641411677aeSAaron LI handle_deauth(netdissect_options *ndo,
1642411677aeSAaron LI const uint8_t *src, const u_char *p, u_int length)
164341c99275SPeter Avalos {
164441c99275SPeter Avalos struct mgmt_body_t pbody;
164541c99275SPeter Avalos const char *reason = NULL;
164641c99275SPeter Avalos
164741c99275SPeter Avalos memset(&pbody, 0, sizeof(pbody));
164841c99275SPeter Avalos
1649*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
165027bfbee1SPeter Avalos if (length < IEEE802_11_REASON_LEN)
1651*ed775ee7SAntonio Huete Jimenez goto trunc;
1652*ed775ee7SAntonio Huete Jimenez pbody.reason_code = GET_LE_U_2(p);
165341c99275SPeter Avalos
165441c99275SPeter Avalos reason = (pbody.reason_code < NUM_REASONS)
165541c99275SPeter Avalos ? reason_text[pbody.reason_code]
165641c99275SPeter Avalos : "Reserved";
165741c99275SPeter Avalos
1658411677aeSAaron LI if (ndo->ndo_eflag) {
1659*ed775ee7SAntonio Huete Jimenez ND_PRINT(": %s", reason);
166041c99275SPeter Avalos } else {
1661*ed775ee7SAntonio Huete Jimenez ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
166241c99275SPeter Avalos }
166341c99275SPeter Avalos return 1;
1664*ed775ee7SAntonio Huete Jimenez trunc:
1665*ed775ee7SAntonio Huete Jimenez return 0;
166641c99275SPeter Avalos }
166741c99275SPeter Avalos
166827bfbee1SPeter Avalos #define PRINT_HT_ACTION(v) (\
1669*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("TxChWidth"): \
1670*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("MIMOPwrSave"): \
1671*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
167227bfbee1SPeter Avalos #define PRINT_BA_ACTION(v) (\
1673*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("ADDBA Request"): \
1674*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("ADDBA Response"): \
1675*ed775ee7SAntonio Huete Jimenez (v) == 2 ? ND_PRINT("DELBA"): \
1676*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
167727bfbee1SPeter Avalos #define PRINT_MESHLINK_ACTION(v) (\
1678*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("Request"): \
1679*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("Report"): \
1680*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
168127bfbee1SPeter Avalos #define PRINT_MESHPEERING_ACTION(v) (\
1682*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("Open"): \
1683*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("Confirm"): \
1684*ed775ee7SAntonio Huete Jimenez (v) == 2 ? ND_PRINT("Close"): \
1685*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
168627bfbee1SPeter Avalos #define PRINT_MESHPATH_ACTION(v) (\
1687*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("Request"): \
1688*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("Report"): \
1689*ed775ee7SAntonio Huete Jimenez (v) == 2 ? ND_PRINT("Error"): \
1690*ed775ee7SAntonio Huete Jimenez (v) == 3 ? ND_PRINT("RootAnnouncement"): \
1691*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
1692411677aeSAaron LI
1693411677aeSAaron LI #define PRINT_MESH_ACTION(v) (\
1694*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("MeshLink"): \
1695*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("HWMP"): \
1696*ed775ee7SAntonio Huete Jimenez (v) == 2 ? ND_PRINT("Gate Announcement"): \
1697*ed775ee7SAntonio Huete Jimenez (v) == 3 ? ND_PRINT("Congestion Control"): \
1698*ed775ee7SAntonio Huete Jimenez (v) == 4 ? ND_PRINT("MCCA Setup Request"): \
1699*ed775ee7SAntonio Huete Jimenez (v) == 5 ? ND_PRINT("MCCA Setup Reply"): \
1700*ed775ee7SAntonio Huete Jimenez (v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \
1701*ed775ee7SAntonio Huete Jimenez (v) == 7 ? ND_PRINT("MCCA Advertisement"): \
1702*ed775ee7SAntonio Huete Jimenez (v) == 8 ? ND_PRINT("MCCA Teardown"): \
1703*ed775ee7SAntonio Huete Jimenez (v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \
1704*ed775ee7SAntonio Huete Jimenez (v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \
1705*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
1706411677aeSAaron LI #define PRINT_MULTIHOP_ACTION(v) (\
1707*ed775ee7SAntonio Huete Jimenez (v) == 0 ? ND_PRINT("Proxy Update"): \
1708*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \
1709*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
1710411677aeSAaron LI #define PRINT_SELFPROT_ACTION(v) (\
1711*ed775ee7SAntonio Huete Jimenez (v) == 1 ? ND_PRINT("Peering Open"): \
1712*ed775ee7SAntonio Huete Jimenez (v) == 2 ? ND_PRINT("Peering Confirm"): \
1713*ed775ee7SAntonio Huete Jimenez (v) == 3 ? ND_PRINT("Peering Close"): \
1714*ed775ee7SAntonio Huete Jimenez (v) == 4 ? ND_PRINT("Group Key Inform"): \
1715*ed775ee7SAntonio Huete Jimenez (v) == 5 ? ND_PRINT("Group Key Acknowledge"): \
1716*ed775ee7SAntonio Huete Jimenez ND_PRINT("Act#%u", (v)))
171727bfbee1SPeter Avalos
171827bfbee1SPeter Avalos static int
handle_action(netdissect_options * ndo,const uint8_t * src,const u_char * p,u_int length)1719411677aeSAaron LI handle_action(netdissect_options *ndo,
1720411677aeSAaron LI const uint8_t *src, const u_char *p, u_int length)
172127bfbee1SPeter Avalos {
1722*ed775ee7SAntonio Huete Jimenez ND_TCHECK_2(p);
172327bfbee1SPeter Avalos if (length < 2)
1724*ed775ee7SAntonio Huete Jimenez goto trunc;
1725411677aeSAaron LI if (ndo->ndo_eflag) {
1726*ed775ee7SAntonio Huete Jimenez ND_PRINT(": ");
172727bfbee1SPeter Avalos } else {
1728*ed775ee7SAntonio Huete Jimenez ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
172927bfbee1SPeter Avalos }
1730*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(p)) {
1731*ed775ee7SAntonio Huete Jimenez case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break;
1732*ed775ee7SAntonio Huete Jimenez case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break;
1733*ed775ee7SAntonio Huete Jimenez case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break;
1734*ed775ee7SAntonio Huete Jimenez case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break;
1735*ed775ee7SAntonio Huete Jimenez case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break;
1736*ed775ee7SAntonio Huete Jimenez case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break;
1737411677aeSAaron LI case 14:
1738*ed775ee7SAntonio Huete Jimenez ND_PRINT("MultiohopAction ");
1739*ed775ee7SAntonio Huete Jimenez PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break;
1740411677aeSAaron LI case 15:
1741*ed775ee7SAntonio Huete Jimenez ND_PRINT("SelfprotectAction ");
1742*ed775ee7SAntonio Huete Jimenez PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break;
1743*ed775ee7SAntonio Huete Jimenez case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break;
174427bfbee1SPeter Avalos default:
1745*ed775ee7SAntonio Huete Jimenez ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1));
174627bfbee1SPeter Avalos break;
174727bfbee1SPeter Avalos }
174827bfbee1SPeter Avalos return 1;
1749*ed775ee7SAntonio Huete Jimenez trunc:
1750*ed775ee7SAntonio Huete Jimenez return 0;
175127bfbee1SPeter Avalos }
175227bfbee1SPeter Avalos
175341c99275SPeter Avalos
175441c99275SPeter Avalos /*********************************************************************************
175541c99275SPeter Avalos * Print Body funcs
175641c99275SPeter Avalos *********************************************************************************/
175741c99275SPeter Avalos
175841c99275SPeter Avalos
175941c99275SPeter Avalos static int
mgmt_body_print(netdissect_options * ndo,uint16_t fc,const uint8_t * src,const u_char * p,u_int length)1760411677aeSAaron LI mgmt_body_print(netdissect_options *ndo,
1761411677aeSAaron LI uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
176241c99275SPeter Avalos {
1763*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
1764411677aeSAaron LI
1765411677aeSAaron LI /* There may be a problem w/ AP not having this bit set */
1766411677aeSAaron LI if (FC_PROTECTED(fc))
1767411677aeSAaron LI return wep_print(ndo, p);
176841c99275SPeter Avalos switch (FC_SUBTYPE(fc)) {
176941c99275SPeter Avalos case ST_ASSOC_REQUEST:
1770411677aeSAaron LI return handle_assoc_request(ndo, p, length);
177141c99275SPeter Avalos case ST_ASSOC_RESPONSE:
1772411677aeSAaron LI return handle_assoc_response(ndo, p, length);
177341c99275SPeter Avalos case ST_REASSOC_REQUEST:
1774411677aeSAaron LI return handle_reassoc_request(ndo, p, length);
177541c99275SPeter Avalos case ST_REASSOC_RESPONSE:
1776411677aeSAaron LI return handle_reassoc_response(ndo, p, length);
177741c99275SPeter Avalos case ST_PROBE_REQUEST:
1778411677aeSAaron LI return handle_probe_request(ndo, p, length);
177941c99275SPeter Avalos case ST_PROBE_RESPONSE:
1780411677aeSAaron LI return handle_probe_response(ndo, p, length);
178141c99275SPeter Avalos case ST_BEACON:
1782411677aeSAaron LI return handle_beacon(ndo, p, length);
178341c99275SPeter Avalos case ST_ATIM:
178441c99275SPeter Avalos return handle_atim();
178541c99275SPeter Avalos case ST_DISASSOC:
1786411677aeSAaron LI return handle_disassoc(ndo, p, length);
178741c99275SPeter Avalos case ST_AUTH:
1788411677aeSAaron LI return handle_auth(ndo, p, length);
178941c99275SPeter Avalos case ST_DEAUTH:
1790411677aeSAaron LI return handle_deauth(ndo, src, p, length);
179127bfbee1SPeter Avalos case ST_ACTION:
1792411677aeSAaron LI return handle_action(ndo, src, p, length);
179341c99275SPeter Avalos default:
179441c99275SPeter Avalos return 1;
179541c99275SPeter Avalos }
179641c99275SPeter Avalos }
179741c99275SPeter Avalos
179841c99275SPeter Avalos
179941c99275SPeter Avalos /*********************************************************************************
180041c99275SPeter Avalos * Handles printing all the control frame types
180141c99275SPeter Avalos *********************************************************************************/
180241c99275SPeter Avalos
180341c99275SPeter Avalos static int
ctrl_body_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1804411677aeSAaron LI ctrl_body_print(netdissect_options *ndo,
1805411677aeSAaron LI uint16_t fc, const u_char *p)
180641c99275SPeter Avalos {
1807*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
180841c99275SPeter Avalos switch (FC_SUBTYPE(fc)) {
180927bfbee1SPeter Avalos case CTRL_CONTROL_WRAPPER:
181027bfbee1SPeter Avalos /* XXX - requires special handling */
181127bfbee1SPeter Avalos break;
181227bfbee1SPeter Avalos case CTRL_BAR:
1813*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
1814411677aeSAaron LI if (!ndo->ndo_eflag)
1815*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
1816*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
1817*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
1818*ed775ee7SAntonio Huete Jimenez GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
1819*ed775ee7SAntonio Huete Jimenez GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
182027bfbee1SPeter Avalos break;
182127bfbee1SPeter Avalos case CTRL_BA:
1822*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
1823411677aeSAaron LI if (!ndo->ndo_eflag)
1824*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s ",
1825*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
182627bfbee1SPeter Avalos break;
182741c99275SPeter Avalos case CTRL_PS_POLL:
1828*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
1829*ed775ee7SAntonio Huete Jimenez ND_PRINT(" AID(%x)",
1830*ed775ee7SAntonio Huete Jimenez GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
183141c99275SPeter Avalos break;
183241c99275SPeter Avalos case CTRL_RTS:
1833*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
1834411677aeSAaron LI if (!ndo->ndo_eflag)
1835*ed775ee7SAntonio Huete Jimenez ND_PRINT(" TA:%s ",
1836*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
183741c99275SPeter Avalos break;
183841c99275SPeter Avalos case CTRL_CTS:
1839*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
1840411677aeSAaron LI if (!ndo->ndo_eflag)
1841*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s ",
1842*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
184341c99275SPeter Avalos break;
184441c99275SPeter Avalos case CTRL_ACK:
1845*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
1846411677aeSAaron LI if (!ndo->ndo_eflag)
1847*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s ",
1848*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
184941c99275SPeter Avalos break;
185041c99275SPeter Avalos case CTRL_CF_END:
1851*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
1852411677aeSAaron LI if (!ndo->ndo_eflag)
1853*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s ",
1854*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
185541c99275SPeter Avalos break;
185641c99275SPeter Avalos case CTRL_END_ACK:
1857*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
1858411677aeSAaron LI if (!ndo->ndo_eflag)
1859*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s ",
1860*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
186141c99275SPeter Avalos break;
186241c99275SPeter Avalos }
186341c99275SPeter Avalos return 1;
1864*ed775ee7SAntonio Huete Jimenez trunc:
1865*ed775ee7SAntonio Huete Jimenez return 0;
186641c99275SPeter Avalos }
186741c99275SPeter Avalos
186841c99275SPeter Avalos /*
186941c99275SPeter Avalos * Data Frame - Address field contents
187041c99275SPeter Avalos *
187141c99275SPeter Avalos * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
187241c99275SPeter Avalos * 0 | 0 | DA | SA | BSSID | n/a
187341c99275SPeter Avalos * 0 | 1 | DA | BSSID | SA | n/a
187441c99275SPeter Avalos * 1 | 0 | BSSID | SA | DA | n/a
187541c99275SPeter Avalos * 1 | 1 | RA | TA | DA | SA
187641c99275SPeter Avalos */
187741c99275SPeter Avalos
1878411677aeSAaron LI /*
1879411677aeSAaron LI * Function to get source and destination MAC addresses for a data frame.
1880411677aeSAaron LI */
188141c99275SPeter Avalos static void
get_data_src_dst_mac(uint16_t fc,const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)1882411677aeSAaron LI get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
1883411677aeSAaron LI const uint8_t **dstp)
188441c99275SPeter Avalos {
188541c99275SPeter Avalos #define ADDR1 (p + 4)
188641c99275SPeter Avalos #define ADDR2 (p + 10)
188741c99275SPeter Avalos #define ADDR3 (p + 16)
188841c99275SPeter Avalos #define ADDR4 (p + 24)
188941c99275SPeter Avalos
1890411677aeSAaron LI if (!FC_TO_DS(fc)) {
1891411677aeSAaron LI if (!FC_FROM_DS(fc)) {
1892411677aeSAaron LI /* not To DS and not From DS */
189341c99275SPeter Avalos *srcp = ADDR2;
189441c99275SPeter Avalos *dstp = ADDR1;
1895411677aeSAaron LI } else {
1896411677aeSAaron LI /* not To DS and From DS */
189741c99275SPeter Avalos *srcp = ADDR3;
189841c99275SPeter Avalos *dstp = ADDR1;
1899411677aeSAaron LI }
1900411677aeSAaron LI } else {
1901411677aeSAaron LI if (!FC_FROM_DS(fc)) {
1902411677aeSAaron LI /* From DS and not To DS */
190341c99275SPeter Avalos *srcp = ADDR2;
190441c99275SPeter Avalos *dstp = ADDR3;
1905411677aeSAaron LI } else {
1906411677aeSAaron LI /* To DS and From DS */
190741c99275SPeter Avalos *srcp = ADDR4;
190841c99275SPeter Avalos *dstp = ADDR3;
1909411677aeSAaron LI }
191041c99275SPeter Avalos }
191141c99275SPeter Avalos
191241c99275SPeter Avalos #undef ADDR1
191341c99275SPeter Avalos #undef ADDR2
191441c99275SPeter Avalos #undef ADDR3
191541c99275SPeter Avalos #undef ADDR4
191641c99275SPeter Avalos }
191741c99275SPeter Avalos
191841c99275SPeter Avalos static void
get_mgmt_src_dst_mac(const u_char * p,const uint8_t ** srcp,const uint8_t ** dstp)1919411677aeSAaron LI get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
192041c99275SPeter Avalos {
192141c99275SPeter Avalos const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
192241c99275SPeter Avalos
192341c99275SPeter Avalos if (srcp != NULL)
192441c99275SPeter Avalos *srcp = hp->sa;
192541c99275SPeter Avalos if (dstp != NULL)
192641c99275SPeter Avalos *dstp = hp->da;
1927411677aeSAaron LI }
192841c99275SPeter Avalos
1929411677aeSAaron LI /*
1930411677aeSAaron LI * Print Header funcs
1931411677aeSAaron LI */
1932411677aeSAaron LI
1933411677aeSAaron LI static void
data_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1934411677aeSAaron LI data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1935411677aeSAaron LI {
1936411677aeSAaron LI u_int subtype = FC_SUBTYPE(fc);
1937411677aeSAaron LI
1938411677aeSAaron LI if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
1939411677aeSAaron LI DATA_FRAME_IS_QOS(subtype)) {
1940*ed775ee7SAntonio Huete Jimenez ND_PRINT("CF ");
1941411677aeSAaron LI if (DATA_FRAME_IS_CF_ACK(subtype)) {
1942411677aeSAaron LI if (DATA_FRAME_IS_CF_POLL(subtype))
1943*ed775ee7SAntonio Huete Jimenez ND_PRINT("Ack/Poll");
1944411677aeSAaron LI else
1945*ed775ee7SAntonio Huete Jimenez ND_PRINT("Ack");
1946411677aeSAaron LI } else {
1947411677aeSAaron LI if (DATA_FRAME_IS_CF_POLL(subtype))
1948*ed775ee7SAntonio Huete Jimenez ND_PRINT("Poll");
1949411677aeSAaron LI }
1950411677aeSAaron LI if (DATA_FRAME_IS_QOS(subtype))
1951*ed775ee7SAntonio Huete Jimenez ND_PRINT("+QoS");
1952*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
1953411677aeSAaron LI }
1954411677aeSAaron LI
1955411677aeSAaron LI #define ADDR1 (p + 4)
1956411677aeSAaron LI #define ADDR2 (p + 10)
1957411677aeSAaron LI #define ADDR3 (p + 16)
1958411677aeSAaron LI #define ADDR4 (p + 24)
1959411677aeSAaron LI
1960411677aeSAaron LI if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1961*ed775ee7SAntonio Huete Jimenez ND_PRINT("DA:%s SA:%s BSSID:%s ",
1962*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1963*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR3));
1964411677aeSAaron LI } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1965*ed775ee7SAntonio Huete Jimenez ND_PRINT("DA:%s BSSID:%s SA:%s ",
1966*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1967*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR3));
1968411677aeSAaron LI } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
1969*ed775ee7SAntonio Huete Jimenez ND_PRINT("BSSID:%s SA:%s DA:%s ",
1970*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1971*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR3));
1972411677aeSAaron LI } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
1973*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
1974*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
1975*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
1976411677aeSAaron LI }
1977411677aeSAaron LI
1978411677aeSAaron LI #undef ADDR1
1979411677aeSAaron LI #undef ADDR2
1980411677aeSAaron LI #undef ADDR3
1981411677aeSAaron LI #undef ADDR4
198241c99275SPeter Avalos }
198341c99275SPeter Avalos
198441c99275SPeter Avalos static void
mgmt_header_print(netdissect_options * ndo,const u_char * p)1985411677aeSAaron LI mgmt_header_print(netdissect_options *ndo, const u_char *p)
198641c99275SPeter Avalos {
1987411677aeSAaron LI const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
198841c99275SPeter Avalos
1989*ed775ee7SAntonio Huete Jimenez ND_PRINT("BSSID:%s DA:%s SA:%s ",
1990*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
1991*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING((hp)->sa));
1992411677aeSAaron LI }
1993411677aeSAaron LI
1994411677aeSAaron LI static void
ctrl_header_print(netdissect_options * ndo,uint16_t fc,const u_char * p)1995411677aeSAaron LI ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
1996411677aeSAaron LI {
199741c99275SPeter Avalos switch (FC_SUBTYPE(fc)) {
199827bfbee1SPeter Avalos case CTRL_BAR:
1999*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
2000*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
2001*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
2002*ed775ee7SAntonio Huete Jimenez GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
2003*ed775ee7SAntonio Huete Jimenez GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
200427bfbee1SPeter Avalos break;
200527bfbee1SPeter Avalos case CTRL_BA:
2006*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s ",
2007*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
200827bfbee1SPeter Avalos break;
200941c99275SPeter Avalos case CTRL_PS_POLL:
2010*ed775ee7SAntonio Huete Jimenez ND_PRINT("BSSID:%s TA:%s ",
2011*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
2012*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
201341c99275SPeter Avalos break;
201441c99275SPeter Avalos case CTRL_RTS:
2015*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s TA:%s ",
2016*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
2017*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
201841c99275SPeter Avalos break;
201941c99275SPeter Avalos case CTRL_CTS:
2020*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s ",
2021*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
202241c99275SPeter Avalos break;
202341c99275SPeter Avalos case CTRL_ACK:
2024*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s ",
2025*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
202641c99275SPeter Avalos break;
202741c99275SPeter Avalos case CTRL_CF_END:
2028*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s BSSID:%s ",
2029*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
2030*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
203141c99275SPeter Avalos break;
203241c99275SPeter Avalos case CTRL_END_ACK:
2033*ed775ee7SAntonio Huete Jimenez ND_PRINT("RA:%s BSSID:%s ",
2034*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
2035*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
203641c99275SPeter Avalos break;
203741c99275SPeter Avalos default:
2038411677aeSAaron LI /* We shouldn't get here - we should already have quit */
203941c99275SPeter Avalos break;
204041c99275SPeter Avalos }
204141c99275SPeter Avalos }
204241c99275SPeter Avalos
204341c99275SPeter Avalos static int
extract_header_length(netdissect_options * ndo,uint16_t fc)2044411677aeSAaron LI extract_header_length(netdissect_options *ndo,
2045411677aeSAaron LI uint16_t fc)
204641c99275SPeter Avalos {
204741c99275SPeter Avalos int len;
204841c99275SPeter Avalos
204941c99275SPeter Avalos switch (FC_TYPE(fc)) {
205041c99275SPeter Avalos case T_MGMT:
205141c99275SPeter Avalos return MGMT_HDRLEN;
205241c99275SPeter Avalos case T_CTRL:
205341c99275SPeter Avalos switch (FC_SUBTYPE(fc)) {
2054411677aeSAaron LI case CTRL_CONTROL_WRAPPER:
2055411677aeSAaron LI return CTRL_CONTROL_WRAPPER_HDRLEN;
205627bfbee1SPeter Avalos case CTRL_BAR:
205727bfbee1SPeter Avalos return CTRL_BAR_HDRLEN;
2058411677aeSAaron LI case CTRL_BA:
2059411677aeSAaron LI return CTRL_BA_HDRLEN;
206041c99275SPeter Avalos case CTRL_PS_POLL:
206141c99275SPeter Avalos return CTRL_PS_POLL_HDRLEN;
206241c99275SPeter Avalos case CTRL_RTS:
206341c99275SPeter Avalos return CTRL_RTS_HDRLEN;
206441c99275SPeter Avalos case CTRL_CTS:
206541c99275SPeter Avalos return CTRL_CTS_HDRLEN;
206641c99275SPeter Avalos case CTRL_ACK:
206741c99275SPeter Avalos return CTRL_ACK_HDRLEN;
206841c99275SPeter Avalos case CTRL_CF_END:
206941c99275SPeter Avalos return CTRL_END_HDRLEN;
207041c99275SPeter Avalos case CTRL_END_ACK:
207141c99275SPeter Avalos return CTRL_END_ACK_HDRLEN;
207241c99275SPeter Avalos default:
2073*ed775ee7SAntonio Huete Jimenez ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
207441c99275SPeter Avalos return 0;
207541c99275SPeter Avalos }
207641c99275SPeter Avalos case T_DATA:
207741c99275SPeter Avalos len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
207841c99275SPeter Avalos if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
207941c99275SPeter Avalos len += 2;
208041c99275SPeter Avalos return len;
208141c99275SPeter Avalos default:
2082*ed775ee7SAntonio Huete Jimenez ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
208341c99275SPeter Avalos return 0;
208441c99275SPeter Avalos }
208541c99275SPeter Avalos }
208641c99275SPeter Avalos
208727bfbee1SPeter Avalos static int
extract_mesh_header_length(netdissect_options * ndo,const u_char * p)2088*ed775ee7SAntonio Huete Jimenez extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
208927bfbee1SPeter Avalos {
2090*ed775ee7SAntonio Huete Jimenez return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
209127bfbee1SPeter Avalos }
209227bfbee1SPeter Avalos
209341c99275SPeter Avalos /*
2094411677aeSAaron LI * Print the 802.11 MAC header.
209541c99275SPeter Avalos */
209627bfbee1SPeter Avalos static void
ieee_802_11_hdr_print(netdissect_options * ndo,uint16_t fc,const u_char * p,u_int hdrlen,u_int meshdrlen)2097411677aeSAaron LI ieee_802_11_hdr_print(netdissect_options *ndo,
2098411677aeSAaron LI uint16_t fc, const u_char *p, u_int hdrlen,
2099411677aeSAaron LI u_int meshdrlen)
210041c99275SPeter Avalos {
2101411677aeSAaron LI if (ndo->ndo_vflag) {
210241c99275SPeter Avalos if (FC_MORE_DATA(fc))
2103*ed775ee7SAntonio Huete Jimenez ND_PRINT("More Data ");
210441c99275SPeter Avalos if (FC_MORE_FLAG(fc))
2105*ed775ee7SAntonio Huete Jimenez ND_PRINT("More Fragments ");
210641c99275SPeter Avalos if (FC_POWER_MGMT(fc))
2107*ed775ee7SAntonio Huete Jimenez ND_PRINT("Pwr Mgmt ");
210841c99275SPeter Avalos if (FC_RETRY(fc))
2109*ed775ee7SAntonio Huete Jimenez ND_PRINT("Retry ");
211041c99275SPeter Avalos if (FC_ORDER(fc))
2111*ed775ee7SAntonio Huete Jimenez ND_PRINT("Strictly Ordered ");
2112411677aeSAaron LI if (FC_PROTECTED(fc))
2113*ed775ee7SAntonio Huete Jimenez ND_PRINT("Protected ");
211441c99275SPeter Avalos if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
2115*ed775ee7SAntonio Huete Jimenez ND_PRINT("%uus ",
2116*ed775ee7SAntonio Huete Jimenez GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
211741c99275SPeter Avalos }
211827bfbee1SPeter Avalos if (meshdrlen != 0) {
211927bfbee1SPeter Avalos const struct meshcntl_t *mc =
2120*ed775ee7SAntonio Huete Jimenez (const struct meshcntl_t *)(p + hdrlen - meshdrlen);
2121*ed775ee7SAntonio Huete Jimenez u_int ae = GET_U_1(mc->flags) & 3;
212227bfbee1SPeter Avalos
2123*ed775ee7SAntonio Huete Jimenez ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
2124*ed775ee7SAntonio Huete Jimenez GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
212527bfbee1SPeter Avalos if (ae > 0)
2126*ed775ee7SAntonio Huete Jimenez ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
212727bfbee1SPeter Avalos if (ae > 1)
2128*ed775ee7SAntonio Huete Jimenez ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
212927bfbee1SPeter Avalos if (ae > 2)
2130*ed775ee7SAntonio Huete Jimenez ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
2131*ed775ee7SAntonio Huete Jimenez ND_PRINT(") ");
213227bfbee1SPeter Avalos }
213341c99275SPeter Avalos
213441c99275SPeter Avalos switch (FC_TYPE(fc)) {
213541c99275SPeter Avalos case T_MGMT:
2136411677aeSAaron LI mgmt_header_print(ndo, p);
213741c99275SPeter Avalos break;
213841c99275SPeter Avalos case T_CTRL:
2139411677aeSAaron LI ctrl_header_print(ndo, fc, p);
214041c99275SPeter Avalos break;
214141c99275SPeter Avalos case T_DATA:
2142411677aeSAaron LI data_header_print(ndo, fc, p);
214341c99275SPeter Avalos break;
214441c99275SPeter Avalos default:
214541c99275SPeter Avalos break;
214641c99275SPeter Avalos }
214741c99275SPeter Avalos }
214841c99275SPeter Avalos
214941c99275SPeter Avalos 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)2150411677aeSAaron LI ieee802_11_print(netdissect_options *ndo,
2151411677aeSAaron LI const u_char *p, u_int length, u_int orig_caplen, int pad,
215227bfbee1SPeter Avalos u_int fcslen)
215341c99275SPeter Avalos {
2154411677aeSAaron LI uint16_t fc;
215527bfbee1SPeter Avalos u_int caplen, hdrlen, meshdrlen;
2156411677aeSAaron LI struct lladdr_info src, dst;
2157411677aeSAaron LI int llc_hdrlen;
215841c99275SPeter Avalos
2159*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "802.11";
216027bfbee1SPeter Avalos caplen = orig_caplen;
216127bfbee1SPeter Avalos /* Remove FCS, if present */
216227bfbee1SPeter Avalos if (length < fcslen) {
2163*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
216441c99275SPeter Avalos return caplen;
216541c99275SPeter Avalos }
216627bfbee1SPeter Avalos length -= fcslen;
216727bfbee1SPeter Avalos if (caplen > length) {
216827bfbee1SPeter Avalos /* Amount of FCS in actual packet data, if any */
216927bfbee1SPeter Avalos fcslen = caplen - length;
217027bfbee1SPeter Avalos caplen -= fcslen;
2171411677aeSAaron LI ndo->ndo_snapend -= fcslen;
217227bfbee1SPeter Avalos }
217327bfbee1SPeter Avalos
217427bfbee1SPeter Avalos if (caplen < IEEE802_11_FC_LEN) {
2175*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
217627bfbee1SPeter Avalos return orig_caplen;
217727bfbee1SPeter Avalos }
217841c99275SPeter Avalos
2179*ed775ee7SAntonio Huete Jimenez fc = GET_LE_U_2(p);
2180411677aeSAaron LI hdrlen = extract_header_length(ndo, fc);
2181411677aeSAaron LI if (hdrlen == 0) {
2182411677aeSAaron LI /* Unknown frame type or control frame subtype; quit. */
2183411677aeSAaron LI return (0);
2184411677aeSAaron LI }
218541c99275SPeter Avalos if (pad)
218641c99275SPeter Avalos hdrlen = roundup2(hdrlen, 4);
2187411677aeSAaron LI if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
218827bfbee1SPeter Avalos DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
2189*ed775ee7SAntonio Huete Jimenez if(!ND_TTEST_1(p + hdrlen)) {
2190*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
2191411677aeSAaron LI return hdrlen;
2192411677aeSAaron LI }
2193*ed775ee7SAntonio Huete Jimenez meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
219427bfbee1SPeter Avalos hdrlen += meshdrlen;
219527bfbee1SPeter Avalos } else
219627bfbee1SPeter Avalos meshdrlen = 0;
219727bfbee1SPeter Avalos
219841c99275SPeter Avalos if (caplen < hdrlen) {
2199*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
220041c99275SPeter Avalos return hdrlen;
220141c99275SPeter Avalos }
220241c99275SPeter Avalos
2203411677aeSAaron LI if (ndo->ndo_eflag)
2204411677aeSAaron LI ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
220541c99275SPeter Avalos
220641c99275SPeter Avalos /*
220741c99275SPeter Avalos * Go past the 802.11 header.
220841c99275SPeter Avalos */
220941c99275SPeter Avalos length -= hdrlen;
221041c99275SPeter Avalos caplen -= hdrlen;
221141c99275SPeter Avalos p += hdrlen;
221241c99275SPeter Avalos
2213411677aeSAaron LI src.addr_string = etheraddr_string;
2214411677aeSAaron LI dst.addr_string = etheraddr_string;
221541c99275SPeter Avalos switch (FC_TYPE(fc)) {
221641c99275SPeter Avalos case T_MGMT:
2217411677aeSAaron LI get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
2218411677aeSAaron LI if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
2219*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
222041c99275SPeter Avalos return hdrlen;
222141c99275SPeter Avalos }
222241c99275SPeter Avalos break;
222341c99275SPeter Avalos case T_CTRL:
2224411677aeSAaron LI if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
2225*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
222641c99275SPeter Avalos return hdrlen;
222741c99275SPeter Avalos }
222841c99275SPeter Avalos break;
222941c99275SPeter Avalos case T_DATA:
223041c99275SPeter Avalos if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
223141c99275SPeter Avalos return hdrlen; /* no-data frame */
223241c99275SPeter Avalos /* There may be a problem w/ AP not having this bit set */
2233411677aeSAaron LI if (FC_PROTECTED(fc)) {
2234*ed775ee7SAntonio Huete Jimenez ND_PRINT("Data");
2235411677aeSAaron LI if (!wep_print(ndo, p)) {
2236*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
223741c99275SPeter Avalos return hdrlen;
223841c99275SPeter Avalos }
2239411677aeSAaron LI } else {
2240411677aeSAaron LI get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
2241411677aeSAaron LI llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
2242411677aeSAaron LI if (llc_hdrlen < 0) {
224341c99275SPeter Avalos /*
224441c99275SPeter Avalos * Some kinds of LLC packet we cannot
224541c99275SPeter Avalos * handle intelligently
224641c99275SPeter Avalos */
2247411677aeSAaron LI if (!ndo->ndo_suppress_default_print)
2248411677aeSAaron LI ND_DEFAULTPRINT(p, caplen);
2249411677aeSAaron LI llc_hdrlen = -llc_hdrlen;
2250411677aeSAaron LI }
2251411677aeSAaron LI hdrlen += llc_hdrlen;
225241c99275SPeter Avalos }
225341c99275SPeter Avalos break;
225441c99275SPeter Avalos default:
2255411677aeSAaron LI /* We shouldn't get here - we should already have quit */
225641c99275SPeter Avalos break;
225741c99275SPeter Avalos }
225841c99275SPeter Avalos
225941c99275SPeter Avalos return hdrlen;
226041c99275SPeter Avalos }
226141c99275SPeter Avalos
226241c99275SPeter Avalos /*
226341c99275SPeter Avalos * This is the top level routine of the printer. 'p' points
226441c99275SPeter Avalos * to the 802.11 header of the packet, 'h->ts' is the timestamp,
226541c99275SPeter Avalos * 'h->len' is the length of the packet off the wire, and 'h->caplen'
226641c99275SPeter Avalos * is the number of bytes actually captured.
226741c99275SPeter Avalos */
2268*ed775ee7SAntonio Huete Jimenez void
ieee802_11_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)2269411677aeSAaron LI ieee802_11_if_print(netdissect_options *ndo,
2270411677aeSAaron LI const struct pcap_pkthdr *h, const u_char *p)
227141c99275SPeter Avalos {
2272*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "802.11";
2273*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
227427bfbee1SPeter Avalos }
227527bfbee1SPeter Avalos
2276411677aeSAaron LI
2277411677aeSAaron LI /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
2278411677aeSAaron LI /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */
2279411677aeSAaron LI
2280411677aeSAaron LI /*-
2281411677aeSAaron LI * Copyright (c) 2003, 2004 David Young. All rights reserved.
2282411677aeSAaron LI *
2283411677aeSAaron LI * Redistribution and use in source and binary forms, with or without
2284411677aeSAaron LI * modification, are permitted provided that the following conditions
2285411677aeSAaron LI * are met:
2286411677aeSAaron LI * 1. Redistributions of source code must retain the above copyright
2287411677aeSAaron LI * notice, this list of conditions and the following disclaimer.
2288411677aeSAaron LI * 2. Redistributions in binary form must reproduce the above copyright
2289411677aeSAaron LI * notice, this list of conditions and the following disclaimer in the
2290411677aeSAaron LI * documentation and/or other materials provided with the distribution.
2291411677aeSAaron LI * 3. The name of David Young may not be used to endorse or promote
2292411677aeSAaron LI * products derived from this software without specific prior
2293411677aeSAaron LI * written permission.
2294411677aeSAaron LI *
2295411677aeSAaron LI * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
2296411677aeSAaron LI * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2297411677aeSAaron LI * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2298411677aeSAaron LI * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
2299411677aeSAaron LI * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2300411677aeSAaron LI * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2301411677aeSAaron LI * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2302411677aeSAaron LI * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2303411677aeSAaron LI * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2304411677aeSAaron LI * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2305411677aeSAaron LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2306411677aeSAaron LI * OF SUCH DAMAGE.
2307411677aeSAaron LI */
2308411677aeSAaron LI
2309411677aeSAaron LI /* A generic radio capture format is desirable. It must be
2310411677aeSAaron LI * rigidly defined (e.g., units for fields should be given),
2311411677aeSAaron LI * and easily extensible.
2312411677aeSAaron LI *
2313411677aeSAaron LI * The following is an extensible radio capture format. It is
2314411677aeSAaron LI * based on a bitmap indicating which fields are present.
2315411677aeSAaron LI *
2316411677aeSAaron LI * I am trying to describe precisely what the application programmer
2317411677aeSAaron LI * should expect in the following, and for that reason I tell the
2318411677aeSAaron LI * units and origin of each measurement (where it applies), or else I
2319411677aeSAaron LI * use sufficiently weaselly language ("is a monotonically nondecreasing
2320411677aeSAaron LI * function of...") that I cannot set false expectations for lawyerly
2321411677aeSAaron LI * readers.
2322411677aeSAaron LI */
2323411677aeSAaron LI
2324411677aeSAaron LI /*
2325411677aeSAaron LI * The radio capture header precedes the 802.11 header.
2326411677aeSAaron LI *
2327411677aeSAaron LI * Note well: all radiotap fields are little-endian.
2328411677aeSAaron LI */
2329411677aeSAaron LI struct ieee80211_radiotap_header {
2330*ed775ee7SAntonio Huete Jimenez nd_uint8_t it_version; /* Version 0. Only increases
2331411677aeSAaron LI * for drastic changes,
2332411677aeSAaron LI * introduction of compatible
2333411677aeSAaron LI * new fields does not count.
2334411677aeSAaron LI */
2335*ed775ee7SAntonio Huete Jimenez nd_uint8_t it_pad;
2336*ed775ee7SAntonio Huete Jimenez nd_uint16_t it_len; /* length of the whole
2337411677aeSAaron LI * header in bytes, including
2338411677aeSAaron LI * it_version, it_pad,
2339411677aeSAaron LI * it_len, and data fields.
2340411677aeSAaron LI */
2341*ed775ee7SAntonio Huete Jimenez nd_uint32_t it_present; /* A bitmap telling which
2342411677aeSAaron LI * fields are present. Set bit 31
2343411677aeSAaron LI * (0x80000000) to extend the
2344411677aeSAaron LI * bitmap by another 32 bits.
2345411677aeSAaron LI * Additional extensions are made
2346411677aeSAaron LI * by setting bit 31.
2347411677aeSAaron LI */
2348411677aeSAaron LI };
2349411677aeSAaron LI
2350411677aeSAaron LI /* Name Data type Units
2351411677aeSAaron LI * ---- --------- -----
2352411677aeSAaron LI *
2353411677aeSAaron LI * IEEE80211_RADIOTAP_TSFT uint64_t microseconds
2354411677aeSAaron LI *
2355411677aeSAaron LI * Value in microseconds of the MAC's 64-bit 802.11 Time
2356411677aeSAaron LI * Synchronization Function timer when the first bit of the
2357411677aeSAaron LI * MPDU arrived at the MAC. For received frames, only.
2358411677aeSAaron LI *
2359411677aeSAaron LI * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
2360411677aeSAaron LI *
2361411677aeSAaron LI * Tx/Rx frequency in MHz, followed by flags (see below).
2362411677aeSAaron LI * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
2363411677aeSAaron LI * represent an HT channel as there is not enough room in
2364411677aeSAaron LI * the flags word.
2365411677aeSAaron LI *
2366411677aeSAaron LI * IEEE80211_RADIOTAP_FHSS uint16_t see below
2367411677aeSAaron LI *
2368411677aeSAaron LI * For frequency-hopping radios, the hop set (first byte)
2369411677aeSAaron LI * and pattern (second byte).
2370411677aeSAaron LI *
2371411677aeSAaron LI * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index
2372411677aeSAaron LI *
2373411677aeSAaron LI * Tx/Rx data rate. If bit 0x80 is set then it represents an
2374411677aeSAaron LI * an MCS index and not an IEEE rate.
2375411677aeSAaron LI *
2376411677aeSAaron LI * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
2377411677aeSAaron LI * one milliwatt (dBm)
2378411677aeSAaron LI *
2379411677aeSAaron LI * RF signal power at the antenna, decibel difference from
2380411677aeSAaron LI * one milliwatt.
2381411677aeSAaron LI *
2382411677aeSAaron LI * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from
2383411677aeSAaron LI * one milliwatt (dBm)
2384411677aeSAaron LI *
2385411677aeSAaron LI * RF noise power at the antenna, decibel difference from one
2386411677aeSAaron LI * milliwatt.
2387411677aeSAaron LI *
2388411677aeSAaron LI * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
2389411677aeSAaron LI *
2390411677aeSAaron LI * RF signal power at the antenna, decibel difference from an
2391411677aeSAaron LI * arbitrary, fixed reference.
2392411677aeSAaron LI *
2393411677aeSAaron LI * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
2394411677aeSAaron LI *
2395411677aeSAaron LI * RF noise power at the antenna, decibel difference from an
2396411677aeSAaron LI * arbitrary, fixed reference point.
2397411677aeSAaron LI *
2398411677aeSAaron LI * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
2399411677aeSAaron LI *
2400411677aeSAaron LI * Quality of Barker code lock. Unitless. Monotonically
2401411677aeSAaron LI * nondecreasing with "better" lock strength. Called "Signal
2402411677aeSAaron LI * Quality" in datasheets. (Is there a standard way to measure
2403411677aeSAaron LI * this?)
2404411677aeSAaron LI *
2405411677aeSAaron LI * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
2406411677aeSAaron LI *
2407411677aeSAaron LI * Transmit power expressed as unitless distance from max
2408411677aeSAaron LI * power set at factory calibration. 0 is max power.
2409411677aeSAaron LI * Monotonically nondecreasing with lower power levels.
2410411677aeSAaron LI *
2411411677aeSAaron LI * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
2412411677aeSAaron LI *
2413411677aeSAaron LI * Transmit power expressed as decibel distance from max power
2414411677aeSAaron LI * set at factory calibration. 0 is max power. Monotonically
2415411677aeSAaron LI * nondecreasing with lower power levels.
2416411677aeSAaron LI *
2417411677aeSAaron LI * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from
2418411677aeSAaron LI * one milliwatt (dBm)
2419411677aeSAaron LI *
2420411677aeSAaron LI * Transmit power expressed as dBm (decibels from a 1 milliwatt
2421411677aeSAaron LI * reference). This is the absolute power level measured at
2422411677aeSAaron LI * the antenna port.
2423411677aeSAaron LI *
2424411677aeSAaron LI * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
2425411677aeSAaron LI *
2426411677aeSAaron LI * Properties of transmitted and received frames. See flags
2427411677aeSAaron LI * defined below.
2428411677aeSAaron LI *
2429411677aeSAaron LI * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
2430411677aeSAaron LI *
2431411677aeSAaron LI * Unitless indication of the Rx/Tx antenna for this packet.
2432411677aeSAaron LI * The first antenna is antenna 0.
2433411677aeSAaron LI *
2434411677aeSAaron LI * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
2435411677aeSAaron LI *
2436411677aeSAaron LI * Properties of received frames. See flags defined below.
2437411677aeSAaron LI *
2438411677aeSAaron LI * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap
2439411677aeSAaron LI * uint16_t MHz
2440411677aeSAaron LI * uint8_t channel number
2441411677aeSAaron LI * uint8_t .5 dBm
2442411677aeSAaron LI *
2443411677aeSAaron LI * Extended channel specification: flags (see below) followed by
2444411677aeSAaron LI * frequency in MHz, the corresponding IEEE channel number, and
2445411677aeSAaron LI * finally the maximum regulatory transmit power cap in .5 dBm
2446411677aeSAaron LI * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL
2447411677aeSAaron LI * and only one of the two should be present.
2448411677aeSAaron LI *
2449411677aeSAaron LI * IEEE80211_RADIOTAP_MCS uint8_t known
2450411677aeSAaron LI * uint8_t flags
2451411677aeSAaron LI * uint8_t mcs
2452411677aeSAaron LI *
2453411677aeSAaron LI * Bitset indicating which fields have known values, followed
2454411677aeSAaron LI * by bitset of flag values, followed by the MCS rate index as
2455411677aeSAaron LI * in IEEE 802.11n.
2456411677aeSAaron LI *
2457411677aeSAaron LI *
2458411677aeSAaron LI * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
2459411677aeSAaron LI *
2460411677aeSAaron LI * Contains the AMPDU information for the subframe.
2461411677aeSAaron LI *
2462411677aeSAaron LI * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
2463411677aeSAaron LI *
2464411677aeSAaron LI * Contains VHT information about this frame.
2465411677aeSAaron LI *
2466411677aeSAaron LI * IEEE80211_RADIOTAP_VENDOR_NAMESPACE
2467411677aeSAaron LI * uint8_t OUI[3]
2468411677aeSAaron LI * uint8_t subspace
2469411677aeSAaron LI * uint16_t length
2470411677aeSAaron LI *
2471411677aeSAaron LI * The Vendor Namespace Field contains three sub-fields. The first
2472411677aeSAaron LI * sub-field is 3 bytes long. It contains the vendor's IEEE 802
2473411677aeSAaron LI * Organizationally Unique Identifier (OUI). The fourth byte is a
2474411677aeSAaron LI * vendor-specific "namespace selector."
2475411677aeSAaron LI *
2476411677aeSAaron LI */
2477411677aeSAaron LI enum ieee80211_radiotap_type {
2478411677aeSAaron LI IEEE80211_RADIOTAP_TSFT = 0,
2479411677aeSAaron LI IEEE80211_RADIOTAP_FLAGS = 1,
2480411677aeSAaron LI IEEE80211_RADIOTAP_RATE = 2,
2481411677aeSAaron LI IEEE80211_RADIOTAP_CHANNEL = 3,
2482411677aeSAaron LI IEEE80211_RADIOTAP_FHSS = 4,
2483411677aeSAaron LI IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
2484411677aeSAaron LI IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
2485411677aeSAaron LI IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
2486411677aeSAaron LI IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
2487411677aeSAaron LI IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
2488411677aeSAaron LI IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
2489411677aeSAaron LI IEEE80211_RADIOTAP_ANTENNA = 11,
2490411677aeSAaron LI IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
2491411677aeSAaron LI IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
2492411677aeSAaron LI IEEE80211_RADIOTAP_RX_FLAGS = 14,
2493411677aeSAaron LI /* NB: gap for netbsd definitions */
2494411677aeSAaron LI IEEE80211_RADIOTAP_XCHANNEL = 18,
2495411677aeSAaron LI IEEE80211_RADIOTAP_MCS = 19,
2496411677aeSAaron LI IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
2497411677aeSAaron LI IEEE80211_RADIOTAP_VHT = 21,
2498411677aeSAaron LI IEEE80211_RADIOTAP_NAMESPACE = 29,
2499411677aeSAaron LI IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
2500411677aeSAaron LI IEEE80211_RADIOTAP_EXT = 31
2501411677aeSAaron LI };
2502411677aeSAaron LI
2503411677aeSAaron LI /* channel attributes */
2504411677aeSAaron LI #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */
2505411677aeSAaron LI #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */
2506411677aeSAaron LI #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */
2507411677aeSAaron LI #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */
2508411677aeSAaron LI #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */
2509411677aeSAaron LI #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */
2510411677aeSAaron LI #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */
2511411677aeSAaron LI #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */
2512411677aeSAaron LI #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */
2513411677aeSAaron LI #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */
2514411677aeSAaron LI #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */
2515411677aeSAaron LI #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */
2516411677aeSAaron LI #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */
2517411677aeSAaron LI #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */
2518411677aeSAaron LI #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */
2519411677aeSAaron LI
2520411677aeSAaron LI /* Useful combinations of channel characteristics, borrowed from Ethereal */
2521411677aeSAaron LI #define IEEE80211_CHAN_A \
2522411677aeSAaron LI (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
2523411677aeSAaron LI #define IEEE80211_CHAN_B \
2524411677aeSAaron LI (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
2525411677aeSAaron LI #define IEEE80211_CHAN_G \
2526411677aeSAaron LI (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
2527411677aeSAaron LI #define IEEE80211_CHAN_TA \
2528411677aeSAaron LI (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
2529411677aeSAaron LI #define IEEE80211_CHAN_TG \
2530411677aeSAaron LI (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO)
2531411677aeSAaron LI
2532411677aeSAaron LI
2533411677aeSAaron LI /* For IEEE80211_RADIOTAP_FLAGS */
2534411677aeSAaron LI #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
2535411677aeSAaron LI * during CFP
2536411677aeSAaron LI */
2537411677aeSAaron LI #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
2538411677aeSAaron LI * with short
2539411677aeSAaron LI * preamble
2540411677aeSAaron LI */
2541411677aeSAaron LI #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
2542411677aeSAaron LI * with WEP encryption
2543411677aeSAaron LI */
2544411677aeSAaron LI #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
2545411677aeSAaron LI * with fragmentation
2546411677aeSAaron LI */
2547411677aeSAaron LI #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
2548411677aeSAaron LI #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
2549411677aeSAaron LI * 802.11 header and payload
2550411677aeSAaron LI * (to 32-bit boundary)
2551411677aeSAaron LI */
2552411677aeSAaron LI #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */
2553411677aeSAaron LI
2554411677aeSAaron LI /* For IEEE80211_RADIOTAP_RX_FLAGS */
2555411677aeSAaron LI #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
2556411677aeSAaron LI #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */
2557411677aeSAaron LI
2558411677aeSAaron LI /* For IEEE80211_RADIOTAP_MCS known */
2559411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01
2560411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */
2561411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04
2562411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08
2563411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10
2564411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20
2565411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40
2566411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80
2567411677aeSAaron LI
2568411677aeSAaron LI /* For IEEE80211_RADIOTAP_MCS flags */
2569411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03
2570411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0
2571411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1
2572411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2
2573411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3
2574411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */
2575411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08
2576411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
2577411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
2578411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_1 1
2579411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_2 2
2580411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_3 3
2581411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
2582411677aeSAaron LI #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80
2583411677aeSAaron LI
2584411677aeSAaron LI /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
2585411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
2586411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
2587411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
2588411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
2589411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
2590411677aeSAaron LI #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
2591411677aeSAaron LI
2592411677aeSAaron LI /* For IEEE80211_RADIOTAP_VHT known */
2593411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001
2594411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002
2595411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004
2596411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008
2597411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010
2598411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020
2599411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040
2600411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080
2601411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100
2602411677aeSAaron LI
2603411677aeSAaron LI /* For IEEE80211_RADIOTAP_VHT flags */
2604411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_STBC 0x01
2605411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02
2606411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04
2607411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08
2608411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10
2609411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20
2610411677aeSAaron LI
2611411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f
2612411677aeSAaron LI
2613411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f
2614411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0
2615411677aeSAaron LI #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4
2616411677aeSAaron LI
2617411677aeSAaron LI #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01
2618411677aeSAaron LI
261927bfbee1SPeter Avalos #define IEEE80211_CHAN_FHSS \
262027bfbee1SPeter Avalos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
262127bfbee1SPeter Avalos #define IEEE80211_CHAN_A \
262227bfbee1SPeter Avalos (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
262327bfbee1SPeter Avalos #define IEEE80211_CHAN_B \
262427bfbee1SPeter Avalos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
262527bfbee1SPeter Avalos #define IEEE80211_CHAN_PUREG \
262627bfbee1SPeter Avalos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
262727bfbee1SPeter Avalos #define IEEE80211_CHAN_G \
262827bfbee1SPeter Avalos (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
262927bfbee1SPeter Avalos
263027bfbee1SPeter Avalos #define IS_CHAN_FHSS(flags) \
263127bfbee1SPeter Avalos ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
263227bfbee1SPeter Avalos #define IS_CHAN_A(flags) \
263327bfbee1SPeter Avalos ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
263427bfbee1SPeter Avalos #define IS_CHAN_B(flags) \
263527bfbee1SPeter Avalos ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
263627bfbee1SPeter Avalos #define IS_CHAN_PUREG(flags) \
263727bfbee1SPeter Avalos ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
263827bfbee1SPeter Avalos #define IS_CHAN_G(flags) \
263927bfbee1SPeter Avalos ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
264027bfbee1SPeter Avalos #define IS_CHAN_ANYG(flags) \
264127bfbee1SPeter Avalos (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
264227bfbee1SPeter Avalos
264327bfbee1SPeter Avalos static void
print_chaninfo(netdissect_options * ndo,uint16_t freq,uint32_t flags,uint32_t presentflags)2644411677aeSAaron LI print_chaninfo(netdissect_options *ndo,
2645*ed775ee7SAntonio Huete Jimenez uint16_t freq, uint32_t flags, uint32_t presentflags)
264627bfbee1SPeter Avalos {
2647*ed775ee7SAntonio Huete Jimenez ND_PRINT("%u MHz", freq);
2648411677aeSAaron LI if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
2649411677aeSAaron LI /*
2650411677aeSAaron LI * We have the MCS field, so this is 11n, regardless
2651411677aeSAaron LI * of what the channel flags say.
2652411677aeSAaron LI */
2653*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11n");
2654411677aeSAaron LI } else {
265527bfbee1SPeter Avalos if (IS_CHAN_FHSS(flags))
2656*ed775ee7SAntonio Huete Jimenez ND_PRINT(" FHSS");
265727bfbee1SPeter Avalos if (IS_CHAN_A(flags)) {
265827bfbee1SPeter Avalos if (flags & IEEE80211_CHAN_HALF)
2659*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11a/10Mhz");
266027bfbee1SPeter Avalos else if (flags & IEEE80211_CHAN_QUARTER)
2661*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11a/5Mhz");
266227bfbee1SPeter Avalos else
2663*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11a");
266427bfbee1SPeter Avalos }
266527bfbee1SPeter Avalos if (IS_CHAN_ANYG(flags)) {
266627bfbee1SPeter Avalos if (flags & IEEE80211_CHAN_HALF)
2667*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11g/10Mhz");
266827bfbee1SPeter Avalos else if (flags & IEEE80211_CHAN_QUARTER)
2669*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11g/5Mhz");
267027bfbee1SPeter Avalos else
2671*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11g");
267227bfbee1SPeter Avalos } else if (IS_CHAN_B(flags))
2673*ed775ee7SAntonio Huete Jimenez ND_PRINT(" 11b");
267427bfbee1SPeter Avalos if (flags & IEEE80211_CHAN_TURBO)
2675*ed775ee7SAntonio Huete Jimenez ND_PRINT(" Turbo");
2676411677aeSAaron LI }
2677411677aeSAaron LI /*
2678411677aeSAaron LI * These apply to 11n.
2679411677aeSAaron LI */
268027bfbee1SPeter Avalos if (flags & IEEE80211_CHAN_HT20)
2681*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ht/20");
268227bfbee1SPeter Avalos else if (flags & IEEE80211_CHAN_HT40D)
2683*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ht/40-");
268427bfbee1SPeter Avalos else if (flags & IEEE80211_CHAN_HT40U)
2685*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ht/40+");
2686*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ");
268741c99275SPeter Avalos }
268841c99275SPeter Avalos
268941c99275SPeter Avalos static int
print_radiotap_field(netdissect_options * ndo,struct cpack_state * s,uint32_t bit,uint8_t * flagsp,uint32_t presentflags)2690411677aeSAaron LI print_radiotap_field(netdissect_options *ndo,
2691411677aeSAaron LI struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
2692411677aeSAaron LI uint32_t presentflags)
269341c99275SPeter Avalos {
2694411677aeSAaron LI u_int i;
269541c99275SPeter Avalos int rc;
269641c99275SPeter Avalos
269741c99275SPeter Avalos switch (bit) {
269827bfbee1SPeter Avalos
2699411677aeSAaron LI case IEEE80211_RADIOTAP_TSFT: {
2700411677aeSAaron LI uint64_t tsft;
270127bfbee1SPeter Avalos
2702*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint64(ndo, s, &tsft);
2703411677aeSAaron LI if (rc != 0)
2704411677aeSAaron LI goto trunc;
2705*ed775ee7SAntonio Huete Jimenez ND_PRINT("%" PRIu64 "us tsft ", tsft);
270627bfbee1SPeter Avalos break;
270727bfbee1SPeter Avalos }
270827bfbee1SPeter Avalos
2709411677aeSAaron LI case IEEE80211_RADIOTAP_FLAGS: {
2710411677aeSAaron LI uint8_t flagsval;
271127bfbee1SPeter Avalos
2712*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &flagsval);
2713411677aeSAaron LI if (rc != 0)
2714411677aeSAaron LI goto trunc;
2715411677aeSAaron LI *flagsp = flagsval;
2716411677aeSAaron LI if (flagsval & IEEE80211_RADIOTAP_F_CFP)
2717*ed775ee7SAntonio Huete Jimenez ND_PRINT("cfp ");
2718411677aeSAaron LI if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
2719*ed775ee7SAntonio Huete Jimenez ND_PRINT("short preamble ");
2720411677aeSAaron LI if (flagsval & IEEE80211_RADIOTAP_F_WEP)
2721*ed775ee7SAntonio Huete Jimenez ND_PRINT("wep ");
2722411677aeSAaron LI if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
2723*ed775ee7SAntonio Huete Jimenez ND_PRINT("fragmented ");
2724411677aeSAaron LI if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
2725*ed775ee7SAntonio Huete Jimenez ND_PRINT("bad-fcs ");
272627bfbee1SPeter Avalos break;
272727bfbee1SPeter Avalos }
272841c99275SPeter Avalos
2729411677aeSAaron LI case IEEE80211_RADIOTAP_RATE: {
2730411677aeSAaron LI uint8_t rate;
273141c99275SPeter Avalos
2732*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &rate);
2733411677aeSAaron LI if (rc != 0)
2734411677aeSAaron LI goto trunc;
273527bfbee1SPeter Avalos /*
273627bfbee1SPeter Avalos * XXX On FreeBSD rate & 0x80 means we have an MCS. On
273727bfbee1SPeter Avalos * Linux and AirPcap it does not. (What about
2738*ed775ee7SAntonio Huete Jimenez * macOS, NetBSD, OpenBSD, and DragonFly BSD?)
273927bfbee1SPeter Avalos *
274027bfbee1SPeter Avalos * This is an issue either for proprietary extensions
274127bfbee1SPeter Avalos * to 11a or 11g, which do exist, or for 11n
274227bfbee1SPeter Avalos * implementations that stuff a rate value into
274327bfbee1SPeter Avalos * this field, which also appear to exist.
274427bfbee1SPeter Avalos *
274527bfbee1SPeter Avalos * We currently handle that by assuming that
274627bfbee1SPeter Avalos * if the 0x80 bit is set *and* the remaining
274727bfbee1SPeter Avalos * bits have a value between 0 and 15 it's
274827bfbee1SPeter Avalos * an MCS value, otherwise it's a rate. If
274927bfbee1SPeter Avalos * there are cases where systems that use
275027bfbee1SPeter Avalos * "0x80 + MCS index" for MCS indices > 15,
275127bfbee1SPeter Avalos * or stuff a rate value here between 64 and
275227bfbee1SPeter Avalos * 71.5 Mb/s in here, we'll need a preference
275327bfbee1SPeter Avalos * setting. Such rates do exist, e.g. 11n
275427bfbee1SPeter Avalos * MCS 7 at 20 MHz with a long guard interval.
275527bfbee1SPeter Avalos */
2756411677aeSAaron LI if (rate >= 0x80 && rate <= 0x8f) {
275727bfbee1SPeter Avalos /*
275827bfbee1SPeter Avalos * XXX - we don't know the channel width
275927bfbee1SPeter Avalos * or guard interval length, so we can't
276027bfbee1SPeter Avalos * convert this to a data rate.
276127bfbee1SPeter Avalos *
276227bfbee1SPeter Avalos * If you want us to show a data rate,
276327bfbee1SPeter Avalos * use the MCS field, not the Rate field;
276427bfbee1SPeter Avalos * the MCS field includes not only the
276527bfbee1SPeter Avalos * MCS index, it also includes bandwidth
276627bfbee1SPeter Avalos * and guard interval information.
276727bfbee1SPeter Avalos *
276827bfbee1SPeter Avalos * XXX - can we get the channel width
276927bfbee1SPeter Avalos * from XChannel and the guard interval
277027bfbee1SPeter Avalos * information from Flags, at least on
277127bfbee1SPeter Avalos * FreeBSD?
277227bfbee1SPeter Avalos */
2773*ed775ee7SAntonio Huete Jimenez ND_PRINT("MCS %u ", rate & 0x7f);
277427bfbee1SPeter Avalos } else
2775*ed775ee7SAntonio Huete Jimenez ND_PRINT("%2.1f Mb/s ", .5 * rate);
277641c99275SPeter Avalos break;
2777411677aeSAaron LI }
2778411677aeSAaron LI
2779411677aeSAaron LI case IEEE80211_RADIOTAP_CHANNEL: {
2780411677aeSAaron LI uint16_t frequency;
2781411677aeSAaron LI uint16_t flags;
2782411677aeSAaron LI
2783*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &frequency);
2784411677aeSAaron LI if (rc != 0)
2785411677aeSAaron LI goto trunc;
2786*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &flags);
2787411677aeSAaron LI if (rc != 0)
2788411677aeSAaron LI goto trunc;
2789411677aeSAaron LI /*
2790411677aeSAaron LI * If CHANNEL and XCHANNEL are both present, skip
2791411677aeSAaron LI * CHANNEL.
2792411677aeSAaron LI */
2793411677aeSAaron LI if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
279441c99275SPeter Avalos break;
2795411677aeSAaron LI print_chaninfo(ndo, frequency, flags, presentflags);
279641c99275SPeter Avalos break;
2797411677aeSAaron LI }
2798411677aeSAaron LI
2799411677aeSAaron LI case IEEE80211_RADIOTAP_FHSS: {
2800411677aeSAaron LI uint8_t hopset;
2801411677aeSAaron LI uint8_t hoppat;
2802411677aeSAaron LI
2803*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &hopset);
2804411677aeSAaron LI if (rc != 0)
2805411677aeSAaron LI goto trunc;
2806*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &hoppat);
2807411677aeSAaron LI if (rc != 0)
2808411677aeSAaron LI goto trunc;
2809*ed775ee7SAntonio Huete Jimenez ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
281041c99275SPeter Avalos break;
2811411677aeSAaron LI }
2812411677aeSAaron LI
2813411677aeSAaron LI case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
2814411677aeSAaron LI int8_t dbm_antsignal;
2815411677aeSAaron LI
2816*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
2817411677aeSAaron LI if (rc != 0)
2818411677aeSAaron LI goto trunc;
2819*ed775ee7SAntonio Huete Jimenez ND_PRINT("%ddBm signal ", dbm_antsignal);
282041c99275SPeter Avalos break;
2821411677aeSAaron LI }
2822411677aeSAaron LI
2823411677aeSAaron LI case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
2824411677aeSAaron LI int8_t dbm_antnoise;
2825411677aeSAaron LI
2826*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
2827411677aeSAaron LI if (rc != 0)
2828411677aeSAaron LI goto trunc;
2829*ed775ee7SAntonio Huete Jimenez ND_PRINT("%ddBm noise ", dbm_antnoise);
283041c99275SPeter Avalos break;
2831411677aeSAaron LI }
2832411677aeSAaron LI
2833411677aeSAaron LI case IEEE80211_RADIOTAP_LOCK_QUALITY: {
2834411677aeSAaron LI uint16_t lock_quality;
2835411677aeSAaron LI
2836*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &lock_quality);
2837411677aeSAaron LI if (rc != 0)
2838411677aeSAaron LI goto trunc;
2839*ed775ee7SAntonio Huete Jimenez ND_PRINT("%u sq ", lock_quality);
284041c99275SPeter Avalos break;
2841411677aeSAaron LI }
2842411677aeSAaron LI
2843411677aeSAaron LI case IEEE80211_RADIOTAP_TX_ATTENUATION: {
2844*ed775ee7SAntonio Huete Jimenez int16_t tx_attenuation;
2845411677aeSAaron LI
2846*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_int16(ndo, s, &tx_attenuation);
2847411677aeSAaron LI if (rc != 0)
2848411677aeSAaron LI goto trunc;
2849*ed775ee7SAntonio Huete Jimenez ND_PRINT("%d tx power ", -tx_attenuation);
285041c99275SPeter Avalos break;
2851411677aeSAaron LI }
2852411677aeSAaron LI
2853411677aeSAaron LI case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
2854*ed775ee7SAntonio Huete Jimenez int8_t db_tx_attenuation;
2855411677aeSAaron LI
2856*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
2857411677aeSAaron LI if (rc != 0)
2858411677aeSAaron LI goto trunc;
2859*ed775ee7SAntonio Huete Jimenez ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
286041c99275SPeter Avalos break;
2861411677aeSAaron LI }
2862411677aeSAaron LI
2863411677aeSAaron LI case IEEE80211_RADIOTAP_DBM_TX_POWER: {
2864411677aeSAaron LI int8_t dbm_tx_power;
2865411677aeSAaron LI
2866*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
2867411677aeSAaron LI if (rc != 0)
2868411677aeSAaron LI goto trunc;
2869*ed775ee7SAntonio Huete Jimenez ND_PRINT("%ddBm tx power ", dbm_tx_power);
287041c99275SPeter Avalos break;
2871411677aeSAaron LI }
2872411677aeSAaron LI
2873411677aeSAaron LI case IEEE80211_RADIOTAP_ANTENNA: {
2874411677aeSAaron LI uint8_t antenna;
2875411677aeSAaron LI
2876*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &antenna);
2877411677aeSAaron LI if (rc != 0)
2878411677aeSAaron LI goto trunc;
2879*ed775ee7SAntonio Huete Jimenez ND_PRINT("antenna %u ", antenna);
288041c99275SPeter Avalos break;
2881411677aeSAaron LI }
2882411677aeSAaron LI
2883411677aeSAaron LI case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
2884411677aeSAaron LI uint8_t db_antsignal;
2885411677aeSAaron LI
2886*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &db_antsignal);
2887411677aeSAaron LI if (rc != 0)
2888411677aeSAaron LI goto trunc;
2889*ed775ee7SAntonio Huete Jimenez ND_PRINT("%udB signal ", db_antsignal);
289041c99275SPeter Avalos break;
2891411677aeSAaron LI }
2892411677aeSAaron LI
2893411677aeSAaron LI case IEEE80211_RADIOTAP_DB_ANTNOISE: {
2894411677aeSAaron LI uint8_t db_antnoise;
2895411677aeSAaron LI
2896*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &db_antnoise);
2897411677aeSAaron LI if (rc != 0)
2898411677aeSAaron LI goto trunc;
2899*ed775ee7SAntonio Huete Jimenez ND_PRINT("%udB noise ", db_antnoise);
2900411677aeSAaron LI break;
2901411677aeSAaron LI }
2902411677aeSAaron LI
2903411677aeSAaron LI case IEEE80211_RADIOTAP_RX_FLAGS: {
2904411677aeSAaron LI uint16_t rx_flags;
2905411677aeSAaron LI
2906*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &rx_flags);
2907411677aeSAaron LI if (rc != 0)
2908411677aeSAaron LI goto trunc;
290927bfbee1SPeter Avalos /* Do nothing for now */
291027bfbee1SPeter Avalos break;
2911411677aeSAaron LI }
2912411677aeSAaron LI
2913411677aeSAaron LI case IEEE80211_RADIOTAP_XCHANNEL: {
2914411677aeSAaron LI uint32_t flags;
2915411677aeSAaron LI uint16_t frequency;
2916411677aeSAaron LI uint8_t channel;
2917411677aeSAaron LI uint8_t maxpower;
2918411677aeSAaron LI
2919*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint32(ndo, s, &flags);
2920411677aeSAaron LI if (rc != 0)
2921411677aeSAaron LI goto trunc;
2922*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &frequency);
2923411677aeSAaron LI if (rc != 0)
2924411677aeSAaron LI goto trunc;
2925*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &channel);
2926411677aeSAaron LI if (rc != 0)
2927411677aeSAaron LI goto trunc;
2928*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &maxpower);
2929411677aeSAaron LI if (rc != 0)
2930411677aeSAaron LI goto trunc;
2931411677aeSAaron LI print_chaninfo(ndo, frequency, flags, presentflags);
293227bfbee1SPeter Avalos break;
2933411677aeSAaron LI }
2934411677aeSAaron LI
293527bfbee1SPeter Avalos case IEEE80211_RADIOTAP_MCS: {
2936411677aeSAaron LI uint8_t known;
2937411677aeSAaron LI uint8_t flags;
2938411677aeSAaron LI uint8_t mcs_index;
2939411677aeSAaron LI static const char *ht_bandwidth[4] = {
294027bfbee1SPeter Avalos "20 MHz",
294127bfbee1SPeter Avalos "40 MHz",
294227bfbee1SPeter Avalos "20 MHz (L)",
294327bfbee1SPeter Avalos "20 MHz (U)"
294427bfbee1SPeter Avalos };
294527bfbee1SPeter Avalos float htrate;
294627bfbee1SPeter Avalos
2947*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &known);
2948411677aeSAaron LI if (rc != 0)
2949411677aeSAaron LI goto trunc;
2950*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &flags);
2951411677aeSAaron LI if (rc != 0)
2952411677aeSAaron LI goto trunc;
2953*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &mcs_index);
2954411677aeSAaron LI if (rc != 0)
2955411677aeSAaron LI goto trunc;
2956411677aeSAaron LI if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
295727bfbee1SPeter Avalos /*
295827bfbee1SPeter Avalos * We know the MCS index.
295927bfbee1SPeter Avalos */
2960411677aeSAaron LI if (mcs_index <= MAX_MCS_INDEX) {
296127bfbee1SPeter Avalos /*
296227bfbee1SPeter Avalos * And it's in-range.
296327bfbee1SPeter Avalos */
2964411677aeSAaron LI if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
296527bfbee1SPeter Avalos /*
296627bfbee1SPeter Avalos * And we know both the bandwidth and
296727bfbee1SPeter Avalos * the guard interval, so we can look
296827bfbee1SPeter Avalos * up the rate.
296927bfbee1SPeter Avalos */
297027bfbee1SPeter Avalos htrate =
2971*ed775ee7SAntonio Huete Jimenez ieee80211_float_htrates
2972*ed775ee7SAntonio Huete Jimenez [mcs_index]
2973*ed775ee7SAntonio Huete Jimenez [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
2974411677aeSAaron LI [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
297527bfbee1SPeter Avalos } else {
297627bfbee1SPeter Avalos /*
297727bfbee1SPeter Avalos * We don't know both the bandwidth
297827bfbee1SPeter Avalos * and the guard interval, so we can
297927bfbee1SPeter Avalos * only report the MCS index.
298027bfbee1SPeter Avalos */
298127bfbee1SPeter Avalos htrate = 0.0;
298227bfbee1SPeter Avalos }
298327bfbee1SPeter Avalos } else {
298427bfbee1SPeter Avalos /*
298527bfbee1SPeter Avalos * The MCS value is out of range.
298627bfbee1SPeter Avalos */
298727bfbee1SPeter Avalos htrate = 0.0;
298827bfbee1SPeter Avalos }
298927bfbee1SPeter Avalos if (htrate != 0.0) {
299027bfbee1SPeter Avalos /*
299127bfbee1SPeter Avalos * We have the rate.
299227bfbee1SPeter Avalos * Print it.
299327bfbee1SPeter Avalos */
2994*ed775ee7SAntonio Huete Jimenez ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
299527bfbee1SPeter Avalos } else {
299627bfbee1SPeter Avalos /*
299727bfbee1SPeter Avalos * We at least have the MCS index.
299827bfbee1SPeter Avalos * Print it.
299927bfbee1SPeter Avalos */
3000*ed775ee7SAntonio Huete Jimenez ND_PRINT("MCS %u ", mcs_index);
300127bfbee1SPeter Avalos }
300227bfbee1SPeter Avalos }
3003411677aeSAaron LI if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
3004*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s ",
3005*ed775ee7SAntonio Huete Jimenez ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
300627bfbee1SPeter Avalos }
3007411677aeSAaron LI if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
3008*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s GI ",
3009411677aeSAaron LI (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
3010*ed775ee7SAntonio Huete Jimenez "short" : "long");
301127bfbee1SPeter Avalos }
3012411677aeSAaron LI if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
3013*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s ",
3014411677aeSAaron LI (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
3015*ed775ee7SAntonio Huete Jimenez "greenfield" : "mixed");
301627bfbee1SPeter Avalos }
3017411677aeSAaron LI if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
3018*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s FEC ",
3019411677aeSAaron LI (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
3020*ed775ee7SAntonio Huete Jimenez "LDPC" : "BCC");
3021411677aeSAaron LI }
3022411677aeSAaron LI if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
3023*ed775ee7SAntonio Huete Jimenez ND_PRINT("RX-STBC%u ",
3024*ed775ee7SAntonio Huete Jimenez (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
302527bfbee1SPeter Avalos }
302627bfbee1SPeter Avalos break;
302727bfbee1SPeter Avalos }
3028411677aeSAaron LI
3029411677aeSAaron LI case IEEE80211_RADIOTAP_AMPDU_STATUS: {
3030411677aeSAaron LI uint32_t reference_num;
3031411677aeSAaron LI uint16_t flags;
3032411677aeSAaron LI uint8_t delim_crc;
3033411677aeSAaron LI uint8_t reserved;
3034411677aeSAaron LI
3035*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint32(ndo, s, &reference_num);
3036411677aeSAaron LI if (rc != 0)
3037411677aeSAaron LI goto trunc;
3038*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &flags);
3039411677aeSAaron LI if (rc != 0)
3040411677aeSAaron LI goto trunc;
3041*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &delim_crc);
3042411677aeSAaron LI if (rc != 0)
3043411677aeSAaron LI goto trunc;
3044*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &reserved);
3045411677aeSAaron LI if (rc != 0)
3046411677aeSAaron LI goto trunc;
3047411677aeSAaron LI /* Do nothing for now */
3048411677aeSAaron LI break;
304941c99275SPeter Avalos }
305041c99275SPeter Avalos
3051411677aeSAaron LI case IEEE80211_RADIOTAP_VHT: {
3052411677aeSAaron LI uint16_t known;
3053411677aeSAaron LI uint8_t flags;
3054411677aeSAaron LI uint8_t bandwidth;
3055411677aeSAaron LI uint8_t mcs_nss[4];
3056411677aeSAaron LI uint8_t coding;
3057411677aeSAaron LI uint8_t group_id;
3058411677aeSAaron LI uint16_t partial_aid;
3059411677aeSAaron LI static const char *vht_bandwidth[32] = {
3060411677aeSAaron LI "20 MHz",
3061411677aeSAaron LI "40 MHz",
3062411677aeSAaron LI "20 MHz (L)",
3063411677aeSAaron LI "20 MHz (U)",
3064411677aeSAaron LI "80 MHz",
3065411677aeSAaron LI "80 MHz (L)",
3066411677aeSAaron LI "80 MHz (U)",
3067411677aeSAaron LI "80 MHz (LL)",
3068411677aeSAaron LI "80 MHz (LU)",
3069411677aeSAaron LI "80 MHz (UL)",
3070411677aeSAaron LI "80 MHz (UU)",
3071411677aeSAaron LI "160 MHz",
3072411677aeSAaron LI "160 MHz (L)",
3073411677aeSAaron LI "160 MHz (U)",
3074411677aeSAaron LI "160 MHz (LL)",
3075411677aeSAaron LI "160 MHz (LU)",
3076411677aeSAaron LI "160 MHz (UL)",
3077411677aeSAaron LI "160 MHz (UU)",
3078411677aeSAaron LI "160 MHz (LLL)",
3079411677aeSAaron LI "160 MHz (LLU)",
3080411677aeSAaron LI "160 MHz (LUL)",
3081411677aeSAaron LI "160 MHz (UUU)",
3082411677aeSAaron LI "160 MHz (ULL)",
3083411677aeSAaron LI "160 MHz (ULU)",
3084411677aeSAaron LI "160 MHz (UUL)",
3085411677aeSAaron LI "160 MHz (UUU)",
3086411677aeSAaron LI "unknown (26)",
3087411677aeSAaron LI "unknown (27)",
3088411677aeSAaron LI "unknown (28)",
3089411677aeSAaron LI "unknown (29)",
3090411677aeSAaron LI "unknown (30)",
3091411677aeSAaron LI "unknown (31)"
3092411677aeSAaron LI };
3093411677aeSAaron LI
3094*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &known);
3095411677aeSAaron LI if (rc != 0)
3096411677aeSAaron LI goto trunc;
3097*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &flags);
3098411677aeSAaron LI if (rc != 0)
3099411677aeSAaron LI goto trunc;
3100*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &bandwidth);
3101411677aeSAaron LI if (rc != 0)
3102411677aeSAaron LI goto trunc;
3103411677aeSAaron LI for (i = 0; i < 4; i++) {
3104*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
3105411677aeSAaron LI if (rc != 0)
3106411677aeSAaron LI goto trunc;
3107411677aeSAaron LI }
3108*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &coding);
3109411677aeSAaron LI if (rc != 0)
3110411677aeSAaron LI goto trunc;
3111*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint8(ndo, s, &group_id);
3112411677aeSAaron LI if (rc != 0)
3113411677aeSAaron LI goto trunc;
3114*ed775ee7SAntonio Huete Jimenez rc = nd_cpack_uint16(ndo, s, &partial_aid);
3115411677aeSAaron LI if (rc != 0)
3116411677aeSAaron LI goto trunc;
3117411677aeSAaron LI for (i = 0; i < 4; i++) {
3118411677aeSAaron LI u_int nss, mcs;
3119411677aeSAaron LI nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
3120411677aeSAaron LI mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
3121411677aeSAaron LI
3122411677aeSAaron LI if (nss == 0)
3123411677aeSAaron LI continue;
3124411677aeSAaron LI
3125*ed775ee7SAntonio Huete Jimenez ND_PRINT("User %u MCS %u ", i, mcs);
3126*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s FEC ",
3127411677aeSAaron LI (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
3128*ed775ee7SAntonio Huete Jimenez "LDPC" : "BCC");
3129411677aeSAaron LI }
3130411677aeSAaron LI if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
3131*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s ",
3132*ed775ee7SAntonio Huete Jimenez vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
3133411677aeSAaron LI }
3134411677aeSAaron LI if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
3135*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s GI ",
3136411677aeSAaron LI (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
3137*ed775ee7SAntonio Huete Jimenez "short" : "long");
3138411677aeSAaron LI }
3139411677aeSAaron LI break;
3140411677aeSAaron LI }
3141411677aeSAaron LI
3142411677aeSAaron LI default:
3143411677aeSAaron LI /* this bit indicates a field whose
3144411677aeSAaron LI * size we do not know, so we cannot
3145411677aeSAaron LI * proceed. Just print the bit number.
3146411677aeSAaron LI */
3147*ed775ee7SAntonio Huete Jimenez ND_PRINT("[bit %u] ", bit);
3148411677aeSAaron LI return -1;
3149411677aeSAaron LI }
3150411677aeSAaron LI
3151411677aeSAaron LI return 0;
3152411677aeSAaron LI
3153411677aeSAaron LI trunc:
3154*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3155411677aeSAaron LI return rc;
3156411677aeSAaron LI }
3157411677aeSAaron LI
3158411677aeSAaron LI
3159411677aeSAaron LI static int
print_in_radiotap_namespace(netdissect_options * ndo,struct cpack_state * s,uint8_t * flags,uint32_t presentflags,int bit0)3160411677aeSAaron LI print_in_radiotap_namespace(netdissect_options *ndo,
3161411677aeSAaron LI struct cpack_state *s, uint8_t *flags,
3162411677aeSAaron LI uint32_t presentflags, int bit0)
316341c99275SPeter Avalos {
316441c99275SPeter Avalos #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
316541c99275SPeter Avalos #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
316641c99275SPeter Avalos #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
316741c99275SPeter Avalos #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
316841c99275SPeter Avalos #define BITNO_2(x) (((x) & 2) ? 1 : 0)
3169411677aeSAaron LI uint32_t present, next_present;
3170411677aeSAaron LI int bitno;
3171411677aeSAaron LI enum ieee80211_radiotap_type bit;
3172411677aeSAaron LI int rc;
3173411677aeSAaron LI
3174411677aeSAaron LI for (present = presentflags; present; present = next_present) {
3175411677aeSAaron LI /*
3176411677aeSAaron LI * Clear the least significant bit that is set.
3177411677aeSAaron LI */
3178411677aeSAaron LI next_present = present & (present - 1);
3179411677aeSAaron LI
3180411677aeSAaron LI /*
3181411677aeSAaron LI * Get the bit number, within this presence word,
3182411677aeSAaron LI * of the remaining least significant bit that
3183411677aeSAaron LI * is set.
3184411677aeSAaron LI */
3185411677aeSAaron LI bitno = BITNO_32(present ^ next_present);
3186411677aeSAaron LI
3187411677aeSAaron LI /*
3188411677aeSAaron LI * Stop if this is one of the "same meaning
3189411677aeSAaron LI * in all presence flags" bits.
3190411677aeSAaron LI */
3191411677aeSAaron LI if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
3192411677aeSAaron LI break;
3193411677aeSAaron LI
3194411677aeSAaron LI /*
3195411677aeSAaron LI * Get the radiotap bit number of that bit.
3196411677aeSAaron LI */
3197411677aeSAaron LI bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
3198411677aeSAaron LI
3199411677aeSAaron LI rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
3200411677aeSAaron LI if (rc != 0)
3201411677aeSAaron LI return rc;
3202411677aeSAaron LI }
3203411677aeSAaron LI
3204411677aeSAaron LI return 0;
3205411677aeSAaron LI }
3206411677aeSAaron LI
3207411677aeSAaron LI u_int
ieee802_11_radio_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3208411677aeSAaron LI ieee802_11_radio_print(netdissect_options *ndo,
3209411677aeSAaron LI const u_char *p, u_int length, u_int caplen)
3210411677aeSAaron LI {
321127bfbee1SPeter Avalos #define BIT(n) (1U << n)
321241c99275SPeter Avalos #define IS_EXTENDED(__p) \
3213*ed775ee7SAntonio Huete Jimenez (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
321441c99275SPeter Avalos
321541c99275SPeter Avalos struct cpack_state cpacker;
3216411677aeSAaron LI const struct ieee80211_radiotap_header *hdr;
3217411677aeSAaron LI uint32_t presentflags;
3218*ed775ee7SAntonio Huete Jimenez const nd_uint32_t *presentp, *last_presentp;
3219411677aeSAaron LI int vendor_namespace;
3220411677aeSAaron LI uint8_t vendor_oui[3];
3221411677aeSAaron LI uint8_t vendor_subnamespace;
3222411677aeSAaron LI uint16_t skip_length;
322341c99275SPeter Avalos int bit0;
322441c99275SPeter Avalos u_int len;
3225411677aeSAaron LI uint8_t flags;
322641c99275SPeter Avalos int pad;
322727bfbee1SPeter Avalos u_int fcslen;
322841c99275SPeter Avalos
3229*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "802.11_radio";
323041c99275SPeter Avalos if (caplen < sizeof(*hdr)) {
3231*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
323241c99275SPeter Avalos return caplen;
323341c99275SPeter Avalos }
323441c99275SPeter Avalos
3235411677aeSAaron LI hdr = (const struct ieee80211_radiotap_header *)p;
323641c99275SPeter Avalos
3237*ed775ee7SAntonio Huete Jimenez len = GET_LE_U_2(hdr->it_len);
3238411677aeSAaron LI if (len < sizeof(*hdr)) {
3239411677aeSAaron LI /*
3240411677aeSAaron LI * The length is the length of the entire header, so
3241411677aeSAaron LI * it must be as large as the fixed-length part of
3242411677aeSAaron LI * the header.
3243411677aeSAaron LI */
3244*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
324541c99275SPeter Avalos return caplen;
324641c99275SPeter Avalos }
3247411677aeSAaron LI
3248411677aeSAaron LI /*
3249411677aeSAaron LI * If we don't have the entire radiotap header, just give up.
3250411677aeSAaron LI */
3251411677aeSAaron LI if (caplen < len) {
3252*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3253411677aeSAaron LI return caplen;
3254411677aeSAaron LI }
3255*ed775ee7SAntonio Huete Jimenez nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
3256*ed775ee7SAntonio Huete Jimenez nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
325741c99275SPeter Avalos for (last_presentp = &hdr->it_present;
3258411677aeSAaron LI (const u_char*)(last_presentp + 1) <= p + len &&
3259411677aeSAaron LI IS_EXTENDED(last_presentp);
3260411677aeSAaron LI last_presentp++)
3261*ed775ee7SAntonio Huete Jimenez nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
326241c99275SPeter Avalos
326341c99275SPeter Avalos /* are there more bitmap extensions than bytes in header? */
3264411677aeSAaron LI if ((const u_char*)(last_presentp + 1) > p + len) {
3265*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
326641c99275SPeter Avalos return caplen;
326741c99275SPeter Avalos }
326841c99275SPeter Avalos
3269411677aeSAaron LI /*
3270411677aeSAaron LI * Start out at the beginning of the default radiotap namespace.
3271411677aeSAaron LI */
3272411677aeSAaron LI bit0 = 0;
3273411677aeSAaron LI vendor_namespace = 0;
3274411677aeSAaron LI memset(vendor_oui, 0, 3);
3275411677aeSAaron LI vendor_subnamespace = 0;
3276411677aeSAaron LI skip_length = 0;
327727bfbee1SPeter Avalos /* Assume no flags */
327827bfbee1SPeter Avalos flags = 0;
327941c99275SPeter Avalos /* Assume no Atheros padding between 802.11 header and body */
328041c99275SPeter Avalos pad = 0;
328127bfbee1SPeter Avalos /* Assume no FCS at end of frame */
328227bfbee1SPeter Avalos fcslen = 0;
3283411677aeSAaron LI for (presentp = &hdr->it_present; presentp <= last_presentp;
3284411677aeSAaron LI presentp++) {
3285*ed775ee7SAntonio Huete Jimenez presentflags = GET_LE_U_4(presentp);
328627bfbee1SPeter Avalos
3287411677aeSAaron LI /*
3288411677aeSAaron LI * If this is a vendor namespace, we don't handle it.
3289411677aeSAaron LI */
3290411677aeSAaron LI if (vendor_namespace) {
3291411677aeSAaron LI /*
3292411677aeSAaron LI * Skip past the stuff we don't understand.
3293411677aeSAaron LI * If we add support for any vendor namespaces,
3294411677aeSAaron LI * it'd be added here; use vendor_oui and
3295411677aeSAaron LI * vendor_subnamespace to interpret the fields.
3296411677aeSAaron LI */
3297*ed775ee7SAntonio Huete Jimenez if (nd_cpack_advance(&cpacker, skip_length) != 0) {
3298411677aeSAaron LI /*
3299411677aeSAaron LI * Ran out of space in the packet.
3300411677aeSAaron LI */
3301411677aeSAaron LI break;
3302411677aeSAaron LI }
330327bfbee1SPeter Avalos
3304411677aeSAaron LI /*
3305411677aeSAaron LI * We've skipped it all; nothing more to
3306411677aeSAaron LI * skip.
3307411677aeSAaron LI */
3308411677aeSAaron LI skip_length = 0;
3309411677aeSAaron LI } else {
3310411677aeSAaron LI if (print_in_radiotap_namespace(ndo, &cpacker,
3311411677aeSAaron LI &flags, presentflags, bit0) != 0) {
3312411677aeSAaron LI /*
3313411677aeSAaron LI * Fatal error - can't process anything
3314411677aeSAaron LI * more in the radiotap header.
3315411677aeSAaron LI */
3316411677aeSAaron LI break;
331741c99275SPeter Avalos }
331841c99275SPeter Avalos }
331927bfbee1SPeter Avalos
3320411677aeSAaron LI /*
3321411677aeSAaron LI * Handle the namespace switch bits; we've already handled
3322411677aeSAaron LI * the extension bit in all but the last word above.
3323411677aeSAaron LI */
3324411677aeSAaron LI switch (presentflags &
3325411677aeSAaron LI (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
3326411677aeSAaron LI
3327411677aeSAaron LI case 0:
3328411677aeSAaron LI /*
3329411677aeSAaron LI * We're not changing namespaces.
3330411677aeSAaron LI * advance to the next 32 bits in the current
3331411677aeSAaron LI * namespace.
3332411677aeSAaron LI */
3333411677aeSAaron LI bit0 += 32;
3334411677aeSAaron LI break;
3335411677aeSAaron LI
3336411677aeSAaron LI case BIT(IEEE80211_RADIOTAP_NAMESPACE):
3337411677aeSAaron LI /*
3338411677aeSAaron LI * We're switching to the radiotap namespace.
3339411677aeSAaron LI * Reset the presence-bitmap index to 0, and
3340411677aeSAaron LI * reset the namespace to the default radiotap
3341411677aeSAaron LI * namespace.
3342411677aeSAaron LI */
3343411677aeSAaron LI bit0 = 0;
3344411677aeSAaron LI vendor_namespace = 0;
3345411677aeSAaron LI memset(vendor_oui, 0, 3);
3346411677aeSAaron LI vendor_subnamespace = 0;
3347411677aeSAaron LI skip_length = 0;
3348411677aeSAaron LI break;
3349411677aeSAaron LI
3350411677aeSAaron LI case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
3351411677aeSAaron LI /*
3352411677aeSAaron LI * We're switching to a vendor namespace.
3353411677aeSAaron LI * Reset the presence-bitmap index to 0,
3354411677aeSAaron LI * note that we're in a vendor namespace,
3355411677aeSAaron LI * and fetch the fields of the Vendor Namespace
3356411677aeSAaron LI * item.
3357411677aeSAaron LI */
3358411677aeSAaron LI bit0 = 0;
3359411677aeSAaron LI vendor_namespace = 1;
3360*ed775ee7SAntonio Huete Jimenez if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
3361*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3362411677aeSAaron LI break;
3363411677aeSAaron LI }
3364*ed775ee7SAntonio Huete Jimenez if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
3365*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3366411677aeSAaron LI break;
3367411677aeSAaron LI }
3368*ed775ee7SAntonio Huete Jimenez if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
3369*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3370411677aeSAaron LI break;
3371411677aeSAaron LI }
3372*ed775ee7SAntonio Huete Jimenez if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
3373*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3374411677aeSAaron LI break;
3375411677aeSAaron LI }
3376*ed775ee7SAntonio Huete Jimenez if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
3377*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3378411677aeSAaron LI break;
3379411677aeSAaron LI }
3380*ed775ee7SAntonio Huete Jimenez if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
3381*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3382411677aeSAaron LI break;
3383411677aeSAaron LI }
3384411677aeSAaron LI break;
3385411677aeSAaron LI
3386411677aeSAaron LI default:
3387411677aeSAaron LI /*
3388411677aeSAaron LI * Illegal combination. The behavior in this
3389411677aeSAaron LI * case is undefined by the radiotap spec; we
3390411677aeSAaron LI * just ignore both bits.
3391411677aeSAaron LI */
3392411677aeSAaron LI break;
3393411677aeSAaron LI }
3394411677aeSAaron LI }
3395411677aeSAaron LI
339627bfbee1SPeter Avalos if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
339727bfbee1SPeter Avalos pad = 1; /* Atheros padding */
339827bfbee1SPeter Avalos if (flags & IEEE80211_RADIOTAP_F_FCS)
339927bfbee1SPeter Avalos fcslen = 4; /* FCS at end of packet */
3400411677aeSAaron LI return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
340127bfbee1SPeter Avalos fcslen);
340241c99275SPeter Avalos #undef BITNO_32
340341c99275SPeter Avalos #undef BITNO_16
340441c99275SPeter Avalos #undef BITNO_8
340541c99275SPeter Avalos #undef BITNO_4
340641c99275SPeter Avalos #undef BITNO_2
340741c99275SPeter Avalos #undef BIT
340841c99275SPeter Avalos }
340941c99275SPeter Avalos
341041c99275SPeter Avalos static u_int
ieee802_11_radio_avs_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen)3411*ed775ee7SAntonio Huete Jimenez ieee802_11_radio_avs_print(netdissect_options *ndo,
3412411677aeSAaron LI const u_char *p, u_int length, u_int caplen)
341341c99275SPeter Avalos {
3414411677aeSAaron LI uint32_t caphdr_len;
341541c99275SPeter Avalos
3416*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "802.11_radio_avs";
3417ea7b4bf5SPeter Avalos if (caplen < 8) {
3418*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3419ea7b4bf5SPeter Avalos return caplen;
3420ea7b4bf5SPeter Avalos }
3421ea7b4bf5SPeter Avalos
3422*ed775ee7SAntonio Huete Jimenez caphdr_len = GET_BE_U_4(p + 4);
342341c99275SPeter Avalos if (caphdr_len < 8) {
342441c99275SPeter Avalos /*
342541c99275SPeter Avalos * Yow! The capture header length is claimed not
342641c99275SPeter Avalos * to be large enough to include even the version
342741c99275SPeter Avalos * cookie or capture header length!
342841c99275SPeter Avalos */
3429*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
343041c99275SPeter Avalos return caplen;
343141c99275SPeter Avalos }
343241c99275SPeter Avalos
343341c99275SPeter Avalos if (caplen < caphdr_len) {
3434*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
343541c99275SPeter Avalos return caplen;
343641c99275SPeter Avalos }
343741c99275SPeter Avalos
3438411677aeSAaron LI return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
343927bfbee1SPeter Avalos length - caphdr_len, caplen - caphdr_len, 0, 0);
344041c99275SPeter Avalos }
344141c99275SPeter Avalos
344241c99275SPeter Avalos #define PRISM_HDR_LEN 144
344341c99275SPeter Avalos
3444ea7b4bf5SPeter Avalos #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
344541c99275SPeter Avalos #define WLANCAP_MAGIC_COOKIE_V1 0x80211001
3446ea7b4bf5SPeter Avalos #define WLANCAP_MAGIC_COOKIE_V2 0x80211002
344741c99275SPeter Avalos
344841c99275SPeter Avalos /*
344941c99275SPeter Avalos * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
345041c99275SPeter Avalos * containing information such as radio information, which we
345141c99275SPeter Avalos * currently ignore.
345241c99275SPeter Avalos *
3453ea7b4bf5SPeter Avalos * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
3454ea7b4bf5SPeter Avalos * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
3455ea7b4bf5SPeter Avalos * (currently, on Linux, there's no ARPHRD_ type for
3456ea7b4bf5SPeter Avalos * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
3457ea7b4bf5SPeter Avalos * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
3458ea7b4bf5SPeter Avalos * the AVS header, and the first 4 bytes of the header are used to
3459ea7b4bf5SPeter Avalos * indicate whether it's a Prism header or an AVS header).
346041c99275SPeter Avalos */
3461*ed775ee7SAntonio Huete Jimenez void
prism_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3462411677aeSAaron LI prism_if_print(netdissect_options *ndo,
3463411677aeSAaron LI const struct pcap_pkthdr *h, const u_char *p)
346441c99275SPeter Avalos {
346541c99275SPeter Avalos u_int caplen = h->caplen;
346641c99275SPeter Avalos u_int length = h->len;
3467411677aeSAaron LI uint32_t msgcode;
346841c99275SPeter Avalos
3469*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "prism";
347041c99275SPeter Avalos if (caplen < 4) {
3471*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3472*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += caplen;
3473*ed775ee7SAntonio Huete Jimenez return;
347441c99275SPeter Avalos }
347541c99275SPeter Avalos
3476*ed775ee7SAntonio Huete Jimenez msgcode = GET_BE_U_4(p);
3477ea7b4bf5SPeter Avalos if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
3478*ed775ee7SAntonio Huete Jimenez msgcode == WLANCAP_MAGIC_COOKIE_V2) {
3479*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
3480*ed775ee7SAntonio Huete Jimenez return;
3481*ed775ee7SAntonio Huete Jimenez }
348241c99275SPeter Avalos
348341c99275SPeter Avalos if (caplen < PRISM_HDR_LEN) {
3484*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
3485*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += caplen;
3486*ed775ee7SAntonio Huete Jimenez return;
348741c99275SPeter Avalos }
348841c99275SPeter Avalos
3489*ed775ee7SAntonio Huete Jimenez p += PRISM_HDR_LEN;
3490*ed775ee7SAntonio Huete Jimenez length -= PRISM_HDR_LEN;
3491*ed775ee7SAntonio Huete Jimenez caplen -= PRISM_HDR_LEN;
3492*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
3493*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
349441c99275SPeter Avalos }
349541c99275SPeter Avalos
349641c99275SPeter Avalos /*
349741c99275SPeter Avalos * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
3498ea7b4bf5SPeter Avalos * header, containing information such as radio information.
349941c99275SPeter Avalos */
3500*ed775ee7SAntonio Huete Jimenez void
ieee802_11_radio_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3501411677aeSAaron LI ieee802_11_radio_if_print(netdissect_options *ndo,
3502411677aeSAaron LI const struct pcap_pkthdr *h, const u_char *p)
350341c99275SPeter Avalos {
3504*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "802.11_radio";
3505*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
350641c99275SPeter Avalos }
350741c99275SPeter Avalos
3508ea7b4bf5SPeter Avalos /*
3509ea7b4bf5SPeter Avalos * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
3510ea7b4bf5SPeter Avalos * extra header, containing information such as radio information,
3511ea7b4bf5SPeter Avalos * which we currently ignore.
3512ea7b4bf5SPeter Avalos */
3513*ed775ee7SAntonio Huete Jimenez void
ieee802_11_radio_avs_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)3514411677aeSAaron LI ieee802_11_radio_avs_if_print(netdissect_options *ndo,
3515411677aeSAaron LI const struct pcap_pkthdr *h, const u_char *p)
3516ea7b4bf5SPeter Avalos {
3517*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "802.11_radio_avs";
3518*ed775ee7SAntonio Huete Jimenez ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
351941c99275SPeter Avalos }
3520