[wtp] implement vendor specific elements

This commit is contained in:
Andreas Schultz 2016-03-08 12:00:01 +01:00
parent 471d1058c4
commit 730f110a25
11 changed files with 157 additions and 123 deletions

View File

@ -101,7 +101,8 @@ capwap_SOURCES = $(top_srcdir)/src/common/capwap.c \
$(top_srcdir)/src/common/capwap_element_80211_wtpradioconf.c \
$(top_srcdir)/src/common/capwap_element_80211_wtpradiofailalarm.c \
$(top_srcdir)/src/common/capwap_element_80211_wtpradioinformation.c \
$(top_srcdir)/src/common/capwap_element_80211n_radioconf.c
$(top_srcdir)/src/common/capwap_element_80211n_radioconf.c \
$(top_srcdir)/src/common/capwap_element_80211n_station_information.c
if DEBUG_BUILD
capwap_SOURCES += $(top_srcdir)/src/common/capwap_debug.c

View File

@ -88,20 +88,41 @@ static const struct capwap_message_elements_ops * capwap_80211_message_elements[
};
#undef element_ops
/* */
#define element_ops(Id, Ops) [(Id) - 1] = &(Ops)
static const struct capwap_message_elements_ops * capwap_vendor_travelping_message_elements[] = {
element_ops(CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE, capwap_element_80211n_radioconf_ops),
element_ops(CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE, capwap_element_80211n_station_info_ops)
};
#undef element_ops
/* */
const struct capwap_message_elements_ops *
capwap_get_message_element_ops(const struct capwap_message_element_id id)
{
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
switch (id.vendor) {
case 0:
if (IS_MESSAGE_ELEMENTS(id)) {
if (id.type >= CAPWAP_MESSAGE_ELEMENTS_START &&
id.type - CAPWAP_MESSAGE_ELEMENTS_START < ARRAY_SIZE(capwap_message_elements)) {
return capwap_message_elements[id.type - CAPWAP_MESSAGE_ELEMENTS_START];
} else if (IS_80211_MESSAGE_ELEMENTS(id)) {
}
else if (id.type >= CAPWAP_80211_MESSAGE_ELEMENTS_START &&
id.type - CAPWAP_80211_MESSAGE_ELEMENTS_START < ARRAY_SIZE(capwap_80211_message_elements)) {
return capwap_80211_message_elements[id.type - CAPWAP_80211_MESSAGE_ELEMENTS_START];
}
break;
case CAPWAP_VENDOR_TRAVELPING_ID:
if (id.type >= 1 &&
id.type - 1 < ARRAY_SIZE(capwap_vendor_travelping_message_elements))
return capwap_vendor_travelping_message_elements[id.type - 1];
break;
}
return NULL;
#undef ARRAY_SIZE
}
/* */
@ -169,7 +190,7 @@ int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap
/* */
bodylength = rxmngpacket->ctrlmsg.length - CAPWAP_CONTROL_MESSAGE_MIN_LENGTH;
while (bodylength > 0) {
struct capwap_message_element_id id;
struct capwap_message_element_id id = { .vendor = 0 };
uint16_t msglength;
struct capwap_list_item* itemlist;
struct capwap_message_element_itemlist* messageelement;
@ -178,45 +199,60 @@ int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap
/* Get type and length */
rxmngpacket->readerpacketallowed = sizeof(struct capwap_message_element);
if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &id.type) != sizeof(uint16_t)) {
if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &id.type) != sizeof(uint16_t) ||
rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength) != sizeof(uint16_t) ||
msglength > bodylength)
return INVALID_MESSAGE_ELEMENT;
}
/* TODO: implement actual vendor handling */
id.vendor = 0;
/* Check type */
capwap_logging_debug("MESSAGE ELEMENT: %06x:%d", id.vendor, id.type);
if (!IS_VALID_MESSAGE_ELEMENTS(id)) {
return UNRECOGNIZED_MESSAGE_ELEMENT;
}
/* Check binding */
if (IS_80211_MESSAGE_ELEMENTS(id) && (binding != CAPWAP_WIRELESS_BINDING_IEEE80211)) {
return UNRECOGNIZED_MESSAGE_ELEMENT;
}
if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength) != sizeof(uint16_t)) {
return INVALID_MESSAGE_ELEMENT;
}
/* Check length */
if (msglength > bodylength) {
return INVALID_MESSAGE_ELEMENT;
}
/* Reader function */
read_ops = capwap_get_message_element_ops(id);
capwap_logging_debug("read_ops: %p", read_ops);
if (!read_ops) {
return INVALID_MESSAGE_ELEMENT;
}
/* Allowed to parsing only the size of message element */
rxmngpacket->readerpacketallowed = msglength;
/* Get message element */
element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
/* Check binding */
if (IS_80211_MESSAGE_ELEMENTS(id) &&
(binding != CAPWAP_WIRELESS_BINDING_IEEE80211))
return UNRECOGNIZED_MESSAGE_ELEMENT;
capwap_logging_debug("MESSAGE ELEMENT: %d", id.type);
if (id.type == CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE) {
struct capwap_message_element_id vendor_id;
if (msglength < 7) {
capwap_logging_debug("Invalid Vendor Specific Payload element: underbuffer");
return INVALID_MESSAGE_ELEMENT;
}
if ((msglength - 6) > CAPWAP_VENDORPAYLOAD_MAXLENGTH) {
capwap_logging_debug("Invalid Vendor Specific Payload element: overbuffer");
return INVALID_MESSAGE_ELEMENT;
}
rxmngpacket->read_ops.read_u32((capwap_message_elements_handle)rxmngpacket, &vendor_id.vendor);
rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &vendor_id.type);
capwap_logging_debug("VENDOR MESSAGE ELEMENT: %06x:%d", id.vendor, id.type);
read_ops = capwap_get_message_element_ops(vendor_id);
capwap_logging_debug("vendor read_ops: %p", read_ops);
if (read_ops) {
id = vendor_id;
element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
} else {
read_ops = capwap_get_message_element_ops(id);
element = capwap_unknown_vendorpayload_element_parsing((capwap_message_elements_handle)rxmngpacket,
&rxmngpacket->read_ops, msglength - 6, vendor_id);
}
} else {
/* Reader function */
read_ops = capwap_get_message_element_ops(id);
capwap_logging_debug("read_ops: %p", read_ops);
if (!read_ops)
return UNRECOGNIZED_MESSAGE_ELEMENT;
/* Get message element */
element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops);
}
if (!element)
return INVALID_MESSAGE_ELEMENT;

View File

@ -45,6 +45,7 @@ struct capwap_message_elements_ops
const struct capwap_message_elements_ops *capwap_get_message_element_ops(const struct capwap_message_element_id id);
/*********************************************************************************************************************/
/* Standard message elements */
#include "capwap_element_acdescriptor.h" /* 00001 */
#include "capwap_element_acipv4list.h" /* 00002 */
@ -127,9 +128,7 @@ const struct capwap_message_elements_ops *capwap_get_message_element_ops(const s
#include "capwap_element_80211_wtpradiofailalarm.h" /* 01047 */
#include "capwap_element_80211_wtpradioinformation.h" /* 01048 */
/* draft-ietf-opsawg-capwap-extension-06 */
#include "capwap_element_80211n_radioconf.h"
#include "capwap_element_80211n_station_information.h"
#include "capwap_vendor_travelping.h"
/*********************************************************************************************************************/
#define CAPWAP_MESSAGE_ELEMENT_SINGLE 0

View File

@ -40,7 +40,7 @@ capwap_80211n_radioconf_element_parsing(capwap_message_elements_handle handle,
{
struct capwap_80211n_radioconf_element *data;
uint16_t reserved;
ASSERT(handle != NULL);
ASSERT(func != NULL);
@ -79,7 +79,7 @@ static void
capwap_80211n_radioconf_element_free(void* data)
{
ASSERT(data != NULL);
capwap_free(data);
}

View File

@ -1,9 +1,9 @@
#ifndef __CAPWAP_ELEMENT_80211N_RADIO_CONF_HEADER__
#define __CAPWAP_ELEMENT_80211N_RADIO_CONF_HEADER__
#define CAPWAP_ELEMENT_80211N_RADIO_CONF_VENDOR 0
#define CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE 1046
#define CAPWAP_ELEMENT_80211N_RADIO_CONF (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211N_RADIO_CONF_VENDOR, .type = CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE }
#define CAPWAP_ELEMENT_80211N_RADIO_CONF_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
#define CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE 8
#define CAPWAP_ELEMENT_80211N_RADIO_CONF (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211N_RADIO_CONF_VENDOR, .type = CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE }
#define CAPWAP_80211N_RADIO_CONF_A_MSDU (1 << 7)

View File

@ -32,14 +32,14 @@ capwap_80211n_station_info_element_create(void *data,
ASSERT(data != NULL);
func->write_block(handle, &element->address, MACADDRESS_EUI48_LENGTH);
func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH);
func->write_u8(handle, element->flags);
func->write_u8(handle, element->maxrxfactor);
func->write_u8(handle, element->minstaspaceing);
func->write_u16(handle, element->hisuppdatarate);
func->write_u16(handle, element->ampdubufsize);
func->write_u8(handle, element->htcsupp);
func->write_block(handle, &element->mcsset, MCS_SET_LENGTH);
func->write_block(handle, element->mcsset, MCS_SET_LENGTH);
}
/* */
@ -48,8 +48,7 @@ capwap_80211n_station_info_element_parsing(capwap_message_elements_handle handle
struct capwap_read_message_elements_ops *func)
{
struct capwap_80211n_station_info_element *data;
uint16_t reserved;
ASSERT(handle != NULL);
ASSERT(func != NULL);
@ -63,14 +62,14 @@ capwap_80211n_station_info_element_parsing(capwap_message_elements_handle handle
memset(data, 0, sizeof(struct capwap_80211n_station_info_element));
/* Retrieve data */
func->read_block(handle, &data->address, MACADDRESS_EUI48_LENGTH);
func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH);
func->read_u8(handle, &data->flags);
func->read_u8(handle, &data->maxrxfactor);
func->read_u8(handle, &data->minstaspaceing);
func->read_u16(handle, &data->hisuppdatarate);
func->read_u16(handle, &data->ampdubufsize);
func->read_u8(handle, &data->htcsupp);
func->read_block(handle, &data->mcsset, MCS_SET_LENGTH);
func->read_block(handle, data->mcsset, MCS_SET_LENGTH);
return data;
}
@ -89,7 +88,7 @@ static void
capwap_80211n_station_info_element_free(void* data)
{
ASSERT(data != NULL);
capwap_free(data);
}

View File

@ -1,9 +1,9 @@
#ifndef __CAPWAP_ELEMENT_80211N_STATION_INFO_HEADER__
#define __CAPWAP_ELEMENT_80211N_STATION_INFO_HEADER__
#define CAPWAP_ELEMENT_80211N_STATION_INFO_VENDOR 0
#define CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE 1046
#define CAPWAP_ELEMENT_80211N_STATION_INFO (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211N_STATION_INFO_VENDOR, .type = CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE }
#define CAPWAP_ELEMENT_80211N_STATION_INFO_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
#define CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE 9
#define CAPWAP_ELEMENT_80211N_STATION_INFO (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_80211N_STATION_INFO_VENDOR, .type = CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE }
#define CAPWAP_80211N_STATION_INFO_40MHZ_BANDWITH (1 << 7)

View File

@ -1,25 +1,28 @@
#include "capwap.h"
#include "capwap_element.h"
/********************************************************************
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Vendor Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Element ID | Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 37 for Vendor Specific Payload
Length: >= 7
********************************************************************/
/*
*
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Vendor Identifier |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Element ID | Data...
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Type: 37 for Vendor Specific Payload
*
* Length: >= 7
*
*/
/* */
static void capwap_vendorpayload_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
struct capwap_vendorpayload_element* element = (struct capwap_vendorpayload_element*)data;
static void capwap_vendorpayload_element_create(void* data,
capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops* func)
{
struct capwap_vendorpayload_element* element = (struct capwap_vendorpayload_element *)data;
ASSERT(data != NULL);
ASSERT(element->datalength > 0);
@ -30,45 +33,38 @@ static void capwap_vendorpayload_element_create(void* data, capwap_message_eleme
}
/* */
static void* capwap_vendorpayload_element_clone(void* data) {
struct capwap_vendorpayload_element* cloneelement;
static void* capwap_vendorpayload_element_clone(void *data)
{
struct capwap_vendorpayload_element* element = (struct capwap_vendorpayload_element *)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_vendorpayload_element));
if (cloneelement->datalength > 0) {
cloneelement->data = capwap_clone(((struct capwap_vendorpayload_element*)data)->data, cloneelement->datalength);
}
return cloneelement;
return capwap_clone(data, sizeof(struct capwap_vendorpayload_element) + element->datalength);
}
/* */
static void capwap_vendorpayload_element_free(void* data) {
struct capwap_vendorpayload_element* element = (struct capwap_vendorpayload_element*)data;
static void capwap_vendorpayload_element_free(void *data)
{
ASSERT(data != NULL);
if (element->data) {
capwap_free(element->data);
}
capwap_free(data);
}
/* */
static void *
void *
capwap_unknown_vendorpayload_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func,
unsigned short length,
uint32_t vendorid, uint16_t elementid)
const struct capwap_message_element_id vendor_id)
{
struct capwap_vendorpayload_element* data;
/* Retrieve data */
data = (struct capwap_vendorpayload_element*)capwap_alloc(sizeof(struct capwap_vendorpayload_element));
data->data = (uint8_t*)capwap_alloc(length);
data->vendorid = vendorid;
data->elementid = elementid;
data = (struct capwap_vendorpayload_element *)capwap_alloc(sizeof(struct capwap_vendorpayload_element)
+ length);
data->vendorid = vendor_id.vendor;
data->elementid = vendor_id.type;
data->datalength = length;
func->read_block(handle, data->data, length);
@ -81,9 +77,7 @@ capwap_vendorpayload_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
unsigned short length;
uint32_t vendorid;
uint16_t elementid;
struct capwap_vendorpayload_element* data;
struct capwap_message_element_id vendor_id;
ASSERT(handle != NULL);
ASSERT(func != NULL);
@ -100,27 +94,11 @@ capwap_vendorpayload_element_parsing(capwap_message_elements_handle handle,
return NULL;
}
func->read_u32(handle, &vendorid);
func->read_u16(handle, &elementid);
/* Retrieve data */
func->read_u32(handle, &vendor_id.vendor);
func->read_u16(handle, &vendor_id.type);
switch (vendorid) {
case VENDOR_TRAVELPING:
switch (elementid) {
case VENDOR_TRAVELPING_ELEMENT_80211N_RADIO_CONF:
case VENDOR_TRAVELPING_ELEMENT_80211N_STATION_INFO:
default:
data = capwap_unknown_vendorpayload_element_parsing(handle, func, length,
vendorid, elementid);
break;
}
break;
default:
data = capwap_unknown_vendorpayload_element_parsing(handle, func, length,
vendorid, elementid);
break;
}
return data;
return capwap_unknown_vendorpayload_element_parsing(handle, func, length, vendor_id);
}
/* */

View File

@ -1,10 +1,6 @@
#ifndef __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__
#define __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__
#define VENDOR_TRAVELPING 18681
#define VENDOR_TRAVELPING_ELEMENT_80211N_RADIO_CONF 123
#define VENDOR_TRAVELPING_ELEMENT_80211N_STATION_INFO 124
#define CAPWAP_ELEMENT_VENDORPAYLOAD_VENDOR 0
#define CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE 37
#define CAPWAP_ELEMENT_VENDORPAYLOAD (struct capwap_message_element_id){ .vendor = CAPWAP_ELEMENT_VENDORPAYLOAD_VENDOR, .type = CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE }
@ -16,9 +12,15 @@ struct capwap_vendorpayload_element {
uint32_t vendorid;
uint16_t elementid;
uint16_t datalength;
uint8_t* data;
uint8_t data[];
};
void *
capwap_unknown_vendorpayload_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func,
unsigned short length,
const struct capwap_message_element_id vendor_id);
extern const struct capwap_message_elements_ops capwap_element_vendorpayload_ops;
#endif /* __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__ */

View File

@ -513,7 +513,10 @@ void capwap_packet_txmng_add_message_element(struct capwap_packet_txmng *txmngpa
Type and Length is add to this function, only custom create write Value message element
*/
txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, id.type);
if (id.vendor != 0)
txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE);
else
txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, id.type);
/* Length of message element is calculate after create function */
writepos.item = txmngpacket->fragmentlist->last;
@ -521,6 +524,12 @@ void capwap_packet_txmng_add_message_element(struct capwap_packet_txmng *txmngpa
txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, 0);
txmngpacket->writerpacketsize = 0;
if (id.vendor != 0) {
/* Write vendor header */
txmngpacket->write_ops.write_u32((capwap_message_elements_handle)txmngpacket, id.vendor);
txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, id.type);
}
/* Build message element */
func->create(data, (capwap_message_elements_handle)txmngpacket, &txmngpacket->write_ops);

View File

@ -0,0 +1,10 @@
#ifndef __CAPWAP_VENDOR_TRAVELPING_HEADER__
#define __CAPWAP_VENDOR_TRAVELPING_HEADER__
#define CAPWAP_VENDOR_TRAVELPING_ID 18681
/* draft-ietf-opsawg-capwap-extension-06 */
#include "capwap_element_80211n_radioconf.h"
#include "capwap_element_80211n_station_information.h"
#endif /* __CAPWAP_VENDOR_TRAVELPING_HEADER__ */