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