| /* |
| * Copyright (c) 1998-2007 The TCPDUMP project |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that: (1) source code |
| * distributions retain the above copyright notice and this paragraph |
| * in its entirety, and (2) distributions including binary code include |
| * the above copyright notice and this paragraph in its entirety in |
| * the documentation or other materials provided with the distribution. |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND |
| * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT |
| * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE. |
| * |
| * Support for the Light Weight Access Point Protocol as per draft-ohara-capwap-lwapp-04 |
| * |
| * Original code by Carles Kishimoto <carles.kishimoto@gmail.com> |
| */ |
| |
| #ifndef lint |
| static const char rcsid[] _U_ = |
| "@(#) $Header: /tcpdump/master/tcpdump/print-lwapp.c,v 1.1 2007-07-24 16:07:30 hannes Exp $"; |
| #endif |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include <tcpdump-stdinc.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "interface.h" |
| #include "extract.h" |
| #include "addrtoname.h" |
| |
| /* |
| * LWAPP transport (common) header |
| * 0 1 2 3 |
| * 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 |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * |VER| RID |C|F|L| Frag ID | Length | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | Status/WLANs | Payload... | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * |
| */ |
| |
| struct lwapp_transport_header { |
| u_int8_t version; |
| u_int8_t frag_id; |
| u_int8_t length[2]; |
| u_int16_t status; |
| }; |
| |
| /* |
| * LWAPP control header |
| * 0 1 2 3 |
| * 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 |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | Message Type | Seq Num | Msg Element Length | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | Session ID | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | Msg Element [0..N] | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| */ |
| |
| struct lwapp_control_header { |
| u_int8_t msg_type; |
| u_int8_t seq_num; |
| u_int8_t len[2]; |
| u_int8_t session_id[4]; |
| }; |
| |
| #define LWAPP_VERSION 0 |
| #define LWAPP_EXTRACT_VERSION(x) (((x)&0xC0)>>6) |
| #define LWAPP_EXTRACT_RID(x) (((x)&0x38)>>3) |
| #define LWAPP_EXTRACT_CONTROL_BIT(x) (((x)&0x04)>>2) |
| |
| static const struct tok lwapp_header_bits_values[] = { |
| { 0x01, "Last Fragment Bit"}, |
| { 0x02, "Fragment Bit"}, |
| { 0x04, "Control Bit"}, |
| { 0, NULL} |
| }; |
| |
| #define LWAPP_MSGTYPE_DISCOVERY_REQUEST 1 |
| #define LWAPP_MSGTYPE_DISCOVERY_RESPONSE 2 |
| #define LWAPP_MSGTYPE_JOIN_REQUEST 3 |
| #define LWAPP_MSGTYPE_JOIN_RESPONSE 4 |
| #define LWAPP_MSGTYPE_JOIN_ACK 5 |
| #define LWAPP_MSGTYPE_JOIN_CONFIRM 6 |
| #define LWAPP_MSGTYPE_CONFIGURE_REQUEST 10 |
| #define LWAPP_MSGTYPE_CONFIGURE_RESPONSE 11 |
| #define LWAPP_MSGTYPE_CONF_UPDATE_REQUEST 12 |
| #define LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE 13 |
| #define LWAPP_MSGTYPE_WTP_EVENT_REQUEST 14 |
| #define LWAPP_MSGTYPE_WTP_EVENT_RESPONSE 15 |
| #define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST 16 |
| #define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE 17 |
| #define LWAPP_MSGTYPE_ECHO_REQUEST 22 |
| #define LWAPP_MSGTYPE_ECHO_RESPONSE 23 |
| #define LWAPP_MSGTYPE_IMAGE_DATA_REQUEST 24 |
| #define LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE 25 |
| #define LWAPP_MSGTYPE_RESET_REQUEST 26 |
| #define LWAPP_MSGTYPE_RESET_RESPONSE 27 |
| #define LWAPP_MSGTYPE_KEY_UPDATE_REQUEST 30 |
| #define LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE 31 |
| #define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST 32 |
| #define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE 33 |
| #define LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST 34 |
| #define LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE 35 |
| #define LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION 36 |
| #define LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST 37 |
| #define LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE 38 |
| #define LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST 39 |
| #define LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE 40 |
| |
| static const struct tok lwapp_msg_type_values[] = { |
| { LWAPP_MSGTYPE_DISCOVERY_REQUEST, "Discovery req"}, |
| { LWAPP_MSGTYPE_DISCOVERY_RESPONSE, "Discovery resp"}, |
| { LWAPP_MSGTYPE_JOIN_REQUEST, "Join req"}, |
| { LWAPP_MSGTYPE_JOIN_RESPONSE, "Join resp"}, |
| { LWAPP_MSGTYPE_JOIN_ACK, "Join ack"}, |
| { LWAPP_MSGTYPE_JOIN_CONFIRM, "Join confirm"}, |
| { LWAPP_MSGTYPE_CONFIGURE_REQUEST, "Configure req"}, |
| { LWAPP_MSGTYPE_CONFIGURE_RESPONSE, "Configure resp"}, |
| { LWAPP_MSGTYPE_CONF_UPDATE_REQUEST, "Update req"}, |
| { LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE, "Update resp"}, |
| { LWAPP_MSGTYPE_WTP_EVENT_REQUEST, "WTP event req"}, |
| { LWAPP_MSGTYPE_WTP_EVENT_RESPONSE, "WTP event resp"}, |
| { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST, "Change state event req"}, |
| { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE, "Change state event resp"}, |
| { LWAPP_MSGTYPE_ECHO_REQUEST, "Echo req"}, |
| { LWAPP_MSGTYPE_ECHO_RESPONSE, "Echo resp"}, |
| { LWAPP_MSGTYPE_IMAGE_DATA_REQUEST, "Image data req"}, |
| { LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE, "Image data resp"}, |
| { LWAPP_MSGTYPE_RESET_REQUEST, "Channel status req"}, |
| { LWAPP_MSGTYPE_RESET_RESPONSE, "Channel status resp"}, |
| { LWAPP_MSGTYPE_KEY_UPDATE_REQUEST, "Key update req"}, |
| { LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE, "Key update resp"}, |
| { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST, "Primary discovery req"}, |
| { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE, "Primary discovery resp"}, |
| { LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST, "Data transfer req"}, |
| { LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE, "Data transfer resp"}, |
| { LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION, "Clear config ind"}, |
| { LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST, "Wlan config req"}, |
| { LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE, "Wlan config resp"}, |
| { LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST, "Mobile config req"}, |
| { LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE, "Mobile config resp"}, |
| { 0, NULL} |
| }; |
| |
| /* |
| * LWAPP message elements |
| * |
| * 0 1 2 3 |
| * 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 |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| * | Type | Length | Value ... | |
| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| */ |
| struct lwapp_message_header { |
| u_int8_t type; |
| u_int8_t length[2]; |
| }; |
| |
| void |
| lwapp_control_print(const u_char *pptr, u_int len, int has_ap_ident) { |
| |
| const struct lwapp_transport_header *lwapp_trans_header; |
| const struct lwapp_control_header *lwapp_control_header; |
| const u_char *tptr; |
| int tlen; |
| int msg_tlen; |
| |
| tptr=pptr; |
| |
| if (has_ap_ident) { |
| /* check if enough bytes for AP identity */ |
| if (!TTEST2(*tptr, 6)) |
| goto trunc; |
| lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6); |
| } else { |
| lwapp_trans_header = (const struct lwapp_transport_header *)pptr; |
| } |
| TCHECK(*lwapp_trans_header); |
| |
| /* |
| * Sanity checking of the header. |
| */ |
| if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) { |
| printf("LWAPP version %u packet not supported", |
| LWAPP_EXTRACT_VERSION(lwapp_trans_header->version)); |
| return; |
| } |
| |
| /* non-verbose */ |
| if (vflag < 1) { |
| printf("LWAPPv%u, %s frame, Flags [%s], length %u", |
| LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), |
| LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", |
| bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), |
| len); |
| return; |
| } |
| |
| /* ok they seem to want to know everything - lets fully decode it */ |
| tlen=EXTRACT_16BITS(lwapp_trans_header->length); |
| |
| printf("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u", |
| LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), |
| LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", |
| LWAPP_EXTRACT_RID(lwapp_trans_header->version), |
| bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), |
| lwapp_trans_header->frag_id, |
| tlen); |
| |
| if (has_ap_ident) { |
| printf("\n\tAP identity: %s", |
| etheraddr_string(tptr)); |
| tptr+=sizeof(const struct lwapp_transport_header)+6; |
| } else { |
| tptr+=sizeof(const struct lwapp_transport_header); |
| } |
| |
| while(tlen>0) { |
| |
| /* did we capture enough for fully decoding the object header ? */ |
| if (!TTEST2(*tptr, sizeof(struct lwapp_control_header))) |
| goto trunc; |
| |
| lwapp_control_header = (const struct lwapp_control_header *)tptr; |
| msg_tlen = EXTRACT_16BITS(lwapp_control_header->len); |
| |
| /* print message header */ |
| printf("\n\t Msg type: %s (%u), Seqnum: %u, Msg len: %d, Session: 0x%08x", |
| tok2str(lwapp_msg_type_values,"Unknown",lwapp_control_header->msg_type), |
| lwapp_control_header->msg_type, |
| lwapp_control_header->seq_num, |
| msg_tlen, |
| EXTRACT_32BITS(lwapp_control_header->session_id)); |
| |
| /* did we capture enough for fully decoding the message */ |
| if (!TTEST2(*tptr, msg_tlen)) |
| goto trunc; |
| |
| /* XXX - Decode sub messages for each message */ |
| switch(lwapp_control_header->msg_type) { |
| case LWAPP_MSGTYPE_DISCOVERY_REQUEST: |
| case LWAPP_MSGTYPE_DISCOVERY_RESPONSE: |
| case LWAPP_MSGTYPE_JOIN_REQUEST: |
| case LWAPP_MSGTYPE_JOIN_RESPONSE: |
| case LWAPP_MSGTYPE_JOIN_ACK: |
| case LWAPP_MSGTYPE_JOIN_CONFIRM: |
| case LWAPP_MSGTYPE_CONFIGURE_REQUEST: |
| case LWAPP_MSGTYPE_CONFIGURE_RESPONSE: |
| case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST: |
| case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE: |
| case LWAPP_MSGTYPE_WTP_EVENT_REQUEST: |
| case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE: |
| case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST: |
| case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE: |
| case LWAPP_MSGTYPE_ECHO_REQUEST: |
| case LWAPP_MSGTYPE_ECHO_RESPONSE: |
| case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST: |
| case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE: |
| case LWAPP_MSGTYPE_RESET_REQUEST: |
| case LWAPP_MSGTYPE_RESET_RESPONSE: |
| case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST: |
| case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE: |
| case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST: |
| case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE: |
| case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST: |
| case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE: |
| case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION: |
| case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST: |
| case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE: |
| case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST: |
| case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE: |
| default: |
| break; |
| } |
| |
| tptr += sizeof(struct lwapp_control_header) + msg_tlen; |
| tlen -= sizeof(struct lwapp_control_header) + msg_tlen; |
| } |
| return; |
| |
| trunc: |
| printf("\n\t\t packet exceeded snapshot"); |
| } |
| |
| void |
| lwapp_data_print(const u_char *pptr, u_int len) { |
| |
| const struct lwapp_transport_header *lwapp_trans_header; |
| const u_char *tptr; |
| int tlen; |
| |
| tptr=pptr; |
| |
| /* check if enough bytes for AP identity */ |
| if (!TTEST2(*tptr, 6)) |
| goto trunc; |
| lwapp_trans_header = (const struct lwapp_transport_header *)pptr; |
| TCHECK(*lwapp_trans_header); |
| |
| /* |
| * Sanity checking of the header. |
| */ |
| if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) { |
| printf("LWAPP version %u packet not supported", |
| LWAPP_EXTRACT_VERSION(lwapp_trans_header->version)); |
| return; |
| } |
| |
| /* non-verbose */ |
| if (vflag < 1) { |
| printf("LWAPPv%u, %s frame, Flags [%s], length %u", |
| LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), |
| LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", |
| bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), |
| len); |
| return; |
| } |
| |
| /* ok they seem to want to know everything - lets fully decode it */ |
| tlen=EXTRACT_16BITS(lwapp_trans_header->length); |
| |
| printf("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u", |
| LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), |
| LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", |
| LWAPP_EXTRACT_RID(lwapp_trans_header->version), |
| bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), |
| lwapp_trans_header->frag_id, |
| tlen); |
| |
| tptr+=sizeof(const struct lwapp_transport_header); |
| tlen-=sizeof(const struct lwapp_transport_header); |
| |
| /* FIX - An IEEE 802.11 frame follows - hexdump for now */ |
| print_unknown_data(tptr, "\n\t", tlen); |
| |
| return; |
| |
| trunc: |
| printf("\n\t\t packet exceeded snapshot"); |
| } |
| |
| /* |
| * Local Variables: |
| * c-style: whitesmith |
| * c-basic-offset: 8 |
| * End: |
| */ |