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