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