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