Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 1998-2007 The TCPDUMP project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that: (1) source code
      6  * distributions retain the above copyright notice and this paragraph
      7  * in its entirety, and (2) distributions including binary code include
      8  * the above copyright notice and this paragraph in its entirety in
      9  * the documentation or other materials provided with the distribution.
     10  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
     11  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
     12  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     13  * FOR A PARTICULAR PURPOSE.
     14  *
     15  * Support for the Light Weight Access Point Protocol as per RFC 5412
     16  *
     17  * Original code by Carles Kishimoto <carles.kishimoto (at) gmail.com>
     18  */
     19 
     20 #define NETDISSECT_REWORKED
     21 #ifdef HAVE_CONFIG_H
     22 #include "config.h"
     23 #endif
     24 
     25 #include <tcpdump-stdinc.h>
     26 
     27 #include "interface.h"
     28 #include "extract.h"
     29 #include "addrtoname.h"
     30 
     31 /*
     32  * LWAPP transport (common) header
     33  *      0                   1                   2                   3
     34  *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     35  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     36  *    |VER| RID |C|F|L|    Frag ID    |            Length             |
     37  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     38  *    |          Status/WLANs         |   Payload...  |
     39  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     40  *
     41  */
     42 
     43 struct lwapp_transport_header {
     44     uint8_t  version;
     45     uint8_t  frag_id;
     46     uint8_t  length[2];
     47     uint16_t status;
     48 };
     49 
     50 /*
     51  * LWAPP control header
     52  *      0                   1                   2                   3
     53  *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     54  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     55  *     |  Message Type |    Seq Num    |      Msg Element Length       |
     56  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     57  *     |                           Session ID                          |
     58  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     59  *     |      Msg Element [0..N]       |
     60  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     61  */
     62 
     63 struct lwapp_control_header {
     64     uint8_t  msg_type;
     65     uint8_t  seq_num;
     66     uint8_t  len[2];
     67     uint8_t  session_id[4];
     68 };
     69 
     70 #define LWAPP_VERSION 0
     71 #define	LWAPP_EXTRACT_VERSION(x) (((x)&0xC0)>>6)
     72 #define	LWAPP_EXTRACT_RID(x) (((x)&0x38)>>3)
     73 #define LWAPP_EXTRACT_CONTROL_BIT(x) (((x)&0x04)>>2)
     74 
     75 static const struct tok lwapp_header_bits_values[] = {
     76     { 0x01, "Last Fragment Bit"},
     77     { 0x02, "Fragment Bit"},
     78     { 0x04, "Control Bit"},
     79     { 0, NULL}
     80 };
     81 
     82 #define	LWAPP_MSGTYPE_DISCOVERY_REQUEST			1
     83 #define	LWAPP_MSGTYPE_DISCOVERY_RESPONSE		2
     84 #define	LWAPP_MSGTYPE_JOIN_REQUEST			3
     85 #define LWAPP_MSGTYPE_JOIN_RESPONSE			4
     86 #define LWAPP_MSGTYPE_JOIN_ACK				5
     87 #define LWAPP_MSGTYPE_JOIN_CONFIRM			6
     88 #define LWAPP_MSGTYPE_CONFIGURE_REQUEST			10
     89 #define LWAPP_MSGTYPE_CONFIGURE_RESPONSE		11
     90 #define LWAPP_MSGTYPE_CONF_UPDATE_REQUEST		12
     91 #define LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE		13
     92 #define LWAPP_MSGTYPE_WTP_EVENT_REQUEST			14
     93 #define LWAPP_MSGTYPE_WTP_EVENT_RESPONSE		15
     94 #define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST	16
     95 #define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE	17
     96 #define LWAPP_MSGTYPE_ECHO_REQUEST			22
     97 #define LWAPP_MSGTYPE_ECHO_RESPONSE			23
     98 #define LWAPP_MSGTYPE_IMAGE_DATA_REQUEST		24
     99 #define LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE		25
    100 #define LWAPP_MSGTYPE_RESET_REQUEST			26
    101 #define LWAPP_MSGTYPE_RESET_RESPONSE			27
    102 #define LWAPP_MSGTYPE_KEY_UPDATE_REQUEST		30
    103 #define LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE		31
    104 #define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST		32
    105 #define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE	33
    106 #define LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST		34
    107 #define LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE		35
    108 #define LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION		36
    109 #define LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST		37
    110 #define LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE		38
    111 #define LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST		39
    112 #define LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE		40
    113 
    114 static const struct tok lwapp_msg_type_values[] = {
    115     { LWAPP_MSGTYPE_DISCOVERY_REQUEST, "Discovery req"},
    116     { LWAPP_MSGTYPE_DISCOVERY_RESPONSE, "Discovery resp"},
    117     { LWAPP_MSGTYPE_JOIN_REQUEST, "Join req"},
    118     { LWAPP_MSGTYPE_JOIN_RESPONSE, "Join resp"},
    119     { LWAPP_MSGTYPE_JOIN_ACK, "Join ack"},
    120     { LWAPP_MSGTYPE_JOIN_CONFIRM, "Join confirm"},
    121     { LWAPP_MSGTYPE_CONFIGURE_REQUEST, "Configure req"},
    122     { LWAPP_MSGTYPE_CONFIGURE_RESPONSE, "Configure resp"},
    123     { LWAPP_MSGTYPE_CONF_UPDATE_REQUEST, "Update req"},
    124     { LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE, "Update resp"},
    125     { LWAPP_MSGTYPE_WTP_EVENT_REQUEST, "WTP event req"},
    126     { LWAPP_MSGTYPE_WTP_EVENT_RESPONSE, "WTP event resp"},
    127     { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST, "Change state event req"},
    128     { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE, "Change state event resp"},
    129     { LWAPP_MSGTYPE_ECHO_REQUEST, "Echo req"},
    130     { LWAPP_MSGTYPE_ECHO_RESPONSE, "Echo resp"},
    131     { LWAPP_MSGTYPE_IMAGE_DATA_REQUEST, "Image data req"},
    132     { LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE, "Image data resp"},
    133     { LWAPP_MSGTYPE_RESET_REQUEST, "Channel status req"},
    134     { LWAPP_MSGTYPE_RESET_RESPONSE, "Channel status resp"},
    135     { LWAPP_MSGTYPE_KEY_UPDATE_REQUEST, "Key update req"},
    136     { LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE, "Key update resp"},
    137     { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST, "Primary discovery req"},
    138     { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE, "Primary discovery resp"},
    139     { LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST, "Data transfer req"},
    140     { LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE, "Data transfer resp"},
    141     { LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION, "Clear config ind"},
    142     { LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST, "Wlan config req"},
    143     { LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE, "Wlan config resp"},
    144     { LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST, "Mobile config req"},
    145     { LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE, "Mobile config resp"},
    146     { 0, NULL}
    147 };
    148 
    149 /*
    150  * LWAPP message elements
    151  *
    152  * 0                   1                   2                   3
    153  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    154  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    155  * |      Type     |             Length            |   Value ...   |
    156  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    157  */
    158 struct lwapp_message_header {
    159     uint8_t type;
    160     uint8_t length[2];
    161 };
    162 
    163 void
    164 lwapp_control_print(netdissect_options *ndo,
    165                     const u_char *pptr, u_int len, int has_ap_ident)
    166 {
    167     const struct lwapp_transport_header *lwapp_trans_header;
    168     const struct lwapp_control_header *lwapp_control_header;
    169     const u_char *tptr;
    170     int  tlen;
    171     int  msg_tlen;
    172 
    173     tptr=pptr;
    174 
    175     if (has_ap_ident) {
    176         /* check if enough bytes for AP identity */
    177         ND_TCHECK2(*tptr, 6);
    178         lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6);
    179     } else {
    180         lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
    181     }
    182     ND_TCHECK(*lwapp_trans_header);
    183 
    184     /*
    185      * Sanity checking of the header.
    186      */
    187     if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) {
    188 	ND_PRINT((ndo, "LWAPP version %u packet not supported",
    189                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version)));
    190 	return;
    191     }
    192 
    193     /* non-verbose */
    194     if (ndo->ndo_vflag < 1) {
    195         ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u",
    196                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
    197                LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
    198                bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
    199                len));
    200         return;
    201     }
    202 
    203     /* ok they seem to want to know everything - lets fully decode it */
    204     tlen=EXTRACT_16BITS(lwapp_trans_header->length);
    205 
    206     ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
    207            LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
    208            LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
    209            LWAPP_EXTRACT_RID(lwapp_trans_header->version),
    210            bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
    211 	   lwapp_trans_header->frag_id,
    212 	   tlen));
    213 
    214     if (has_ap_ident) {
    215         ND_PRINT((ndo, "\n\tAP identity: %s", etheraddr_string(ndo, tptr)));
    216         tptr+=sizeof(const struct lwapp_transport_header)+6;
    217     } else {
    218         tptr+=sizeof(const struct lwapp_transport_header);
    219     }
    220 
    221     while(tlen>0) {
    222 
    223         /* did we capture enough for fully decoding the object header ? */
    224         ND_TCHECK2(*tptr, sizeof(struct lwapp_control_header));
    225 
    226         lwapp_control_header = (const struct lwapp_control_header *)tptr;
    227 	msg_tlen = EXTRACT_16BITS(lwapp_control_header->len);
    228 
    229 	/* print message header */
    230         ND_PRINT((ndo, "\n\t  Msg type: %s (%u), Seqnum: %u, Msg len: %d, Session: 0x%08x",
    231                tok2str(lwapp_msg_type_values,"Unknown",lwapp_control_header->msg_type),
    232                lwapp_control_header->msg_type,
    233                lwapp_control_header->seq_num,
    234                msg_tlen,
    235                EXTRACT_32BITS(lwapp_control_header->session_id)));
    236 
    237         /* did we capture enough for fully decoding the message */
    238         ND_TCHECK2(*tptr, msg_tlen);
    239 
    240 	/* XXX - Decode sub messages for each message */
    241         switch(lwapp_control_header->msg_type) {
    242         case LWAPP_MSGTYPE_DISCOVERY_REQUEST:
    243         case LWAPP_MSGTYPE_DISCOVERY_RESPONSE:
    244         case LWAPP_MSGTYPE_JOIN_REQUEST:
    245         case LWAPP_MSGTYPE_JOIN_RESPONSE:
    246         case LWAPP_MSGTYPE_JOIN_ACK:
    247         case LWAPP_MSGTYPE_JOIN_CONFIRM:
    248         case LWAPP_MSGTYPE_CONFIGURE_REQUEST:
    249         case LWAPP_MSGTYPE_CONFIGURE_RESPONSE:
    250         case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST:
    251         case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE:
    252         case LWAPP_MSGTYPE_WTP_EVENT_REQUEST:
    253         case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE:
    254         case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST:
    255         case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE:
    256         case LWAPP_MSGTYPE_ECHO_REQUEST:
    257         case LWAPP_MSGTYPE_ECHO_RESPONSE:
    258         case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST:
    259         case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE:
    260         case LWAPP_MSGTYPE_RESET_REQUEST:
    261         case LWAPP_MSGTYPE_RESET_RESPONSE:
    262         case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST:
    263         case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE:
    264         case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST:
    265         case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE:
    266         case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST:
    267         case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE:
    268         case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION:
    269         case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST:
    270         case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE:
    271         case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST:
    272         case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE:
    273         default:
    274             break;
    275         }
    276 
    277         tptr += sizeof(struct lwapp_control_header) + msg_tlen;
    278         tlen -= sizeof(struct lwapp_control_header) + msg_tlen;
    279     }
    280     return;
    281 
    282  trunc:
    283     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
    284 }
    285 
    286 void
    287 lwapp_data_print(netdissect_options *ndo,
    288                  const u_char *pptr, u_int len)
    289 {
    290     const struct lwapp_transport_header *lwapp_trans_header;
    291     const u_char *tptr;
    292     int tlen;
    293 
    294     tptr=pptr;
    295 
    296     /* check if enough bytes for AP identity */
    297     ND_TCHECK2(*tptr, 6);
    298     lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
    299     ND_TCHECK(*lwapp_trans_header);
    300 
    301     /*
    302      * Sanity checking of the header.
    303      */
    304     if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) {
    305         ND_PRINT((ndo, "LWAPP version %u packet not supported",
    306                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version)));
    307         return;
    308     }
    309 
    310     /* non-verbose */
    311     if (ndo->ndo_vflag < 1) {
    312         ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u",
    313                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
    314                LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
    315                bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
    316                len));
    317         return;
    318     }
    319 
    320     /* ok they seem to want to know everything - lets fully decode it */
    321     tlen=EXTRACT_16BITS(lwapp_trans_header->length);
    322 
    323     ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id  %u, Flags [%s], Frag-id  %u, length %u",
    324            LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
    325            LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
    326            LWAPP_EXTRACT_RID(lwapp_trans_header->version),
    327            bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
    328            lwapp_trans_header->frag_id,
    329            tlen));
    330 
    331     tptr+=sizeof(const struct lwapp_transport_header);
    332     tlen-=sizeof(const struct lwapp_transport_header);
    333 
    334     /* FIX - An IEEE 802.11 frame follows - hexdump for now */
    335     print_unknown_data(ndo, tptr, "\n\t", tlen);
    336 
    337     return;
    338 
    339  trunc:
    340     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
    341 }
    342 
    343 /*
    344  * Local Variables:
    345  * c-style: whitesmith
    346  * c-basic-offset: 8
    347  * End:
    348  */
    349