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