freewtp/src/common/capwap_element_wtpboarddata.c

162 lines
5.5 KiB
C

#include "capwap.h"
#include "capwap_array.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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Board Data Sub-Element...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Board Data Type | Board Data Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Board Data Value...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type: 38 for WTP Board Data
Length: >=14
********************************************************************/
struct capwap_wtpboarddata_raw_element {
unsigned long vendor;
char data[0];
} __attribute__((__packed__));
struct capwap_wtpboarddata_raw_board_subelement {
unsigned short type;
unsigned short length;
char data[0];
} __attribute__((__packed__));
/* */
struct capwap_message_element* capwap_wtpboarddata_element_create(void* data, unsigned long datalength) {
char* pos;
unsigned long i;
unsigned short length;
struct capwap_message_element* element;
struct capwap_wtpboarddata_raw_element* dataraw;
struct capwap_wtpboarddata_element* dataelement = (struct capwap_wtpboarddata_element*)data;
ASSERT(data != NULL);
ASSERT(datalength >= sizeof(struct capwap_wtpboarddata_element));
ASSERT(dataelement->boardsubelement != NULL);
/* Calc length packet */
length = sizeof(struct capwap_wtpboarddata_raw_element);
for (i = 0; i < dataelement->boardsubelement->count; i++) {
struct capwap_wtpboarddata_board_subelement* board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(dataelement->boardsubelement, i);
length += sizeof(struct capwap_wtpboarddata_raw_board_subelement) + board->length;
}
/* Alloc block of memory */
element = capwap_alloc(sizeof(struct capwap_message_element) + length);
if (!element) {
capwap_outofmemory();
}
/* Create message element */
memset(element, 0, sizeof(struct capwap_message_element) + length);
element->type = htons(CAPWAP_ELEMENT_WTPBOARDDATA);
element->length = htons(length);
/* */
dataraw = (struct capwap_wtpboarddata_raw_element*)element->data;
dataraw->vendor = htonl(dataelement->vendor);
pos = dataraw->data;
/* Board Sub-Element */
for (i = 0; i < dataelement->boardsubelement->count; i++) {
struct capwap_wtpboarddata_raw_board_subelement* boardraw = (struct capwap_wtpboarddata_raw_board_subelement*)pos;
struct capwap_wtpboarddata_board_subelement* board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(dataelement->boardsubelement, i);
boardraw->type = htons(board->type);
boardraw->length = htons(board->length);
memcpy(boardraw->data, board->data, board->length);
pos += sizeof(struct capwap_wtpboarddata_raw_board_subelement) + board->length;
}
return element;
}
/* */
int capwap_wtpboarddata_element_validate(struct capwap_message_element* element) {
/* TODO */
return 1;
}
/* */
void* capwap_wtpboarddata_element_parsing(struct capwap_message_element* element) {
long i;
char* pos;
long length;
struct capwap_wtpboarddata_element* data;
struct capwap_wtpboarddata_raw_element* dataraw;
ASSERT(element);
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPBOARDDATA);
length = (long)ntohs(element->length);
if (length < 14) {
capwap_logging_debug("Invalid WTP Board Data element");
return NULL;
}
/* */
dataraw = (struct capwap_wtpboarddata_raw_element*)element->data;
data = (struct capwap_wtpboarddata_element*)capwap_alloc(sizeof(struct capwap_wtpboarddata_element));
data->boardsubelement = capwap_array_create(sizeof(struct capwap_wtpboarddata_board_subelement), 0);
/* */
data->vendor = ntohl(dataraw->vendor);
pos = dataraw->data;
length -= sizeof(struct capwap_wtpboarddata_raw_element);
/* Board Subelement */
i = 0;
while (length > 0) {
struct capwap_wtpboarddata_board_subelement* board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(data->boardsubelement, i);
struct capwap_wtpboarddata_raw_board_subelement* boardraw = (struct capwap_wtpboarddata_raw_board_subelement*)pos;
unsigned short boardlength = ntohs(boardraw->length);
unsigned short boardrawlength = sizeof(struct capwap_wtpboarddata_raw_board_subelement) + boardlength;
if ((boardlength > CAPWAP_BOARD_SUBELEMENT_MAXDATA) || (length < boardrawlength)) {
capwap_logging_debug("Invalid WTP Board Data element");
capwap_wtpboarddata_element_free(data);
return NULL;
}
/* */
board->type = ntohs(boardraw->type);
board->length = boardlength;
memcpy(board->data, boardraw->data, boardlength);
/* */
i++;
pos += boardrawlength;
length -= boardrawlength;
}
return data;
}
/* */
void capwap_wtpboarddata_element_free(void* data) {
struct capwap_wtpboarddata_element* dataelement = (struct capwap_wtpboarddata_element*)data;
ASSERT(dataelement != NULL);
ASSERT(dataelement->boardsubelement != NULL);
capwap_array_free(dataelement->boardsubelement);
capwap_free(dataelement);
}