source: libpacketdump/link_4.c @ 8b49230

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 8b49230 was 8780774, checked in by Shane Alcock <salcock@…>, 8 years ago

Fixed libpacketdump decode issues with 802.11 on big endian hosts

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