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