freewtp/lib/element_wtpdescriptor.c

263 lines
8.7 KiB
C

#include "capwap.h"
#include "array.h"
#include "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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Max Radios | Radios in use | Num Encrypt |Encryp Sub-Elmt|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Encryption Sub-Element | Descriptor Sub-Element...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Resvd| WBID | Encryption Capabilities |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Descriptor Vendor Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Descriptor Type | Descriptor Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Descriptor Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 39 for WTP Descriptor
Length: >= 33
********************************************************************/
/* */
static void capwap_wtpdescriptor_element_create(void *data, capwap_message_elements_handle handle,
struct capwap_write_message_elements_ops *func)
{
int i;
struct capwap_wtpdescriptor_element *element = (struct capwap_wtpdescriptor_element *)data;
ASSERT(data != NULL);
ASSERT(element->maxradios >= element->radiosinuse);
ASSERT(element->encryptsubelement->count > 0);
ASSERT(element->descsubelement->count > 0);
/* */
func->write_u8(handle, element->maxradios);
func->write_u8(handle, element->radiosinuse);
func->write_u8(handle, element->encryptsubelement->count);
/* */
for (i = 0; i < element->encryptsubelement->count; i++) {
struct capwap_wtpdescriptor_encrypt_subelement *desc =
(struct capwap_wtpdescriptor_encrypt_subelement *)
capwap_array_get_item_pointer(element->encryptsubelement, i);
ASSERT((desc->wbid & CAPWAP_WTPDESC_SUBELEMENT_WBID_MASK) == desc->wbid);
func->write_u8(handle, desc->wbid);
func->write_u16(handle, desc->capabilities);
}
/* */
for (i = 0; i < element->descsubelement->count; i++) {
uint16_t length;
struct capwap_wtpdescriptor_desc_subelement *desc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(element->descsubelement, i);
ASSERT((desc->type >= CAPWAP_WTPDESC_SUBELEMENT_TYPE_FIRST) &&
(desc->type <= CAPWAP_WTPDESC_SUBELEMENT_TYPE_LAST));
length = strlen((char*)desc->data);
ASSERT(length > 0);
func->write_u32(handle, desc->vendor);
func->write_u16(handle, desc->type);
func->write_u16(handle, length);
func->write_block(handle, desc->data, length);
}
}
/* */
static void *capwap_wtpdescriptor_element_clone(void *data)
{
int i;
struct capwap_wtpdescriptor_element *cloneelement;
struct capwap_wtpdescriptor_element *element = (struct capwap_wtpdescriptor_element*)data;
ASSERT(data != NULL);
cloneelement = capwap_clone(data, sizeof(struct capwap_wtpdescriptor_element));
cloneelement->encryptsubelement =
capwap_array_create(sizeof(struct capwap_wtpdescriptor_encrypt_subelement), 0, 0);
for (i = 0; i < element->encryptsubelement->count; i++)
memcpy(capwap_array_get_item_pointer(cloneelement->encryptsubelement, i),
capwap_array_get_item_pointer(element->encryptsubelement, i),
sizeof(struct capwap_wtpdescriptor_encrypt_subelement));
cloneelement->descsubelement =
capwap_array_create(sizeof(struct capwap_wtpdescriptor_desc_subelement), 0, 1);
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_wtpdescriptor_desc_subelement *desc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(element->descsubelement, i);
struct capwap_wtpdescriptor_desc_subelement *clonedesc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(cloneelement->descsubelement, i);
memcpy(clonedesc, desc, sizeof(struct capwap_wtpdescriptor_desc_subelement));
if (desc->data)
clonedesc->data = (uint8_t*)capwap_duplicate_string((char *)desc->data);
}
return cloneelement;
}
/* */
static void capwap_wtpdescriptor_element_free(void *data)
{
int i;
struct capwap_wtpdescriptor_element *element = (struct capwap_wtpdescriptor_element *)data;
ASSERT(data != NULL);
ASSERT(element->encryptsubelement != NULL);
ASSERT(element->descsubelement != NULL);
/* */
for (i = 0; i < element->descsubelement->count; i++) {
struct capwap_wtpdescriptor_desc_subelement *desc =
(struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(element->descsubelement, i);
if (desc->data)
capwap_free(desc->data);
}
capwap_array_free(element->encryptsubelement);
capwap_array_free(element->descsubelement);
capwap_free(data);
}
/* */
static void *capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle handle,
struct capwap_read_message_elements_ops *func)
{
uint8_t i;
uint8_t encryptlength;
struct capwap_wtpdescriptor_element *data;
ASSERT(handle != NULL);
ASSERT(func != NULL);
if (func->read_ready(handle) < 33) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor element: underbufer");
return NULL;
}
/* */
data = (struct capwap_wtpdescriptor_element*)capwap_alloc(sizeof(struct capwap_wtpdescriptor_element));
data->encryptsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_encrypt_subelement), 0, 0);
data->descsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_desc_subelement), 0, 1);
/* Retrieve data */
func->read_u8(handle, &data->maxradios);
func->read_u8(handle, &data->radiosinuse);
func->read_u8(handle, &encryptlength);
/* Check */
if (!encryptlength) {
capwap_wtpdescriptor_element_free(data);
log_printf(LOG_DEBUG, "Invalid WTP Descriptor element: invalid encryptlength");
return NULL;
} else if (data->maxradios < data->radiosinuse) {
capwap_wtpdescriptor_element_free(data);
log_printf(LOG_DEBUG, "Invalid WTP Descriptor element: invalid radio");
return NULL;
}
/* Encryption Subelement */
for (i = 0; i < encryptlength; i++) {
struct capwap_wtpdescriptor_encrypt_subelement *desc;
/* Check */
if (func->read_ready(handle) < 3) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor subelement: underbuffer");
capwap_wtpdescriptor_element_free(data);
return NULL;
}
/* */
desc = (struct capwap_wtpdescriptor_encrypt_subelement *)
capwap_array_get_item_pointer(data->encryptsubelement, data->encryptsubelement->count);
func->read_u8(handle, &desc->wbid);
func->read_u16(handle, &desc->capabilities);
if ((desc->wbid & CAPWAP_WTPDESC_SUBELEMENT_WBID_MASK) != desc->wbid) {
capwap_wtpdescriptor_element_free(data);
log_printf(LOG_DEBUG, "Invalid WTP Descriptor element: invalid wbid");
return NULL;
}
}
/* WTP Description Subelement */
while (func->read_ready(handle) > 0) {
unsigned short length;
uint16_t lengthdesc;
struct capwap_wtpdescriptor_desc_subelement *desc;
/* Check */
if (func->read_ready(handle) < 8) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor subelement: underbuffer");
capwap_wtpdescriptor_element_free(data);
return NULL;
}
/* */
desc = (struct capwap_wtpdescriptor_desc_subelement *)
capwap_array_get_item_pointer(data->descsubelement, data->descsubelement->count);
func->read_u32(handle, &desc->vendor);
func->read_u16(handle, &desc->type);
func->read_u16(handle, &lengthdesc);
if ((desc->type < CAPWAP_WTPDESC_SUBELEMENT_TYPE_FIRST) ||
(desc->type > CAPWAP_WTPDESC_SUBELEMENT_TYPE_LAST)) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor subelement: invalid type");
capwap_wtpdescriptor_element_free(data);
return NULL;
}
/* Check buffer size */
length = func->read_ready(handle);
if (!length ||
(length > CAPWAP_WTPDESC_SUBELEMENT_MAXDATA) ||
(length < lengthdesc)) {
log_printf(LOG_DEBUG, "Invalid WTP Descriptor element");
capwap_wtpdescriptor_element_free(data);
return NULL;
}
desc->data = (uint8_t*)capwap_alloc(lengthdesc + 1);
func->read_block(handle, desc->data, lengthdesc);
desc->data[lengthdesc] = 0;
}
return data;
}
/* */
const struct capwap_message_elements_ops capwap_element_wtpdescriptor_ops = {
.category = CAPWAP_MESSAGE_ELEMENT_SINGLE,
.create = capwap_wtpdescriptor_element_create,
.parse = capwap_wtpdescriptor_element_parsing,
.clone = capwap_wtpdescriptor_element_clone,
.free = capwap_wtpdescriptor_element_free
};