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