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