1 | /* |
---|
2 | * |
---|
3 | * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand. |
---|
4 | * All rights reserved. |
---|
5 | * |
---|
6 | * This file is part of libtrace. |
---|
7 | * |
---|
8 | * This code has been developed by the University of Waikato WAND |
---|
9 | * research group. For further information please see http://www.wand.net.nz/ |
---|
10 | * |
---|
11 | * libtrace is free software; you can redistribute it and/or modify |
---|
12 | * it under the terms of the GNU Lesser General Public License as published by |
---|
13 | * the Free Software Foundation; either version 3 of the License, or |
---|
14 | * (at your option) any later version. |
---|
15 | * |
---|
16 | * libtrace is distributed in the hope that it will be useful, |
---|
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | * GNU Lesser General Public License for more details. |
---|
20 | * |
---|
21 | * You should have received a copy of the GNU Lesser General Public License |
---|
22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
23 | * |
---|
24 | * |
---|
25 | */ |
---|
26 | /* |
---|
27 | * 802.11 libpacketdump decoder |
---|
28 | * |
---|
29 | * Originally based on "wagdump" (c) 2005 Dean Armstrong |
---|
30 | * |
---|
31 | * This decoder will attempt to do it's best at decoding the frame formats |
---|
32 | * defined in the following standards. Not all fields are decoded, but they |
---|
33 | * are at least acknowledged as being present. |
---|
34 | * |
---|
35 | * 802.11 |
---|
36 | * 802.11b |
---|
37 | * 802.11d - operation in multiple regulatory domains |
---|
38 | * 802.11e - wireless multimedia extensions |
---|
39 | * 802.11g |
---|
40 | * 802.11h - power management |
---|
41 | * 802.11i - MAC security enhancements |
---|
42 | * |
---|
43 | * It will also attempt to decode vendor specific Information Elements |
---|
44 | * if possible. |
---|
45 | * |
---|
46 | * (c) 2006 Scott Raynel <scottraynel@gmail.com> |
---|
47 | */ |
---|
48 | |
---|
49 | #include <sys/types.h> |
---|
50 | #include <netinet/in.h> |
---|
51 | #include <stdio.h> |
---|
52 | #include <inttypes.h> |
---|
53 | #include "libpacketdump.h" |
---|
54 | #include "libtrace.h" |
---|
55 | |
---|
56 | typedef struct ieee80211_frame_control { |
---|
57 | # if __BYTE_ORDER == __LITTLE_ENDIAN |
---|
58 | uint8_t version:2; |
---|
59 | uint8_t type:2; |
---|
60 | uint8_t subtype:4; |
---|
61 | uint8_t to_ds:1; |
---|
62 | uint8_t from_ds:1; |
---|
63 | uint8_t more_frag:1; |
---|
64 | uint8_t retry:1; |
---|
65 | uint8_t power:1; |
---|
66 | uint8_t more_data:1; |
---|
67 | uint8_t wep:1; |
---|
68 | uint8_t order:1; |
---|
69 | # elif __BYTE_ORDER == __BIG_ENDIAN |
---|
70 | uint8_t subtype:4; |
---|
71 | uint8_t type:2; |
---|
72 | uint8_t version:2; |
---|
73 | uint8_t order:1; |
---|
74 | uint8_t wep:1; |
---|
75 | uint8_t more_data:1; |
---|
76 | uint8_t power:1; |
---|
77 | uint8_t retry:1; |
---|
78 | uint8_t more_frag:1; |
---|
79 | uint8_t from_ds:1; |
---|
80 | uint8_t to_ds:1; |
---|
81 | #else |
---|
82 | # error "Adjust your <bits/endian.h> defines" |
---|
83 | # endif |
---|
84 | } __attribute__ ((__packed__)) ieee80211_frame_control; |
---|
85 | |
---|
86 | typedef struct ieee80211_ctrl_frame_1addr { |
---|
87 | ieee80211_frame_control ctl; |
---|
88 | uint16_t duration; |
---|
89 | uint8_t addr1[6]; |
---|
90 | } __attribute__ ((__packed__)) ieee80211_ctrl_frame_1addr; |
---|
91 | |
---|
92 | typedef struct ieee80211_ctrl_frame_2addr { |
---|
93 | ieee80211_frame_control ctl; |
---|
94 | uint16_t duration; |
---|
95 | uint8_t addr1[6]; |
---|
96 | uint8_t addr2[6]; |
---|
97 | } __attribute__ ((__packed__)) ieee80211_ctrl_frame_2addr; |
---|
98 | |
---|
99 | typedef struct ieee80211_data_frame_3 { |
---|
100 | ieee80211_frame_control ctl; |
---|
101 | uint16_t duration; |
---|
102 | uint8_t addr1[6]; |
---|
103 | uint8_t addr2[6]; |
---|
104 | uint8_t addr3[6]; |
---|
105 | uint16_t seq_ctrl; |
---|
106 | } __attribute__ ((__packed__)) ieee80211_data_frame_3; |
---|
107 | |
---|
108 | typedef struct ieee80211_data_frame { |
---|
109 | ieee80211_frame_control ctl; |
---|
110 | uint16_t duration; |
---|
111 | uint8_t addr1[6]; |
---|
112 | uint8_t addr2[6]; |
---|
113 | uint8_t addr3[6]; |
---|
114 | uint16_t seq_ctrl; |
---|
115 | uint8_t addr4[6]; |
---|
116 | } __attribute__ ((__packed__)) ieee80211_data_frame; |
---|
117 | |
---|
118 | typedef struct ieee80211_qos_data_frame { |
---|
119 | ieee80211_frame_control ctl; |
---|
120 | uint16_t duration; |
---|
121 | uint8_t addr1[6]; |
---|
122 | uint8_t addr2[6]; |
---|
123 | uint8_t addr3[6]; |
---|
124 | uint16_t seq_ctrl; |
---|
125 | uint8_t addr4[6]; |
---|
126 | uint16_t qos; |
---|
127 | } __attribute__ ((__packed__)) ieee80211_qos_data_frame; |
---|
128 | |
---|
129 | typedef struct ieee80211_mgmt_frame { |
---|
130 | ieee80211_frame_control ctl; |
---|
131 | uint16_t duration; |
---|
132 | uint8_t addr1[6]; |
---|
133 | uint8_t addr2[6]; |
---|
134 | uint8_t addr3[6]; |
---|
135 | uint16_t seq_ctrl; |
---|
136 | } __attribute__ ((__packed__)) ieee80211_mgmt_frame; |
---|
137 | |
---|
138 | typedef struct ieee80211_payload { |
---|
139 | uint16_t ethertype; |
---|
140 | uint8_t payload[1]; |
---|
141 | } __attribute__ ((__packed__)) ieee80211_payload; |
---|
142 | |
---|
143 | static char *macaddr(uint8_t mac[]) { |
---|
144 | static char ether_buf[18] = {0, }; |
---|
145 | trace_ether_ntoa(mac, ether_buf); |
---|
146 | return ether_buf; |
---|
147 | } |
---|
148 | |
---|
149 | typedef struct ieee80211_capinfo { |
---|
150 | #if __BYTE_ORDER == __LITTLE_ENDIAN |
---|
151 | uint8_t ess:1; |
---|
152 | uint8_t ibss:1; |
---|
153 | uint8_t cf_pollable:1; |
---|
154 | uint8_t cf_poll_req:1; |
---|
155 | uint8_t privacy:1; |
---|
156 | uint8_t short_preamble:1; |
---|
157 | uint8_t pbcc:1; |
---|
158 | uint8_t channel_agility:1; |
---|
159 | uint8_t spectrum_mgmt:1; |
---|
160 | uint8_t qos:1; |
---|
161 | uint8_t short_slot_time:1; |
---|
162 | uint8_t apsd:1; |
---|
163 | uint8_t res1:1; |
---|
164 | uint8_t dsss_ofdm:1; |
---|
165 | uint8_t delayed_block_ack:1; |
---|
166 | uint8_t immediate_block_ack:1; |
---|
167 | #elif __BYTE_ORDER == __BIG_ENDIAN |
---|
168 | uint8_t channel_agility:1; |
---|
169 | uint8_t pbcc:1; |
---|
170 | uint8_t short_preamble:1; |
---|
171 | uint8_t privacy:1; |
---|
172 | uint8_t cf_poll_req:1; |
---|
173 | uint8_t cf_pollable:1; |
---|
174 | uint8_t ibss:1; |
---|
175 | uint8_t ess:1; |
---|
176 | uint8_t immediate_block_ack:1; |
---|
177 | uint8_t delayed_block_ack:1; |
---|
178 | uint8_t dsss_ofdm:1; |
---|
179 | uint8_t res1:1; |
---|
180 | uint8_t apsd:1; |
---|
181 | uint8_t short_slot_time:1; |
---|
182 | uint8_t qos:1; |
---|
183 | uint8_t spectrum_mgmt:1; |
---|
184 | #else |
---|
185 | # error "Unknown byte order -- please check <bits/endian.h>" |
---|
186 | #endif |
---|
187 | } __attribute__ ((__packed__)) ieee80211_capinfo; |
---|
188 | |
---|
189 | typedef struct ieee80211_beacon { |
---|
190 | ieee80211_mgmt_frame mgmt; |
---|
191 | uint64_t ts; |
---|
192 | uint16_t interval; |
---|
193 | ieee80211_capinfo capinfo; |
---|
194 | } __attribute__ ((__packed__)) ieee80211_beacon; |
---|
195 | |
---|
196 | typedef struct ieee80211_assoc_req { |
---|
197 | ieee80211_mgmt_frame mgmt; |
---|
198 | ieee80211_capinfo capinfo; |
---|
199 | uint16_t listen_interval; |
---|
200 | } __attribute__ ((__packed__)) ieee80211_assoc_req; |
---|
201 | |
---|
202 | typedef struct ieee80211_assoc_resp { |
---|
203 | ieee80211_mgmt_frame mgmt; |
---|
204 | ieee80211_capinfo capinfo; |
---|
205 | uint16_t status_code; |
---|
206 | uint16_t assoc_id; |
---|
207 | } __attribute__ ((__packed__)) ieee80211_assoc_resp; |
---|
208 | |
---|
209 | typedef struct ieee80211_reassoc_req { |
---|
210 | ieee80211_mgmt_frame mgmt; |
---|
211 | ieee80211_capinfo capinfo; |
---|
212 | uint16_t listen_interval; |
---|
213 | uint8_t current_address[6]; |
---|
214 | } __attribute__ ((__packed__)) ieee80211_reassoc_req; |
---|
215 | |
---|
216 | typedef struct ieee80211_auth { |
---|
217 | ieee80211_mgmt_frame mgmt; |
---|
218 | uint16_t auth_algo_num; |
---|
219 | uint16_t auth_trans_seq_num; |
---|
220 | uint16_t status_code; |
---|
221 | } __attribute__ ((__packed__)) ieee80211_auth; |
---|
222 | |
---|
223 | |
---|
224 | typedef struct ieee80211_ie { |
---|
225 | uint8_t id; |
---|
226 | uint8_t length; |
---|
227 | } __attribute__ ((__packed__)) ieee80211_ie; |
---|
228 | |
---|
229 | /* |
---|
230 | * Takes a vendor IE and decodes it |
---|
231 | */ |
---|
232 | static void decode_80211_vendor_ie(ieee80211_ie *ie) { |
---|
233 | uint8_t *data = (uint8_t *) ((char *)ie + sizeof(ieee80211_ie)); |
---|
234 | uint32_t ie_oui; |
---|
235 | printf(" Vendor Private Information Element\n"); |
---|
236 | if (ie->length <= 3) return; |
---|
237 | ie_oui = (data[0] << 16) | (data[1] << 8) | data[2]; |
---|
238 | switch(ie_oui) { |
---|
239 | case 0x0050f2: |
---|
240 | printf(" Atheros 802.11i/WPA IE\n"); |
---|
241 | break; |
---|
242 | case 0x00037f: |
---|
243 | printf(" Atheros Advanced Capability IE\n"); |
---|
244 | break; |
---|
245 | default: |
---|
246 | printf(" Unknown Vendor OUI (0x%06x)\n", ie_oui); |
---|
247 | break; |
---|
248 | } |
---|
249 | |
---|
250 | } |
---|
251 | |
---|
252 | /* |
---|
253 | * Takes a pointer to the start of the IEs in a beacon and the |
---|
254 | * length remaining and decodes the IEs. |
---|
255 | */ |
---|
256 | static void decode_80211_information_elements(const char *pkt, unsigned len) { |
---|
257 | ieee80211_ie *ie; |
---|
258 | int i = 0; |
---|
259 | const uint8_t * data; |
---|
260 | uint8_t bmap_offset; |
---|
261 | while (len >= sizeof(ieee80211_ie)) { |
---|
262 | ie = (ieee80211_ie *) pkt; |
---|
263 | |
---|
264 | if ( len < ( sizeof(ieee80211_ie) + ie->length)) { |
---|
265 | printf(" [Truncated]\n"); |
---|
266 | return; |
---|
267 | } |
---|
268 | |
---|
269 | data = (( const unsigned char *)pkt + sizeof (ieee80211_ie)); |
---|
270 | |
---|
271 | switch (ie->id) { |
---|
272 | case 0: |
---|
273 | printf(" SSID = "); |
---|
274 | for (i = 0; i < ie->length; i++) |
---|
275 | printf("%c", data[i]); |
---|
276 | printf("\n"); |
---|
277 | break; |
---|
278 | case 1: |
---|
279 | printf(" Supported Rates (Kbit/s):\n "); |
---|
280 | /* NB: the MSB of each field will be set |
---|
281 | * if the rate it describes is part of the |
---|
282 | * basic rate set, hence the AND */ |
---|
283 | for (i = 0; i < ie->length; i++) { |
---|
284 | printf("%u, ", |
---|
285 | ( (data[i]&0x7F) * 500)); |
---|
286 | |
---|
287 | } |
---|
288 | printf("%c%c\n", 0x8, 0x8); |
---|
289 | break; |
---|
290 | case 3: |
---|
291 | printf(" DSSS Channel = "); |
---|
292 | printf("%u\n", *data); |
---|
293 | break; |
---|
294 | case 5: |
---|
295 | printf(" Traffic Indication Message:\n"); |
---|
296 | printf(" DTIM Count = %u, ", *data); |
---|
297 | data++; |
---|
298 | printf("DTIM Period = %u\n", *data); |
---|
299 | data++; |
---|
300 | printf(" Broadcast/Multicast waiting = %s\n", |
---|
301 | (*data) & 0x01 ? "Yes\0" : "No\0"); |
---|
302 | bmap_offset = ((*data) & 0xFE) >> 1; |
---|
303 | data++; |
---|
304 | if ((ie->length == 4) && ( *data == 0)) { |
---|
305 | printf(" No traffic waiting for stations\n"); |
---|
306 | break; |
---|
307 | } |
---|
308 | |
---|
309 | printf(" Traffic waiting for AssocIDs: "); |
---|
310 | for (i = 0; i < (ie->length - 3); i++) { |
---|
311 | int j; |
---|
312 | for (j = 0; j < 8; j++) { |
---|
313 | if (data[i] & (1 << j)) { |
---|
314 | printf("%u ", (bmap_offset + i + 1) * 8 + j); |
---|
315 | } |
---|
316 | } |
---|
317 | } |
---|
318 | printf("\n"); |
---|
319 | |
---|
320 | break; |
---|
321 | case 7: |
---|
322 | printf(" 802.11d Country Information:\n"); |
---|
323 | printf(" ISO 3166 Country Code: %c%c\n", data[0], data[1]); |
---|
324 | printf(" Regulatory Operating Environment: "); |
---|
325 | if (data[2] == ' ') printf("Indoor/Outdoor\n"); |
---|
326 | else if (data[2] == 'O') printf("Outdoor only\n"); |
---|
327 | else if (data[2] == 'I') printf("Indoor only\n"); |
---|
328 | else printf("Unknown, code = %c\n", data[2]); |
---|
329 | data += sizeof(uint8_t) * 3; |
---|
330 | for (i = 0; i < ((ie->length - 3) / 3); i++) { |
---|
331 | printf(" First Channel: %u, Num Channels: %u, Max Tx Power %idBm\n", |
---|
332 | data[0], data[1], (int8_t) data[2]); |
---|
333 | data += sizeof(uint8_t) * 3; |
---|
334 | } |
---|
335 | |
---|
336 | break; |
---|
337 | case 11: |
---|
338 | printf(" 802.11e QBSS Load\n"); |
---|
339 | break; |
---|
340 | case 12: |
---|
341 | printf(" 802.11e EDCA Parameter\n"); |
---|
342 | break; |
---|
343 | case 13: |
---|
344 | printf(" 802.11e TSPEC\n"); |
---|
345 | break; |
---|
346 | case 14: |
---|
347 | printf(" 802.11e TCLAS\n"); |
---|
348 | break; |
---|
349 | case 15: |
---|
350 | printf(" 802.11e Schedule\n"); |
---|
351 | break; |
---|
352 | case 16: |
---|
353 | printf(" Authentication Challenge Text\n"); |
---|
354 | break; |
---|
355 | case 32: |
---|
356 | printf(" 802.11h Power Contraint\n"); |
---|
357 | printf(" Local Power Contraint = %udB\n", data[0]); |
---|
358 | break; |
---|
359 | case 33: |
---|
360 | printf(" 802.11h Power Capability\n"); |
---|
361 | printf(" Minimum Transmit Power Capability = %idBm\n", (int8_t)data[0]); |
---|
362 | printf(" Maximum Transmit Power Capability = %idBm\n", (int8_t)data[1]); |
---|
363 | break; |
---|
364 | case 34: |
---|
365 | printf(" 802.11h Transmit Power Control Request\n"); |
---|
366 | break; |
---|
367 | case 35: |
---|
368 | printf(" 802.11h Transmit Power Control Report\n"); |
---|
369 | printf(" Transmit Power = %idBm\n", (int8_t)data[0]); |
---|
370 | printf(" Link Margin = %idB\n", (int8_t)data[1]); |
---|
371 | break; |
---|
372 | case 36: |
---|
373 | printf(" 802.11h Supported Channels\n"); |
---|
374 | for(i = 0; i < (ie->length / 2); i++) { |
---|
375 | printf(" First Channel = %u, Num Channels = %u\n", data[0], data[1]); |
---|
376 | data += 2; |
---|
377 | } |
---|
378 | break; |
---|
379 | case 37: |
---|
380 | printf(" 802.11h Channel Switch Announcement\n"); |
---|
381 | printf(" New Channel Number = %u\n", data[1]); |
---|
382 | printf(" Target Beacon Transmission Times untill switch = %u\n", data[2]); |
---|
383 | if (data[0]) printf(" Don't transmit more frames until switch occurs\n"); |
---|
384 | break; |
---|
385 | case 38: |
---|
386 | printf(" 802.11h Measurement Request\n"); |
---|
387 | break; |
---|
388 | case 39: |
---|
389 | printf(" 802.11h Measurement Report\n"); |
---|
390 | break; |
---|
391 | case 40: |
---|
392 | printf(" 802.11h Quiet\n"); |
---|
393 | break; |
---|
394 | case 41: |
---|
395 | printf(" 802.11h IBSS DFS\n"); |
---|
396 | break; |
---|
397 | case 42: |
---|
398 | printf(" 802.11g ERP Information\n"); |
---|
399 | if(data[0] & 0x80) printf(" NonERP STAs are present in this BSS\n"); |
---|
400 | if(data[0] & 0x40) printf(" Use Protection Mechanism\n"); |
---|
401 | if(data[0] & 0x20) printf(" Do not use short preamble\n"); |
---|
402 | break; |
---|
403 | case 43: |
---|
404 | printf(" 802.11e TS Delay\n"); |
---|
405 | break; |
---|
406 | case 44: |
---|
407 | printf(" 802.11e TCLAS Processing\n"); |
---|
408 | break; |
---|
409 | case 46: |
---|
410 | printf(" 802.11e QoS Capability\n"); |
---|
411 | break; |
---|
412 | case 48: |
---|
413 | printf(" 802.11i RSN:\n"); |
---|
414 | break; |
---|
415 | case 50: |
---|
416 | printf(" 802.11g Extended Supported Rates (Kbit/s)\n "); |
---|
417 | for(i = 0; i < ie->length; i++) |
---|
418 | printf("%u, ", data[i] * 500); |
---|
419 | printf("%c%c\n", (char) 8, (char) 8); |
---|
420 | break; |
---|
421 | |
---|
422 | case 221: |
---|
423 | decode_80211_vendor_ie(ie); |
---|
424 | break; |
---|
425 | default: |
---|
426 | printf(" Unknown IE Element ID, 0x%02x\n", ie->id); |
---|
427 | } |
---|
428 | len -= sizeof(ieee80211_ie) + ie->length; |
---|
429 | pkt = ((char *)pkt + sizeof(ieee80211_ie) + ie->length); |
---|
430 | } |
---|
431 | } |
---|
432 | |
---|
433 | static |
---|
434 | void ieee80211_print_reason_code(uint16_t code) { |
---|
435 | switch (code) { |
---|
436 | case 0: printf("Reserved"); break; |
---|
437 | case 1: printf("Unspecified Reason"); break; |
---|
438 | case 2: printf("Previous authentication no longer valid"); break; |
---|
439 | case 3: printf("Deauthenticated because sending station is leaving or has left IBSS or BSS"); break; |
---|
440 | case 4: printf("Disassociated due to inactivity"); break; |
---|
441 | case 5: printf("Disassociated because AP is unable to handle all currently associated stations"); break; |
---|
442 | case 6: printf("Class 2 frame received from nonauthenticated station"); break; |
---|
443 | case 7: printf("Class 3 frame received from nonassociated station"); break; |
---|
444 | case 8: printf("Disassociated because AP is leaving (or has left) BSS"); break; |
---|
445 | case 9: printf("Station requesting (re)association is not authenticated with responding station"); break; |
---|
446 | default: printf("Unknown reason code: %u\n", code); |
---|
447 | } |
---|
448 | } |
---|
449 | |
---|
450 | static |
---|
451 | void ieee80211_print_status_code(uint16_t code) { |
---|
452 | switch (code) { |
---|
453 | case 0: printf("Successful"); break; |
---|
454 | case 1: printf("Unspecified failure"); break; |
---|
455 | case 10: printf("Cannot support all requested capabilities in the Capability Information field"); break; |
---|
456 | case 11: printf("Reassociation denied due to inablity to confirm that association exists"); break; |
---|
457 | case 12: printf("Association denied due to reason outside the scope of this standard"); break; |
---|
458 | case 13: printf("Responding station does not support the specified authentication algorithm"); break; |
---|
459 | case 14: printf("Received an Authentication frame with authentication transaction sequence number outside of expected sequence"); break; |
---|
460 | case 15: printf("Authentication rejected because of channege failure"); break; |
---|
461 | case 16: printf("Authentication rejected due to timeout waiting for next frame in sequence"); break; |
---|
462 | case 17: printf("Association denied because AP is unable to handle additional associated stations"); break; |
---|
463 | case 18: printf("Association denied due to requesting station not supporting all of the data rates in the BSSBasicRates parameter"); break; |
---|
464 | default: printf("Unknown status code: %u", code); |
---|
465 | } |
---|
466 | } |
---|
467 | |
---|
468 | /* Decodes a capability info field */ |
---|
469 | static void decode_80211_capinfo(ieee80211_capinfo *c) { |
---|
470 | printf(" 802.11MAC: Capability Info:"); |
---|
471 | if (c->ess) printf(" ESS"); |
---|
472 | if (c->ibss) printf(" IBSS"); |
---|
473 | if (c->cf_pollable) printf(" CF-POLLABLE"); |
---|
474 | if (c->cf_poll_req) printf(" CF-POLL-REQ"); |
---|
475 | if (c->privacy) printf(" PRIVACY"); |
---|
476 | if (c->short_preamble) printf(" SHORT-PREAMBLE"); |
---|
477 | if (c->pbcc) printf (" PBCC"); |
---|
478 | if (c->channel_agility) printf (" CHANNEL-AGILITY"); |
---|
479 | if (c->spectrum_mgmt) printf( " SPECTRUM-MGMT"); |
---|
480 | if (c->qos) printf(" QoS"); |
---|
481 | if (c->short_slot_time) printf (" SHORT-SLOT-TIME"); |
---|
482 | if (c->apsd) printf(" APSD"); |
---|
483 | if (c->dsss_ofdm) printf (" DSSS-OFDM"); |
---|
484 | if (c->delayed_block_ack) printf(" DELAYED-BLK-ACK"); |
---|
485 | if (c->immediate_block_ack) printf(" IMMEDIATE-BLK-ACK"); |
---|
486 | printf("\n"); |
---|
487 | } |
---|
488 | |
---|
489 | /* Decodes a beacon (or a probe response) */ |
---|
490 | static void decode_80211_beacon(const char *pkt, unsigned len) { |
---|
491 | ieee80211_beacon *b = (ieee80211_beacon *)pkt; |
---|
492 | if (len < sizeof(ieee80211_beacon)) { |
---|
493 | printf(" 802.11MAC: [Truncated]\n"); |
---|
494 | return; |
---|
495 | } |
---|
496 | |
---|
497 | printf(" 802.11MAC: Timestamp = %" PRIu64 "\n", b->ts); |
---|
498 | printf(" 802.11MAC: Beacon Interval = %u\n", b->interval); |
---|
499 | decode_80211_capinfo(&b->capinfo); |
---|
500 | printf(" 802.11MAC: Information Elements:\n"); |
---|
501 | decode_80211_information_elements((char *) pkt + sizeof(ieee80211_beacon), len - sizeof(ieee80211_beacon)); |
---|
502 | } |
---|
503 | |
---|
504 | static void decode_80211_assoc_request(const char *pkt, unsigned len) { |
---|
505 | ieee80211_assoc_req *a = (ieee80211_assoc_req *) pkt; |
---|
506 | |
---|
507 | if (len < sizeof(ieee80211_assoc_req)) { |
---|
508 | printf(" [Truncated association request]\n"); |
---|
509 | return; |
---|
510 | } |
---|
511 | |
---|
512 | decode_80211_capinfo(&a->capinfo); |
---|
513 | printf(" 802.11MAC: Listen Interval = %u beacon intervals\n", a->listen_interval); |
---|
514 | printf(" 802.11MAC: Information Elements:\n"); |
---|
515 | decode_80211_information_elements((char *)pkt + sizeof(ieee80211_assoc_req), len - sizeof(ieee80211_assoc_req)); |
---|
516 | } |
---|
517 | |
---|
518 | static void decode_80211_assoc_response(const char *pkt, unsigned len) { |
---|
519 | ieee80211_assoc_resp *r = (ieee80211_assoc_resp *) pkt; |
---|
520 | |
---|
521 | if (len < sizeof(ieee80211_assoc_resp)) { |
---|
522 | printf(" [Truncated association response]\n"); |
---|
523 | return; |
---|
524 | } |
---|
525 | decode_80211_capinfo(&r->capinfo); |
---|
526 | printf(" 802.11MAC: Status Code = "); |
---|
527 | ieee80211_print_status_code(r->status_code); |
---|
528 | /* AID has two most significant bits set to 1 */ |
---|
529 | printf("\n 802.11MAC: Association ID = %u\n", r->assoc_id & 0x3FFF); |
---|
530 | decode_80211_information_elements((char *)pkt + sizeof(ieee80211_assoc_resp), len-sizeof(ieee80211_assoc_resp)); |
---|
531 | } |
---|
532 | |
---|
533 | static void decode_80211_reassoc_request(const char *pkt, unsigned len) { |
---|
534 | ieee80211_reassoc_req *r = (ieee80211_reassoc_req *) pkt; |
---|
535 | |
---|
536 | if (len < sizeof(ieee80211_reassoc_req)) { |
---|
537 | printf(" [Truncated reassociation request]\n"); |
---|
538 | return; |
---|
539 | } |
---|
540 | decode_80211_capinfo(&r->capinfo); |
---|
541 | printf(" 802.11MAC: Listen Interval = %u beacon intervals\n", r->listen_interval); |
---|
542 | printf(" 802.11MAC: Current AP address = %s\n", macaddr(r->current_address)); |
---|
543 | printf(" 802.11MAC: Information Elements:\n"); |
---|
544 | decode_80211_information_elements((char *)pkt + sizeof(ieee80211_reassoc_req), len - sizeof(ieee80211_reassoc_req)); |
---|
545 | } |
---|
546 | |
---|
547 | static void decode_80211_authentication_frame(const char *pkt, unsigned len) { |
---|
548 | ieee80211_auth *auth = (ieee80211_auth *)pkt; |
---|
549 | if(len < sizeof(ieee80211_auth)) { |
---|
550 | printf(" [Truncated authentication frame]\n"); |
---|
551 | return; |
---|
552 | } |
---|
553 | printf(" 802.11MAC: Authentication algorithm number = %u\n", auth->auth_algo_num); |
---|
554 | printf(" 802.11MAC: Authentication transaction sequence number = %u\n", auth->auth_trans_seq_num); |
---|
555 | printf(" 802.11MAC: Status Code = "); |
---|
556 | ieee80211_print_status_code(auth->status_code); |
---|
557 | printf("\n 802.11MAC: Information Elements:\n"); |
---|
558 | decode_80211_information_elements((char *)pkt + sizeof(ieee80211_auth), len - sizeof(ieee80211_auth)); |
---|
559 | |
---|
560 | } |
---|
561 | |
---|
562 | static void decode_80211_mgmt(const char *pkt, unsigned len) { |
---|
563 | ieee80211_mgmt_frame *mgmt = (ieee80211_mgmt_frame *)pkt; |
---|
564 | const char *data; |
---|
565 | |
---|
566 | printf(" 802.11MAC: Management frame: "); |
---|
567 | |
---|
568 | if (len < sizeof(ieee80211_mgmt_frame)) { |
---|
569 | printf("[Truncated]\n"); |
---|
570 | return; |
---|
571 | } |
---|
572 | |
---|
573 | switch (mgmt->ctl.subtype) { |
---|
574 | case 0: printf("association request"); break; |
---|
575 | case 1: printf("association response"); break; |
---|
576 | case 2: printf("reassociation request"); break; |
---|
577 | case 3: printf("reassociation response"); break; |
---|
578 | case 4: printf("probe request"); break; |
---|
579 | case 5: printf("probe response"); break; |
---|
580 | case 8: printf("beacon"); break; |
---|
581 | case 9: printf("ATIM"); break; |
---|
582 | case 10: printf("disassociation"); break; |
---|
583 | case 11: printf("authentication"); break; |
---|
584 | case 12: printf("deauthentication"); break; |
---|
585 | case 13: printf("action"); break; |
---|
586 | default: printf("RESERVED"); break; |
---|
587 | } |
---|
588 | |
---|
589 | printf("\n 802.11MAC: Duration = %u us\n", mgmt->duration); |
---|
590 | printf(" 802.11MAC: DA = %s\n", macaddr(mgmt->addr1)); |
---|
591 | printf(" 802.11MAC: SA = %s\n", macaddr(mgmt->addr2)); |
---|
592 | printf(" 802.11MAC: BSSID = %s\n", macaddr(mgmt->addr3)); |
---|
593 | printf(" 802.11MAC: fragment no. = %u, sequence no. = %u\n", |
---|
594 | (mgmt->seq_ctrl & 0x000F) , |
---|
595 | (mgmt->seq_ctrl & 0xFFF0) >> 4); |
---|
596 | |
---|
597 | switch (mgmt->ctl.subtype) { |
---|
598 | case 0: |
---|
599 | decode_80211_assoc_request(pkt, len); |
---|
600 | break; |
---|
601 | case 1: |
---|
602 | decode_80211_assoc_response(pkt, len); |
---|
603 | break; |
---|
604 | case 2: |
---|
605 | decode_80211_reassoc_request(pkt, len); |
---|
606 | break; |
---|
607 | case 3: |
---|
608 | /* Reassoc response == assoc response */ |
---|
609 | decode_80211_assoc_response(pkt, len); |
---|
610 | break; |
---|
611 | case 4: |
---|
612 | decode_80211_information_elements((char *)pkt + sizeof(ieee80211_mgmt_frame), len - sizeof(ieee80211_mgmt_frame)); |
---|
613 | break; |
---|
614 | case 5: |
---|
615 | /* Probe response == beacon frame */ |
---|
616 | decode_80211_beacon(pkt, len); |
---|
617 | break; |
---|
618 | case 8: |
---|
619 | decode_80211_beacon(pkt, len); |
---|
620 | break; |
---|
621 | case 10: |
---|
622 | data = (pkt + sizeof(ieee80211_mgmt_frame)); |
---|
623 | printf(" 802.11MAC: Reason Code = "); |
---|
624 | ieee80211_print_reason_code((uint16_t) ((data[0] << 8) | (data[1]))); |
---|
625 | printf("\n"); |
---|
626 | break; |
---|
627 | |
---|
628 | case 11: |
---|
629 | decode_80211_authentication_frame(pkt, len); |
---|
630 | break; |
---|
631 | case 12: |
---|
632 | data = (pkt + sizeof(ieee80211_mgmt_frame)); |
---|
633 | printf(" 802.11MAC: Reason Code = "); |
---|
634 | ieee80211_print_reason_code((uint16_t) ((data[0] << 8) | (data[1]))); |
---|
635 | printf("\n"); |
---|
636 | break; |
---|
637 | default: |
---|
638 | printf(" 802.11MAC: Subtype %u decoder not implemented\n", mgmt->ctl.subtype); |
---|
639 | } |
---|
640 | |
---|
641 | printf("\n"); |
---|
642 | |
---|
643 | } |
---|
644 | |
---|
645 | static void decode_80211_ctrl(const char *pkt, unsigned len) { |
---|
646 | ieee80211_ctrl_frame_1addr *ctrl1 = (ieee80211_ctrl_frame_1addr *) pkt; |
---|
647 | ieee80211_ctrl_frame_2addr *ctrl2 = (ieee80211_ctrl_frame_2addr *) pkt; |
---|
648 | printf(" 802.11MAC: Control frame: "); |
---|
649 | |
---|
650 | if (len < sizeof(ieee80211_ctrl_frame_1addr)) { |
---|
651 | printf("[Truncated]\n"); |
---|
652 | return; |
---|
653 | } |
---|
654 | |
---|
655 | switch (ctrl1->ctl.subtype) { |
---|
656 | case 8: |
---|
657 | printf("BlockAckReq\n"); |
---|
658 | break; |
---|
659 | case 9: |
---|
660 | printf("BlockAck\n"); |
---|
661 | break; |
---|
662 | case 10: |
---|
663 | printf("PS-Poll\n"); |
---|
664 | printf(" 802.11MAC: AID = 0x%04x\n", ntohs(ctrl1->duration)); |
---|
665 | printf(" 802.11MAC: BSSID = %s\n", macaddr(ctrl1->addr1)); |
---|
666 | break; |
---|
667 | case 11: |
---|
668 | printf("RTS\n"); |
---|
669 | |
---|
670 | if (len < sizeof(ieee80211_ctrl_frame_2addr)) { |
---|
671 | printf("[Truncated]\n"); |
---|
672 | return; |
---|
673 | } |
---|
674 | |
---|
675 | printf(" 802.11MAC: RA = %s\n", macaddr(ctrl2->addr1)); |
---|
676 | printf(" 802.11MAC: TA = %s\n", macaddr(ctrl2->addr2)); |
---|
677 | break; |
---|
678 | case 12: |
---|
679 | printf("CTS\n"); |
---|
680 | printf(" 802.11MAC: RA = %s\n", macaddr(ctrl1->addr1)); |
---|
681 | break; |
---|
682 | case 13: |
---|
683 | printf("ACK\n"); |
---|
684 | printf(" 802.11MAC: RA = %s\n", macaddr(ctrl1->addr1)); |
---|
685 | break; |
---|
686 | case 14: |
---|
687 | printf("CF-End\n"); |
---|
688 | |
---|
689 | if (len < sizeof(ieee80211_ctrl_frame_2addr)) { |
---|
690 | printf("[Truncated]\n"); |
---|
691 | return; |
---|
692 | } |
---|
693 | |
---|
694 | printf(" 802.11MAC: RA = %s\n", macaddr(ctrl2->addr1)); |
---|
695 | printf(" 802.11MAC: BSSID = %s\n", macaddr(ctrl2->addr2)); |
---|
696 | break; |
---|
697 | case 15: |
---|
698 | printf("CF-End + CF-Ack\n"); |
---|
699 | |
---|
700 | if (len < sizeof(ieee80211_ctrl_frame_2addr)) { |
---|
701 | printf("[Truncated]\n"); |
---|
702 | return; |
---|
703 | } |
---|
704 | |
---|
705 | printf(" 802.11MAC: RA = %s\n", macaddr(ctrl2->addr1)); |
---|
706 | printf(" 802.11MAC: BSSID = %s\n", macaddr(ctrl2->addr2)); |
---|
707 | break; |
---|
708 | default: |
---|
709 | printf("RESERVED"); |
---|
710 | break; |
---|
711 | } |
---|
712 | |
---|
713 | } |
---|
714 | |
---|
715 | static void decode_80211_data(const char *pkt, unsigned len) { |
---|
716 | ieee80211_data_frame *data = (ieee80211_data_frame *) pkt; |
---|
717 | ieee80211_qos_data_frame *qos = (ieee80211_qos_data_frame *)pkt; |
---|
718 | ieee80211_payload *pld; |
---|
719 | uint32_t hdrlen = 0; |
---|
720 | |
---|
721 | printf(" 802.11MAC: Data frame: "); |
---|
722 | |
---|
723 | if (len < sizeof(ieee80211_data_frame_3)) { |
---|
724 | printf("[Truncated]\n"); |
---|
725 | return; |
---|
726 | } |
---|
727 | |
---|
728 | switch (data->ctl.subtype) { |
---|
729 | case 0: printf("Data"); break; |
---|
730 | case 1: printf("Data + CF-Ack"); break; |
---|
731 | case 2: printf("Data + CF-Poll"); break; |
---|
732 | case 3: printf("Data + CF-Ack + CF-Poll"); break; |
---|
733 | case 4: printf("Null (no data)"); break; |
---|
734 | case 5: printf("CF-Ack (no data)"); break; |
---|
735 | case 6: printf("CF-Poll (no data)"); break; |
---|
736 | case 7: printf("CF-Ack + CF-Poll (no data)"); break; |
---|
737 | case 8: printf("QoS Data"); break; |
---|
738 | case 9: printf("QoS Data + CF-Ack"); break; |
---|
739 | case 10: printf("QoS Data + CF-Poll"); break; |
---|
740 | case 11: printf("QoS Data + CF-Ack + CF-Poll"); break; |
---|
741 | case 12: printf("QoS Null (no data)"); break; |
---|
742 | /* subtype 13 is reserved */ |
---|
743 | case 14: printf("QoS CF-Poll (no data)"); break; |
---|
744 | case 15: printf("Qos CF-Ack + CF-Poll (no data)"); break; |
---|
745 | |
---|
746 | default: printf("RESERVED"); break; |
---|
747 | } |
---|
748 | |
---|
749 | printf("\n 802.11MAC: duration = %u us\n", data->duration); |
---|
750 | printf(" 802.11MAC: fragment no. = %u, sequence no. = %u\n", |
---|
751 | (data->seq_ctrl & 0x000F) , |
---|
752 | (data->seq_ctrl & 0xFFF0) >> 4); |
---|
753 | |
---|
754 | hdrlen = sizeof(ieee80211_data_frame_3); |
---|
755 | |
---|
756 | if (! data->ctl.from_ds && ! data->ctl.to_ds) { |
---|
757 | printf(" 802.11MAC: DA = %s\n", macaddr(data->addr1)); |
---|
758 | printf(" 802.11MAC: SA = %s\n", macaddr(data->addr2)); |
---|
759 | printf(" 802.11MAC: BSSID = %s\n", macaddr(data->addr3)); |
---|
760 | } else if ( ! data->ctl.from_ds && data->ctl.to_ds) { |
---|
761 | printf(" 802.11MAC: DA = %s\n", macaddr(data->addr3)); |
---|
762 | printf(" 802.11MAC: SA = %s\n", macaddr(data->addr2)); |
---|
763 | printf(" 802.11MAC: BSSID = %s\n", macaddr(data->addr1)); |
---|
764 | } else if ( data->ctl.from_ds && ! data->ctl.to_ds) { |
---|
765 | printf(" 802.11MAC: DA = %s\n", macaddr(data->addr1)); |
---|
766 | printf(" 802.11MAC: SA = %s\n", macaddr(data->addr3)); |
---|
767 | printf(" 802.11MAC: BSSID = %s\n", macaddr(data->addr2)); |
---|
768 | } else { |
---|
769 | /* Check to make sure we have a four-address frame first */ |
---|
770 | if (len < sizeof(ieee80211_data_frame)) { |
---|
771 | printf(" 802.11MAC: [Truncated]\n"); |
---|
772 | return; |
---|
773 | } |
---|
774 | printf(" 802.11MAC: DA = %s\n", macaddr(data->addr3)); |
---|
775 | printf(" 802.11MAC: SA = %s\n", macaddr(data->addr4)); |
---|
776 | printf(" 802.11MAC: TA = %s\n", macaddr(data->addr2)); |
---|
777 | printf(" 802.11MAC: RA = %s\n", macaddr(data->addr1)); |
---|
778 | hdrlen = sizeof(ieee80211_data_frame); /* 4 addr header */ |
---|
779 | } |
---|
780 | |
---|
781 | |
---|
782 | if (data->ctl.subtype >= 8) { |
---|
783 | printf(" 802.11e: QoS = 0x%04x\n", qos->qos); |
---|
784 | if (len > sizeof(ieee80211_qos_data_frame)) |
---|
785 | hdrlen = sizeof(ieee80211_qos_data_frame); |
---|
786 | } |
---|
787 | |
---|
788 | if (len > hdrlen) { |
---|
789 | int payload_offset = 0; |
---|
790 | uint16_t ethertype = 0; |
---|
791 | pld = (ieee80211_payload *) ((char *)pkt + hdrlen) ; |
---|
792 | if (ntohs(pld->ethertype) == 0xaaaa) { |
---|
793 | /* 802.11 payload contains an 802.2 LLC/SNAP header */ |
---|
794 | libtrace_llcsnap_t *llcsnap = (libtrace_llcsnap_t *) pld; |
---|
795 | printf(" 802.2: DSAP = 0x%x, SSAP = 0x%x, OUI = 0x%x, Type = 0x%x\n", |
---|
796 | llcsnap->dsap, llcsnap->ssap, llcsnap->oui, ntohs(llcsnap->type)); |
---|
797 | payload_offset = sizeof(libtrace_llcsnap_t); |
---|
798 | ethertype = ntohs(llcsnap->type); |
---|
799 | } else { |
---|
800 | /* 802.11 payload contains an Ethernet II frame */ |
---|
801 | printf(" 802.11MAC: Payload ethertype = 0x%04x\n", ntohs(pld->ethertype)); |
---|
802 | payload_offset = sizeof(pld->ethertype); |
---|
803 | ethertype = ntohs(pld->ethertype); |
---|
804 | } |
---|
805 | decode_next((char *) pkt + hdrlen + payload_offset, |
---|
806 | len - hdrlen - payload_offset, "eth", ethertype); |
---|
807 | } |
---|
808 | |
---|
809 | |
---|
810 | } |
---|
811 | |
---|
812 | DLLEXPORT void decode(int link_type UNUSED, const char *pkt, unsigned len) |
---|
813 | { |
---|
814 | ieee80211_frame_control *fc; |
---|
815 | |
---|
816 | if (len < sizeof(ieee80211_frame_control)) { |
---|
817 | printf(" 802.11MAC: Truncated at frame control field\n"); |
---|
818 | return; |
---|
819 | } |
---|
820 | |
---|
821 | fc = (ieee80211_frame_control *) pkt; |
---|
822 | |
---|
823 | printf(" 802.11MAC: "); |
---|
824 | |
---|
825 | printf("proto = %d, type = %d, subtype = %d, ", fc->version, fc->type, fc->subtype); |
---|
826 | |
---|
827 | printf("flags ="); |
---|
828 | if (fc->to_ds) printf(" toDS"); |
---|
829 | if (fc->from_ds) printf(" fromDS"); |
---|
830 | if (fc->more_frag) printf(" moreFrag"); |
---|
831 | if (fc->retry) printf(" retry"); |
---|
832 | if (fc->power) printf(" pwrMgmt"); |
---|
833 | if (fc->more_data) printf(" moreData"); |
---|
834 | if (fc->wep) printf(" WEP"); |
---|
835 | if (fc->order) printf(" order"); |
---|
836 | |
---|
837 | printf("\n"); |
---|
838 | switch (fc->type) { |
---|
839 | case 0: |
---|
840 | decode_80211_mgmt(pkt, len); |
---|
841 | break; |
---|
842 | case 1: |
---|
843 | decode_80211_ctrl(pkt, len); |
---|
844 | break; |
---|
845 | case 2: |
---|
846 | decode_80211_data(pkt, len); |
---|
847 | break; |
---|
848 | case 3: |
---|
849 | printf(" Unable to decode frame type %u, dumping rest of packet\n", fc->type); |
---|
850 | decode_next(pkt + sizeof(ieee80211_frame_control), len - sizeof(ieee80211_frame_control), "unknown", 0); |
---|
851 | |
---|
852 | break; |
---|
853 | } |
---|
854 | |
---|
855 | } |
---|
856 | |
---|
857 | |
---|