Changeset 41b7eab for libpacketdump


Ignore:
Timestamp:
09/27/06 15:43:45 (15 years ago)
Author:
Scott Raynel <smr26@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
a7d1914
Parents:
fc2078d
Message:

Major changes to the libpacketdump decoder for 802.11

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libpacketdump/link_4.c

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