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