First commit
This commit is contained in:
151
src/common/capwap.c
Normal file
151
src/common/capwap.c
Normal file
@ -0,0 +1,151 @@
|
||||
#include "capwap.h"
|
||||
|
||||
/* Helper exit */
|
||||
void capwap_exit(int errorcode) {
|
||||
exit(errorcode);
|
||||
}
|
||||
|
||||
/* Helper timeout calc */
|
||||
void capwap_init_timeout(struct timeout_control* timeout) {
|
||||
ASSERT(timeout);
|
||||
|
||||
memset(timeout, 0, sizeof(struct timeout_control));
|
||||
}
|
||||
|
||||
void capwap_update_timeout(struct timeout_control* timeout) {
|
||||
int i;
|
||||
struct timeval now;
|
||||
|
||||
ASSERT(timeout);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
for (i = 0; i < CAPWAP_MAX_TIMER; i++) {
|
||||
if (timeout->items[i].enable && (timeout->items[i].delta >= 0)) {
|
||||
timeout->items[i].delta = (timeout->items[i].timestop.tv_sec - now.tv_sec) * 1000 + (timeout->items[i].timestop.tv_usec - now.tv_usec) / 1000;
|
||||
if (timeout->items[i].delta < 0) {
|
||||
timeout->items[i].delta = 0;
|
||||
} else if (timeout->items[i].delta > timeout->items[i].durate) {
|
||||
/* Changed system time */
|
||||
timeout->items[i].delta = timeout->items[i].durate;
|
||||
memcpy(&timeout->items[i].timestop, &now, sizeof(struct timeval));
|
||||
timeout->items[i].timestop.tv_sec += timeout->items[i].durate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long capwap_get_timeout(struct timeout_control* timeout, long* index) {
|
||||
long i;
|
||||
long delta = 0;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(index != NULL);
|
||||
|
||||
*index = CAPWAP_TIMER_UNDEF;
|
||||
for (i = 0; i < CAPWAP_MAX_TIMER; i++) {
|
||||
if (timeout->items[i].enable) {
|
||||
if (timeout->items[i].delta <= 0) {
|
||||
*index = i;
|
||||
delta = 0;
|
||||
break;
|
||||
} else if (!delta || (delta > timeout->items[i].delta)) {
|
||||
*index = i;
|
||||
delta = timeout->items[i].delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
int capwap_is_enable_timeout(struct timeout_control* timeout, unsigned long index) {
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(index < CAPWAP_MAX_TIMER);
|
||||
|
||||
return (timeout->items[index].enable ? 1 : 0);
|
||||
}
|
||||
|
||||
int capwap_is_timeout(struct timeout_control* timeout, unsigned long index) {
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(index < CAPWAP_MAX_TIMER);
|
||||
|
||||
if (timeout->items[index].enable && (timeout->items[index].delta <= 0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void capwap_set_timeout(unsigned long value, struct timeout_control* timeout, unsigned long index) {
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(index < CAPWAP_MAX_TIMER);
|
||||
|
||||
/* Set timeout in ms */
|
||||
timeout->items[index].enable = 1;
|
||||
timeout->items[index].delta = value * 1000;
|
||||
timeout->items[index].durate = value * 1000;
|
||||
gettimeofday(&timeout->items[index].timestop, NULL);
|
||||
timeout->items[index].timestop.tv_sec += value;
|
||||
}
|
||||
|
||||
void capwap_kill_timeout(struct timeout_control* timeout, unsigned long index) {
|
||||
ASSERT(timeout != NULL);
|
||||
ASSERT(index < CAPWAP_MAX_TIMER);
|
||||
|
||||
timeout->items[index].enable = 0;
|
||||
}
|
||||
|
||||
void capwap_killall_timeout(struct timeout_control* timeout) {
|
||||
long i;
|
||||
|
||||
ASSERT(timeout != NULL);
|
||||
|
||||
for (i = 0; i < CAPWAP_MAX_TIMER; i++) {
|
||||
timeout->items[i].enable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init randon generator */
|
||||
void capwap_init_rand(void) {
|
||||
srand(time(NULL));
|
||||
}
|
||||
|
||||
/* Get random number */
|
||||
int capwap_get_rand(int max) {
|
||||
if ((max < 0) || (max > RAND_MAX)) {
|
||||
max = RAND_MAX;
|
||||
}
|
||||
|
||||
return (rand() % max);
|
||||
}
|
||||
|
||||
/* Duplicate string */
|
||||
char* capwap_duplicate_string(const char* source) {
|
||||
char* clone;
|
||||
|
||||
ASSERT(source != NULL);
|
||||
|
||||
clone = capwap_alloc(sizeof(char) * (strlen(source) + 1));
|
||||
if (!clone) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
strcpy(clone, source);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/* Buffer clone */
|
||||
void* capwap_clone(void* buffer, int buffersize) {
|
||||
void* bufferclone;
|
||||
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(buffersize > 0);
|
||||
|
||||
bufferclone = capwap_alloc(buffersize);
|
||||
if (!bufferclone) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
return memcpy(bufferclone, buffer, buffersize);
|
||||
}
|
101
src/common/capwap.h
Normal file
101
src/common/capwap.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef __CAPWAP_HEADER__
|
||||
#define __CAPWAP_HEADER__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <net/if.h>
|
||||
|
||||
//TODO:
|
||||
//#ifdef NATIVE_UDPLITE_HEADER
|
||||
//#include <netinet/udplite.h>
|
||||
//#else
|
||||
//#define IPPROTO_UDPLITE 136
|
||||
#define SOL_UDPLITE 136
|
||||
#define UDPLITE_SEND_CSCOV 10
|
||||
//#endif
|
||||
|
||||
/* Endian */
|
||||
#ifdef WIN32
|
||||
#define CAPWAP_LITTLE_ENDIAN
|
||||
#else
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define CAPWAP_BIG_ENDIAN
|
||||
#else
|
||||
#define CAPWAP_LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Min & Max */
|
||||
#ifndef max
|
||||
#define max(a,b) ((a) >= (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* config */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* standard include */
|
||||
#include "capwap_logging.h"
|
||||
#include "capwap_debug.h"
|
||||
#include "capwap_error.h"
|
||||
|
||||
/* Helper exit */
|
||||
void capwap_exit(int errorcode);
|
||||
|
||||
/* Random generator */
|
||||
void capwap_init_rand(void);
|
||||
int capwap_get_rand(int max);
|
||||
|
||||
/* Helper timeout calc */
|
||||
struct timeout_control_item {
|
||||
int enable;
|
||||
long delta;
|
||||
unsigned long durate;
|
||||
struct timeval timestop;
|
||||
};
|
||||
|
||||
#define CAPWAP_TIMER_UNDEF -1
|
||||
#define CAPWAP_TIMER_CONTROL_CONNECTION 0
|
||||
#define CAPWAP_TIMER_CONTROL_ECHO 1
|
||||
#define CAPWAP_TIMER_DATA_KEEPALIVE 2
|
||||
#define CAPWAP_TIMER_DATA_KEEPALIVEDEAD 3
|
||||
#define CAPWAP_MAX_TIMER 4
|
||||
|
||||
struct timeout_control {
|
||||
struct timeout_control_item items[CAPWAP_MAX_TIMER];
|
||||
};
|
||||
|
||||
void capwap_init_timeout(struct timeout_control* timeout);
|
||||
long capwap_get_timeout(struct timeout_control* timeout, long* index);
|
||||
void capwap_update_timeout(struct timeout_control* timeout);
|
||||
void capwap_set_timeout(unsigned long value, struct timeout_control* timeout, unsigned long index);
|
||||
void capwap_kill_timeout(struct timeout_control* timeout, unsigned long index);
|
||||
void capwap_killall_timeout(struct timeout_control* timeout);
|
||||
int capwap_is_enable_timeout(struct timeout_control* timeout, unsigned long index);
|
||||
int capwap_is_timeout(struct timeout_control* timeout, unsigned long index);
|
||||
|
||||
/* */
|
||||
#define capwap_outofmemory() capwap_logging_fatal("Out of memory %s(%d)", __FILE__, __LINE__); \
|
||||
capwap_exit(CAPWAP_OUT_OF_MEMORY);
|
||||
|
||||
/* Helper buffer copy */
|
||||
char* capwap_duplicate_string(const char* source);
|
||||
void* capwap_clone(void* buffer, int buffersize);
|
||||
|
||||
#endif /* __CAPWAP_HEADER__ */
|
92
src/common/capwap_array.c
Normal file
92
src/common/capwap_array.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_array.h"
|
||||
|
||||
/* */
|
||||
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount) {
|
||||
struct capwap_array* array;
|
||||
|
||||
ASSERT(itemsize > 0);
|
||||
|
||||
array = (struct capwap_array*)capwap_alloc(sizeof(struct capwap_array));
|
||||
if (!array) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
memset(array, 0, sizeof(struct capwap_array));
|
||||
array->itemsize = itemsize;
|
||||
if (initcount > 0) {
|
||||
capwap_array_resize(array, initcount);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_array* capwap_array_clone(struct capwap_array* array) {
|
||||
unsigned long i;
|
||||
struct capwap_array* clone;
|
||||
|
||||
ASSERT (array != NULL);
|
||||
|
||||
/* Clone array e items */
|
||||
clone = capwap_array_create(array->itemsize, array->count);
|
||||
for (i = 0; i < array->count; i++) {
|
||||
memcpy(capwap_array_get_item_pointer(clone, i), capwap_array_get_item_pointer(array, i), array->itemsize);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_array_free(struct capwap_array* array) {
|
||||
ASSERT(array != NULL);
|
||||
|
||||
if (array->buffer) {
|
||||
capwap_free(array->buffer);
|
||||
}
|
||||
|
||||
capwap_free(array);
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos) {
|
||||
ASSERT(array != NULL);
|
||||
ASSERT((array->count == 0) || (array->buffer != NULL));
|
||||
|
||||
if (pos >= array->count) {
|
||||
capwap_array_resize(array, pos + 1);
|
||||
}
|
||||
|
||||
return (void*)(((char*)array->buffer) + array->itemsize * pos);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_array_resize(struct capwap_array* array, unsigned long count) {
|
||||
void* newbuffer = NULL;
|
||||
|
||||
ASSERT(array != NULL);
|
||||
ASSERT(array->itemsize > 0);
|
||||
|
||||
if (array->count == count) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
newbuffer = capwap_alloc(array->itemsize * count);
|
||||
if (!newbuffer) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
}
|
||||
|
||||
if (array->buffer) {
|
||||
if (newbuffer != NULL) {
|
||||
memcpy(newbuffer, array->buffer, array->itemsize * min(array->count, count));
|
||||
}
|
||||
|
||||
capwap_free(array->buffer);
|
||||
}
|
||||
|
||||
array->buffer = newbuffer;
|
||||
array->count = count;
|
||||
}
|
||||
|
21
src/common/capwap_array.h
Normal file
21
src/common/capwap_array.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __CAPWAP_ARRAY_HEADER__
|
||||
#define __CAPWAP_ARRAY_HEADER__
|
||||
|
||||
struct capwap_array {
|
||||
void* buffer;
|
||||
unsigned short itemsize;
|
||||
unsigned long count;
|
||||
};
|
||||
|
||||
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount);
|
||||
struct capwap_array* capwap_array_clone(struct capwap_array* array);
|
||||
void capwap_array_free(struct capwap_array* array);
|
||||
void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos);
|
||||
void capwap_array_resize(struct capwap_array* array, unsigned long count);
|
||||
|
||||
/* Helper */
|
||||
#define capwap_array_getitem(x, y, z) *((z*)capwap_array_get_item_pointer((x), (y)))
|
||||
#define capwap_array_setnewitem(x, y, z) *((z*)capwap_array_get_item_pointer((x), (x)->count)) = (y)
|
||||
|
||||
|
||||
#endif /* __CAPWAP_ARRAY_HEADER__ */
|
161
src/common/capwap_debug.c
Normal file
161
src/common/capwap_debug.c
Normal file
@ -0,0 +1,161 @@
|
||||
#include <execinfo.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "capwap_logging.h"
|
||||
|
||||
#define CANARY 0xaaaaaaaa
|
||||
#define BACKTRACE_BUFFER 256
|
||||
|
||||
#ifndef DEBUG_BREAKPOINT
|
||||
#define DEBUG_BREAKPOINT() __asm__("int3")
|
||||
#endif
|
||||
|
||||
/* Memory block */
|
||||
struct capwap_memory_block {
|
||||
void* item;
|
||||
size_t size;
|
||||
const char* file;
|
||||
int line;
|
||||
void* backtrace[BACKTRACE_BUFFER];
|
||||
int backtrace_count;
|
||||
struct capwap_memory_block* next;
|
||||
};
|
||||
|
||||
static struct capwap_memory_block* g_memoryblocks = NULL;
|
||||
|
||||
/* Alloc memory block */
|
||||
void* capwap_alloc_debug(size_t size, const char* file, const int line) {
|
||||
struct capwap_memory_block* block;
|
||||
|
||||
/* Request size > 0 */
|
||||
if (size <= 0) {
|
||||
capwap_logging_debug("%s(%d): Invalid memory size %d", file, line, size);
|
||||
DEBUG_BREAKPOINT();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Alloc block with memory block and canary */
|
||||
block = (struct capwap_memory_block*)malloc(sizeof(struct capwap_memory_block) + size + 4);
|
||||
if (!block) {
|
||||
capwap_logging_debug("Out of memory %s(%d)", __FILE__, __LINE__);
|
||||
DEBUG_BREAKPOINT();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Info memory block */
|
||||
block->item = (void*)(((char*)block) + sizeof(struct capwap_memory_block));
|
||||
block->size = size;
|
||||
block->file = file;
|
||||
block->line = line;
|
||||
block->backtrace_count = backtrace(block->backtrace, BACKTRACE_BUFFER);
|
||||
block->next = g_memoryblocks;
|
||||
|
||||
/* Canary */
|
||||
*((unsigned long*)(((char*)block->item) + block->size)) = CANARY;
|
||||
|
||||
g_memoryblocks = block;
|
||||
|
||||
return block->item;
|
||||
}
|
||||
|
||||
/* Free memory block */
|
||||
void capwap_free_debug(void* p, const char* file, const int line) {
|
||||
struct capwap_memory_block* block;
|
||||
struct capwap_memory_block* findblock;
|
||||
struct capwap_memory_block* prevblock;
|
||||
|
||||
if (!p) {
|
||||
capwap_logging_debug("%s(%d): Free NULL pointer", file, line);
|
||||
DEBUG_BREAKPOINT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Memory block */
|
||||
if ((size_t)p <= sizeof(struct capwap_memory_block)) {
|
||||
capwap_logging_debug("%s(%d): Invalid pointer", file, line);
|
||||
DEBUG_BREAKPOINT();
|
||||
return;
|
||||
}
|
||||
|
||||
block = (struct capwap_memory_block*)((char*)p - sizeof(struct capwap_memory_block));
|
||||
if (block->item != p) {
|
||||
capwap_logging_debug("%s(%d): Invalid pointer", file, line);
|
||||
DEBUG_BREAKPOINT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check canary */
|
||||
if (*((unsigned long*)(((char*)block->item) + block->size)) != CANARY) {
|
||||
capwap_logging_debug("%s(%d): Invalid canary allocted in %s(%d)", file, line, block->file, block->line);
|
||||
DEBUG_BREAKPOINT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find memory block */
|
||||
prevblock = NULL;
|
||||
findblock = g_memoryblocks;
|
||||
while (findblock != NULL) {
|
||||
if (findblock == block) {
|
||||
if (!prevblock) {
|
||||
g_memoryblocks = block->next;
|
||||
} else {
|
||||
prevblock->next = block->next;
|
||||
}
|
||||
|
||||
/* Invalidate block */
|
||||
memset(block, 0, sizeof(struct capwap_memory_block));
|
||||
free(block);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Next */
|
||||
prevblock = findblock;
|
||||
findblock = findblock->next;
|
||||
}
|
||||
|
||||
capwap_logging_debug("%s(%d): Unable to find memory block", file, line);
|
||||
}
|
||||
|
||||
/* Dump memory alloced */
|
||||
void capwap_dump_memory(void) {
|
||||
char** backtrace_functions;
|
||||
struct capwap_memory_block* findblock;
|
||||
|
||||
findblock = g_memoryblocks;
|
||||
while (findblock != NULL) {
|
||||
capwap_logging_debug("%s(%d): block at %p, %d bytes long", findblock->file, findblock->line, findblock->item, findblock->size);
|
||||
|
||||
backtrace_functions = backtrace_symbols(findblock->backtrace, findblock->backtrace_count);
|
||||
if (backtrace_functions) {
|
||||
int j;
|
||||
|
||||
/* Skipping capwap_alloc_debug function print out */
|
||||
for (j = 1; j < findblock->backtrace_count; j++) {
|
||||
capwap_logging_debug("\t%s", backtrace_functions[j]);
|
||||
}
|
||||
|
||||
free(backtrace_functions);
|
||||
}
|
||||
|
||||
|
||||
/* Next */
|
||||
findblock = findblock->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if all memory is free */
|
||||
int capwap_check_memory_leak(int verbose) {
|
||||
if ((g_memoryblocks != NULL) && (verbose != 0)) {
|
||||
capwap_logging_debug("*** Detected memory leaks ! ***");
|
||||
capwap_dump_memory();
|
||||
capwap_logging_debug("*******************************");
|
||||
}
|
||||
|
||||
return ((g_memoryblocks != NULL) ? 1 : 0);
|
||||
}
|
37
src/common/capwap_debug.h
Normal file
37
src/common/capwap_debug.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef __CAPWAP_DEBUG_HEADER__
|
||||
#define __CAPWAP_DEBUG_HEADER__
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define DEBUG_BREAKPOINT() __asm__("int3")
|
||||
|
||||
#define ASSERT(expr) if (!(expr)) { \
|
||||
capwap_logging_fatal("Assertion failed \'%s\': %s(%d)", #expr, __FILE__, __LINE__); \
|
||||
DEBUG_BREAKPOINT(); \
|
||||
}
|
||||
|
||||
/* Custom memory management */
|
||||
#define capwap_alloc(x) capwap_alloc_debug(x, __FILE__, __LINE__)
|
||||
void* capwap_alloc_debug(size_t size, const char* file, const int line);
|
||||
#define capwap_free(x) capwap_free_debug(x, __FILE__, __LINE__)
|
||||
void capwap_free_debug(void* p, const char* file, const int line);
|
||||
|
||||
int capwap_check_memory_leak(int verbose);
|
||||
void capwap_dump_memory(void);
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_BREAKPOINT()
|
||||
|
||||
#define ASSERT(expr)
|
||||
|
||||
/* Standard memory management */
|
||||
#define capwap_alloc(x) (void*)malloc(x)
|
||||
#define capwap_free(x) free(x)
|
||||
#define capwap_check_memory_leak(x) (0)
|
||||
#define capwap_dump_memory() (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __CAPWAP_DEBUG_HEADER__ */
|
||||
|
61
src/common/capwap_dfa.c
Normal file
61
src/common/capwap_dfa.c
Normal file
@ -0,0 +1,61 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_dfa.h"
|
||||
|
||||
static char* l_nameofstate[] = {
|
||||
"START", /* CAPWAP_START_STATE */
|
||||
"START_TO_IDLE", /* CAPWAP_START_TO_IDLE_STATE */
|
||||
"IDLE", /* CAPWAP_IDLE_STATE */
|
||||
"IDLE_TO_DISCOVERY", /* CAPWAP_IDLE_TO_DISCOVERY_STATE */
|
||||
"IDLE_TO_DTLS_SETUP", /* CAPWAP_IDLE_TO_DTLS_SETUP_STATE */
|
||||
"DISCOVERY", /* CAPWAP_DISCOVERY_STATE */
|
||||
"DISCOVERY_TO_IDLE", /* CAPWAP_DISCOVERY_TO_IDLE_STATE */
|
||||
"DISCOVERY_TO_SULKING", /* CAPWAP_DISCOVERY_TO_SULKING_STATE */
|
||||
"DISCOVERY_TO_DTLS_SETUP", /* CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE */
|
||||
"SULKING", /* CAPWAP_SULKING_STATE */
|
||||
"SULKING_TO_IDLE", /* CAPWAP_SULKING_TO_IDLE_STATE */
|
||||
"DTLS_SETUP", /* CAPWAP_DTLS_SETUP_STATE */
|
||||
"DTLS_SETUP_TO_IDLE", /* CAPWAP_DTLS_SETUP_TO_IDLE_STATE */
|
||||
"DTLS_SETUP_TO_SULKING", /* CAPWAP_DTLS_SETUP_TO_SULKING_STATE */
|
||||
"DTLS_SETUP_TO_AUTHORIZE", /* CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE */
|
||||
"AUTHORIZE", /* CAPWAP_AUTHORIZE_STATE */
|
||||
"AUTHORIZE_TO_DTLS_SETUP", /* CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE */
|
||||
"AUTHORIZE_TO_DTLS_CONNECT", /* CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE */
|
||||
"AUTHORIZE_TO_DTLS_TEARDOWN", /* CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE */
|
||||
"DTLS_CONNECT", /* CAPWAP_DTLS_CONNECT_STATE */
|
||||
"DTLS_CONNECT_TO_DTLS_TEARDOWN", /* CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE */
|
||||
"DTLS_CONNECT_TO_JOIN", /* CAPWAP_DTLS_CONNECT_TO_JOIN_STATE */
|
||||
"DTLS_TEARDOWN", /* CAPWAP_DTLS_TEARDOWN_STATE */
|
||||
"DTLS_TEARDOWN_TO_IDLE", /* CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE */
|
||||
"DTLS_TEARDOWN_TO_SULKING", /* CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE */
|
||||
"DTLS_TEARDOWN_TO_DEAD", /* CAPWAP_DTLS_TEARDOWN_TO_DEAD_STATE */
|
||||
"JOIN", /* CAPWAP_JOIN_STATE */
|
||||
"POST_JOIN", /* CAPWAP_POSTJOIN_STATE */
|
||||
"JOIN_TO_DTLS_TEARDOWN", /* CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE */
|
||||
"JOIN_TO_IMAGE_DATA", /* CAPWAP_JOIN_TO_IMAGE_DATA_STATE */
|
||||
"JOIN_TO_CONFIGURE", /* CAPWAP_JOIN_TO_CONFIGURE_STATE */
|
||||
"IMAGE_DATA", /* CAPWAP_IMAGE_DATA_STATE */
|
||||
"IMAGE_DATA_TO_RESET", /* CAPWAP_IMAGE_DATA_TO_RESET_STATE */
|
||||
"IMAGE_DATA_TO_DTLS_TEARDOWN", /* CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE */
|
||||
"CONFIGURE", /* CAPWAP_CONFIGURE_STATE */
|
||||
"CONFIGURE_TO_RESET", /* CAPWAP_CONFIGURE_TO_RESET_STATE */
|
||||
"CONFIGURE_TO_DTLS_TEARDOWN", /* CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE */
|
||||
"CONFIGURE_TO_DATA_CHECK", /* CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE */
|
||||
"RESET", /* CAPWAP_RESET_STATE */
|
||||
"RESET_TO_DTLS_TEARDOWN", /* CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE */
|
||||
"DATA_CHECK", /* CAPWAP_DATA_CHECK_STATE */
|
||||
"DATA_CHECK_TO_DTLS_TEARDOWN", /* CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE */
|
||||
"DATA_CHECK_TO_RUN", /* CAPWAP_DATA_CHECK_TO_RUN_STATE */
|
||||
"RUN", /* CAPWAP_RUN_STATE */
|
||||
"RUN_TO_DTLS_TEARDOWN", /* CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE */
|
||||
"RUN_TO_RESET", /* CAPWAP_RUN_TO_RESET_STATE */
|
||||
"DEAD" /* CAPWAP_DEAD_STATE */
|
||||
};
|
||||
|
||||
/* */
|
||||
char* capwap_dfa_getname(int state) {
|
||||
if ((state < 0) || (state > CAPWAP_LAST_STATE)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return l_nameofstate[state];
|
||||
}
|
57
src/common/capwap_dfa.h
Normal file
57
src/common/capwap_dfa.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef __CAPWAP_DFA_HEADER__
|
||||
#define __CAPWAP_DFA_HEADER__
|
||||
|
||||
#define CAPWAP_UNDEF_STATE -1
|
||||
#define CAPWAP_START_STATE 0
|
||||
#define CAPWAP_START_TO_IDLE_STATE 1
|
||||
#define CAPWAP_IDLE_STATE 2
|
||||
#define CAPWAP_IDLE_TO_DISCOVERY_STATE 3
|
||||
#define CAPWAP_IDLE_TO_DTLS_SETUP_STATE 4
|
||||
#define CAPWAP_DISCOVERY_STATE 5
|
||||
#define CAPWAP_DISCOVERY_TO_IDLE_STATE 6
|
||||
#define CAPWAP_DISCOVERY_TO_SULKING_STATE 7
|
||||
#define CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE 8
|
||||
#define CAPWAP_SULKING_STATE 9
|
||||
#define CAPWAP_SULKING_TO_IDLE_STATE 10
|
||||
#define CAPWAP_DTLS_SETUP_STATE 11
|
||||
#define CAPWAP_DTLS_SETUP_TO_IDLE_STATE 12
|
||||
#define CAPWAP_DTLS_SETUP_TO_SULKING_STATE 13
|
||||
#define CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE 14
|
||||
#define CAPWAP_AUTHORIZE_STATE 15
|
||||
#define CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE 16
|
||||
#define CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE 17
|
||||
#define CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE 18
|
||||
#define CAPWAP_DTLS_CONNECT_STATE 19
|
||||
#define CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE 20
|
||||
#define CAPWAP_DTLS_CONNECT_TO_JOIN_STATE 21
|
||||
#define CAPWAP_DTLS_TEARDOWN_STATE 22
|
||||
#define CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE 23
|
||||
#define CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE 24
|
||||
#define CAPWAP_DTLS_TEARDOWN_TO_DEAD_STATE 25
|
||||
#define CAPWAP_JOIN_STATE 26
|
||||
#define CAPWAP_POSTJOIN_STATE 27
|
||||
#define CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE 28
|
||||
#define CAPWAP_JOIN_TO_IMAGE_DATA_STATE 29
|
||||
#define CAPWAP_JOIN_TO_CONFIGURE_STATE 30
|
||||
#define CAPWAP_IMAGE_DATA_STATE 31
|
||||
#define CAPWAP_IMAGE_DATA_TO_RESET_STATE 32
|
||||
#define CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE 33
|
||||
#define CAPWAP_CONFIGURE_STATE 34
|
||||
#define CAPWAP_CONFIGURE_TO_RESET_STATE 35
|
||||
#define CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE 36
|
||||
#define CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE 37
|
||||
#define CAPWAP_RESET_STATE 38
|
||||
#define CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE 39
|
||||
#define CAPWAP_DATA_CHECK_STATE 40
|
||||
#define CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE 41
|
||||
#define CAPWAP_DATA_CHECK_TO_RUN_STATE 42
|
||||
#define CAPWAP_RUN_STATE 43
|
||||
#define CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE 44
|
||||
#define CAPWAP_RUN_TO_RESET_STATE 45
|
||||
#define CAPWAP_DEAD_STATE 46
|
||||
#define CAPWAP_LAST_STATE 46
|
||||
|
||||
/* */
|
||||
char* capwap_dfa_getname(int state);
|
||||
|
||||
#endif /* __CAPWAP_DFA_HEADER__ */
|
785
src/common/capwap_dtls.c
Normal file
785
src/common/capwap_dtls.c
Normal file
@ -0,0 +1,785 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_dtls.h"
|
||||
#include "capwap_protocol.h"
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/conf.h>
|
||||
|
||||
#define CAPWAP_DTLS_CERT_VERIFY_DEPTH 1
|
||||
#define CAPWAP_DTLS_MTU_SIZE 16384
|
||||
|
||||
/* */
|
||||
static int capwap_bio_method_new(BIO* bio);
|
||||
static int capwap_bio_method_free(BIO* bio);
|
||||
static int capwap_bio_method_puts(BIO* bio, const char* str);
|
||||
static int capwap_bio_method_read(BIO* bio, char* str, int length);
|
||||
static int capwap_bio_method_write(BIO* bio, const char* str, int length);
|
||||
static long capwap_bio_method_ctrl(BIO* bio, int cmd, long num, void* ptr);
|
||||
|
||||
/* OpenSSL BIO methods */
|
||||
static BIO_METHOD bio_methods_memory = {
|
||||
BIO_TYPE_DGRAM,
|
||||
"dtls capwap packet",
|
||||
capwap_bio_method_write,
|
||||
capwap_bio_method_read,
|
||||
capwap_bio_method_puts,
|
||||
NULL,
|
||||
capwap_bio_method_ctrl,
|
||||
capwap_bio_method_new,
|
||||
capwap_bio_method_free,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* OpenSSL BIO custom data */
|
||||
struct bio_capwap_data {
|
||||
int mtu;
|
||||
struct sockaddr_storage peer;
|
||||
struct capwap_dtls* dtls;
|
||||
capwap_bio_send send;
|
||||
void* param;
|
||||
};
|
||||
|
||||
/* */
|
||||
static BIO* capwap_bio_new() {
|
||||
BIO* result;
|
||||
|
||||
result = BIO_new(&bio_methods_memory);
|
||||
if (result) {
|
||||
memset(result->ptr, 0, sizeof(struct bio_capwap_data));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_bio_method_new(BIO* bio) {
|
||||
bio->init = 1;
|
||||
bio->num = 0;
|
||||
bio->flags = 0;
|
||||
bio->ptr = (char*)capwap_alloc(sizeof(struct bio_capwap_data));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_bio_method_free(BIO* bio) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
} else if (bio->ptr) {
|
||||
capwap_free(bio->ptr);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_bio_method_puts(BIO* bio, const char* str) {
|
||||
return capwap_bio_method_write(bio, str, strlen(str));
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_bio_method_read(BIO* bio, char* str, int length) {
|
||||
struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
|
||||
struct capwap_dtls_header* dtlspreamble;
|
||||
int size;
|
||||
|
||||
/* Check read packet */
|
||||
if ((data->dtls->length < sizeof(struct capwap_dtls_header)) || !data->dtls->buffer) {
|
||||
if (!data->dtls->length && !data->dtls->buffer) {
|
||||
BIO_set_retry_read(bio); /* Notify empty buffer */
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check DTLS Capwap Preamble */
|
||||
dtlspreamble = (struct capwap_dtls_header*)data->dtls->buffer;
|
||||
if ((dtlspreamble->preamble.version != CAPWAP_PROTOCOL_VERSION) || (dtlspreamble->preamble.type != CAPWAP_PREAMBLE_DTLS_HEADER)) {
|
||||
capwap_logging_debug("Wrong DTLS Capwap Preamble");
|
||||
return -1; /* Wrong DTLS Capwap Preamble */
|
||||
}
|
||||
|
||||
/* */
|
||||
size = data->dtls->length - sizeof(struct capwap_dtls_header);
|
||||
data->dtls->length = 0;
|
||||
|
||||
data->dtls->buffer += sizeof(struct capwap_dtls_header);
|
||||
if (size > length) {
|
||||
data->dtls->buffer = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy DTLS packet */
|
||||
memcpy(str, data->dtls->buffer, size);
|
||||
data->dtls->buffer = NULL;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_bio_method_write(BIO* bio, const char* str, int length) {
|
||||
struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
|
||||
char buffer[CAPWAP_MAX_PACKET_SIZE];
|
||||
struct capwap_dtls_header* dtlspreamble = (struct capwap_dtls_header*)&buffer[0];
|
||||
|
||||
/* Check for maxium size of packet */
|
||||
if (length > (CAPWAP_MAX_PACKET_SIZE - sizeof(struct capwap_dtls_header))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create DTLS Capwap Preamble */
|
||||
dtlspreamble->preamble.version = CAPWAP_PROTOCOL_VERSION;
|
||||
dtlspreamble->preamble.type = CAPWAP_PREAMBLE_DTLS_HEADER;
|
||||
dtlspreamble->reserved1 = dtlspreamble->reserved2 = dtlspreamble->reserved3 = 0;
|
||||
memcpy(&buffer[0] + sizeof(struct capwap_dtls_header), str, length);
|
||||
|
||||
/* Send packet */
|
||||
if (!data->send(data->dtls, buffer, length + sizeof(struct capwap_dtls_header), data->param)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't return size of DTLS Capwap Preamble */
|
||||
return length;
|
||||
}
|
||||
|
||||
/* */
|
||||
static long capwap_bio_method_ctrl(BIO* bio, int cmd, long num, void* ptr) {
|
||||
long result = 1;
|
||||
struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_EOF: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_INFO: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_GET_CLOSE: {
|
||||
result = bio->shutdown;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_SET_CLOSE: {
|
||||
bio->shutdown = (int)num;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
case BIO_CTRL_PENDING: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH: {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_PUSH: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_POP: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DGRAM_QUERY_MTU: {
|
||||
data->mtu = CAPWAP_DTLS_MTU_SIZE;
|
||||
result = data->mtu;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DGRAM_GET_MTU: {
|
||||
result = data->mtu;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DGRAM_SET_MTU: {
|
||||
data->mtu = (int)num;
|
||||
result = data->mtu;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DGRAM_SET_PEER: {
|
||||
memcpy(&data->peer, ptr, sizeof(struct sockaddr_storage));
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DGRAM_GET_PEER: {
|
||||
memcpy(ptr, &data->peer, sizeof(struct sockaddr_storage));
|
||||
break;
|
||||
}
|
||||
|
||||
case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: {
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_crypt_init() {
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_crypt_free() {
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
|
||||
ENGINE_cleanup();
|
||||
EVP_cleanup();
|
||||
|
||||
CONF_modules_finish();
|
||||
CONF_modules_free();
|
||||
CONF_modules_unload(1);
|
||||
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
sk_SSL_COMP_free (SSL_COMP_get_compression_methods());
|
||||
}
|
||||
|
||||
/* */
|
||||
static int check_passwd(char* buffer, int size, int rwflag, void* userdata) {
|
||||
int length;
|
||||
struct capwap_dtls_context* dtlscontext = (struct capwap_dtls_context*)userdata;
|
||||
|
||||
ASSERT(dtlscontext != NULL);
|
||||
ASSERT(dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE);
|
||||
ASSERT(dtlscontext->cert.pwdprivatekey != NULL);
|
||||
|
||||
length = strlen(dtlscontext->cert.pwdprivatekey);
|
||||
if (!buffer || (size < (length + 1))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(buffer, dtlscontext->cert.pwdprivatekey);
|
||||
return length;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int verify_certificate(int ok, X509_STORE_CTX* ctx) {
|
||||
int err;
|
||||
int depth;
|
||||
X509* err_cert;
|
||||
char buf[256];
|
||||
int preverify_ok = 1;
|
||||
|
||||
err_cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
|
||||
err = X509_STORE_CTX_get_error(ctx);
|
||||
X509_verify_cert_error_string(err);
|
||||
|
||||
depth = X509_STORE_CTX_get_error_depth(ctx);
|
||||
|
||||
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
|
||||
|
||||
if (depth > CAPWAP_DTLS_CERT_VERIFY_DEPTH) {
|
||||
preverify_ok = 0;
|
||||
err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
|
||||
X509_STORE_CTX_set_error(ctx, err);
|
||||
}
|
||||
|
||||
if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
|
||||
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
|
||||
}
|
||||
|
||||
return preverify_ok;
|
||||
}
|
||||
|
||||
static int create_cookie(SSL* ssl, unsigned char* cookie, unsigned int* cookie_len) {
|
||||
int length;
|
||||
unsigned char* buffer;
|
||||
struct sockaddr_storage peer;
|
||||
struct capwap_app_data* appdata;
|
||||
|
||||
/* */
|
||||
appdata = (struct capwap_app_data*)SSL_get_app_data(ssl);
|
||||
if (!appdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read peer information */
|
||||
BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
|
||||
|
||||
/* Create buffer with peer's address and port */
|
||||
if (peer.ss_family == AF_INET) {
|
||||
length = sizeof(struct in_addr) + sizeof(in_port_t);
|
||||
} else if (peer.ss_family == AF_INET6) {
|
||||
length = sizeof(struct in6_addr) + sizeof(in_port_t);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
buffer = capwap_alloc(length);
|
||||
if (!buffer) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
if (peer.ss_family == AF_INET) {
|
||||
struct sockaddr_in* peeripv4 = (struct sockaddr_in*)&peer;
|
||||
|
||||
memcpy(buffer, &peeripv4->sin_port, sizeof(in_port_t));
|
||||
memcpy(buffer + sizeof(in_port_t), &peeripv4->sin_addr, sizeof(struct in_addr));
|
||||
} else if (peer.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6* peeripv6 = (struct sockaddr_in6*)&peer;
|
||||
|
||||
memcpy(buffer, &peeripv6->sin6_port, sizeof(in_port_t));
|
||||
memcpy(buffer + sizeof(in_port_t), &peeripv6->sin6_addr, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
/* Calculate HMAC of buffer using the secret */
|
||||
HMAC(EVP_sha1(), appdata->cookie, CAPWAP_COOKIE_SECRET_LENGTH, buffer, length, cookie, cookie_len);
|
||||
capwap_free(buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int generate_cookie(SSL* ssl, unsigned char* cookie, unsigned int* cookie_len) {
|
||||
unsigned int resultlength;
|
||||
unsigned char result[EVP_MAX_MD_SIZE];
|
||||
|
||||
if (!create_cookie(ssl, &result[0], &resultlength)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cookie generated */
|
||||
memcpy(cookie, result, resultlength);
|
||||
*cookie_len = resultlength;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int verify_cookie(SSL* ssl, unsigned char* cookie, unsigned int cookie_len) {
|
||||
unsigned int resultlength;
|
||||
unsigned char result[EVP_MAX_MD_SIZE];
|
||||
|
||||
if (!create_cookie(ssl, &result[0], &resultlength)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check cookie */
|
||||
if ((cookie_len != resultlength) || (memcmp(result, cookie, resultlength) != 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_crypt_createcontext(struct capwap_dtls_context* dtlscontext, struct capwap_dtls_param* param) {
|
||||
int length;
|
||||
|
||||
ASSERT(dtlscontext != NULL);
|
||||
ASSERT(param != NULL);
|
||||
|
||||
memset(dtlscontext, 0, sizeof(struct capwap_dtls_context));
|
||||
dtlscontext->type = param->type;
|
||||
dtlscontext->mode = param->mode;
|
||||
|
||||
/* Alloc context */
|
||||
dtlscontext->sslcontext = SSL_CTX_new(((param->type == CAPWAP_DTLS_SERVER) ? DTLSv1_server_method() : DTLSv1_client_method()));
|
||||
if (!dtlscontext->sslcontext) {
|
||||
capwap_logging_debug("Error to initialize dtls context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
|
||||
/* Check context */
|
||||
if (!param->cert.filecert || !strlen(param->cert.filecert)) {
|
||||
capwap_logging_debug("Error, request certificate file");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
} else if (!param->cert.filekey || !strlen(param->cert.filekey)) {
|
||||
capwap_logging_debug("Error, request privatekey file");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
} else if (!param->cert.fileca || !strlen(param->cert.fileca)) {
|
||||
capwap_logging_debug("Error, request ca file");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Public certificate */
|
||||
if (!SSL_CTX_use_certificate_file(dtlscontext->sslcontext, param->cert.filecert, SSL_FILETYPE_PEM)) {
|
||||
capwap_logging_debug("Error to load certificate file");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Passwork decrypt privatekey */
|
||||
length = (param->cert.pwdprivatekey ? strlen(param->cert.pwdprivatekey) : 0);
|
||||
dtlscontext->cert.pwdprivatekey = (char*)capwap_alloc(sizeof(char) * (length + 1));
|
||||
if (length > 0) {
|
||||
strcpy(dtlscontext->cert.pwdprivatekey, param->cert.pwdprivatekey);
|
||||
}
|
||||
dtlscontext->cert.pwdprivatekey[length] = 0;
|
||||
|
||||
SSL_CTX_set_default_passwd_cb(dtlscontext->sslcontext, check_passwd);
|
||||
SSL_CTX_set_default_passwd_cb_userdata(dtlscontext->sslcontext, dtlscontext);
|
||||
|
||||
/* Private key */
|
||||
if (!SSL_CTX_use_PrivateKey_file(dtlscontext->sslcontext, param->cert.filekey, SSL_FILETYPE_PEM)) {
|
||||
capwap_logging_debug("Error to load private key file");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_check_private_key(dtlscontext->sslcontext)) {
|
||||
capwap_logging_debug("Error to check private key");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Certificate Authority */
|
||||
if (!SSL_CTX_load_verify_locations(dtlscontext->sslcontext, param->cert.fileca, NULL)) {
|
||||
capwap_logging_debug("Error to load ca file");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_set_default_verify_paths(dtlscontext->sslcontext)) {
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify certificate callback */
|
||||
SSL_CTX_set_verify(dtlscontext->sslcontext, ((param->type == CAPWAP_DTLS_SERVER) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_PEER), verify_certificate);
|
||||
|
||||
/* Cipher list:
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
|
||||
*/
|
||||
if (!SSL_CTX_set_cipher_list(dtlscontext->sslcontext, "AES128-SHA:DHE-RSA-AES128-SHA:AES256-SHA:DHE-RSA-AES256-SHA")) {
|
||||
capwap_logging_debug("Error to select cipher list");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
} else if (dtlscontext->mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
|
||||
/* TODO */
|
||||
} else {
|
||||
capwap_logging_debug("Invalid DTLS mode");
|
||||
capwap_crypt_freecontext(dtlscontext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cookie callback */
|
||||
RAND_bytes(dtlscontext->cookie, CAPWAP_COOKIE_SECRET_LENGTH);
|
||||
SSL_CTX_set_cookie_generate_cb(dtlscontext->sslcontext, generate_cookie);
|
||||
SSL_CTX_set_cookie_verify_cb(dtlscontext->sslcontext, verify_cookie);
|
||||
|
||||
/* */
|
||||
SSL_CTX_set_read_ahead(dtlscontext->sslcontext, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_crypt_freecontext(struct capwap_dtls_context* dtlscontext) {
|
||||
ASSERT(dtlscontext != NULL);
|
||||
|
||||
/* */
|
||||
if (dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
|
||||
if (dtlscontext->cert.pwdprivatekey) {
|
||||
capwap_free(dtlscontext->cert.pwdprivatekey);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free context */
|
||||
if (dtlscontext->sslcontext) {
|
||||
SSL_CTX_free(dtlscontext->sslcontext);
|
||||
}
|
||||
|
||||
memset(dtlscontext, 0, sizeof(struct capwap_dtls));
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_crypt_createsession(struct capwap_dtls* dtls, int sessiontype, struct capwap_dtls_context* dtlscontext, capwap_bio_send biosend, void* param) {
|
||||
BIO* bio;
|
||||
struct capwap_app_data* appdata;
|
||||
|
||||
ASSERT(dtls != NULL);
|
||||
ASSERT(dtlscontext != NULL);
|
||||
ASSERT(biosend != NULL);
|
||||
|
||||
memset(dtls, 0, sizeof(struct capwap_dtls));
|
||||
|
||||
/* Create ssl session */
|
||||
dtls->sslsession = SSL_new(dtlscontext->sslcontext);
|
||||
if (!dtls->sslsession) {
|
||||
capwap_logging_debug("Error to initialize dtls session");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create BIO */
|
||||
bio = capwap_bio_new();
|
||||
if (!bio) {
|
||||
capwap_logging_debug("Error to initialize bio");
|
||||
capwap_crypt_free(dtls);
|
||||
return 0;
|
||||
} else {
|
||||
struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
|
||||
data->dtls = dtls;
|
||||
data->send = biosend;
|
||||
data->param = param;
|
||||
}
|
||||
|
||||
/* Configure BIO */
|
||||
SSL_set_bio(dtls->sslsession, bio, bio);
|
||||
|
||||
/* In server mode enable cookie exchange */
|
||||
if (dtlscontext->type == CAPWAP_DTLS_SERVER) {
|
||||
SSL_set_options(dtls->sslsession, SSL_OP_COOKIE_EXCHANGE);
|
||||
}
|
||||
|
||||
/* Set static MTU size */
|
||||
SSL_set_options(dtls->sslsession, SSL_OP_NO_QUERY_MTU);
|
||||
SSL_set_mtu(dtls->sslsession, CAPWAP_DTLS_MTU_SIZE);
|
||||
|
||||
/* */
|
||||
SSL_set_verify_depth(dtls->sslsession, CAPWAP_DTLS_CERT_VERIFY_DEPTH + 1);
|
||||
|
||||
/* */
|
||||
SSL_set_read_ahead(dtls->sslsession, 1);
|
||||
|
||||
if (dtlscontext->type == CAPWAP_DTLS_SERVER) {
|
||||
SSL_set_accept_state(dtls->sslsession);
|
||||
} else {
|
||||
SSL_set_connect_state(dtls->sslsession);
|
||||
}
|
||||
|
||||
/* SSL session app data */
|
||||
appdata = (struct capwap_app_data*)capwap_alloc(sizeof(struct capwap_app_data));
|
||||
if (!appdata) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
appdata->cookie = &dtlscontext->cookie[0];
|
||||
SSL_set_app_data(dtls->sslsession, (void*)appdata);
|
||||
|
||||
/* */
|
||||
dtls->action = CAPWAP_DTLS_ACTION_NONE;
|
||||
dtls->session = sessiontype;
|
||||
dtls->enable = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int capwap_crypt_handshake(struct capwap_dtls* dtls) {
|
||||
int result;
|
||||
|
||||
ASSERT(dtls != NULL);
|
||||
ASSERT(dtls->enable != 0);
|
||||
ASSERT((dtls->action == CAPWAP_DTLS_ACTION_NONE) || (dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE));
|
||||
|
||||
ERR_clear_error();
|
||||
result = SSL_do_handshake(dtls->sslsession);
|
||||
if (result <= 0) {
|
||||
result = SSL_get_error(dtls->sslsession, result);
|
||||
if ((result == SSL_ERROR_WANT_READ) || (result == SSL_ERROR_WANT_WRITE)) {
|
||||
/* Incomplete handshake */
|
||||
dtls->action = CAPWAP_DTLS_ACTION_HANDSHAKE;
|
||||
return CAPWAP_HANDSHAKE_CONTINUE;
|
||||
}
|
||||
|
||||
/* Handshake error */
|
||||
dtls->action = CAPWAP_DTLS_ACTION_ERROR;
|
||||
return CAPWAP_HANDSHAKE_ERROR;
|
||||
}
|
||||
|
||||
/* Check certificate */
|
||||
result = SSL_get_verify_result(dtls->sslsession);
|
||||
if (result != X509_V_OK) {
|
||||
dtls->action = CAPWAP_DTLS_ACTION_ERROR;
|
||||
return CAPWAP_HANDSHAKE_ERROR;
|
||||
}
|
||||
|
||||
/* Handshake complete */
|
||||
dtls->action = CAPWAP_DTLS_ACTION_DATA;
|
||||
return CAPWAP_HANDSHAKE_COMPLETE;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_crypt_open(struct capwap_dtls* dtls, struct sockaddr_storage* peeraddr) {
|
||||
BIO_dgram_set_peer(SSL_get_rbio(dtls->sslsession), peeraddr);
|
||||
return capwap_crypt_handshake(dtls);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_crypt_close(struct capwap_dtls* dtls) {
|
||||
ASSERT(dtls != NULL);
|
||||
ASSERT(dtls->enable != 0);
|
||||
|
||||
if ((dtls->action == CAPWAP_DTLS_ACTION_DATA) || (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) {
|
||||
SSL_shutdown(dtls->sslsession);
|
||||
}
|
||||
}
|
||||
|
||||
/* Change bio send */
|
||||
void capwap_crypt_change_bio_send(struct capwap_dtls* dtls, capwap_bio_send biosend, void* param) {
|
||||
BIO* bio;
|
||||
|
||||
ASSERT(dtls != NULL);
|
||||
ASSERT(dtls->enable != 0);
|
||||
ASSERT(biosend != NULL);
|
||||
|
||||
bio = SSL_get_wbio(dtls->sslsession);
|
||||
if ((bio != NULL) && (bio->ptr != NULL)) {
|
||||
struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
|
||||
|
||||
data->send = biosend;
|
||||
data->param = param;
|
||||
}
|
||||
}
|
||||
|
||||
/* Change DTLS */
|
||||
void capwap_crypt_change_dtls(struct capwap_dtls* dtls, struct capwap_dtls* newdtls) {
|
||||
BIO* bio;
|
||||
|
||||
ASSERT(dtls != NULL);
|
||||
ASSERT(dtls->enable != 0);
|
||||
ASSERT(newdtls != NULL);
|
||||
|
||||
memcpy(newdtls, dtls, sizeof(struct capwap_dtls));
|
||||
|
||||
/* Update DTLS into BIO */
|
||||
bio = SSL_get_rbio(dtls->sslsession);
|
||||
if ((bio != NULL) && (bio->ptr != NULL)) {
|
||||
struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
|
||||
|
||||
data->dtls = newdtls;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_crypt_freesession(struct capwap_dtls* dtls) {
|
||||
ASSERT(dtls != NULL);
|
||||
|
||||
/* Free SSL session */
|
||||
if (dtls->sslsession) {
|
||||
struct capwap_app_data* appdata = (struct capwap_app_data*)SSL_get_app_data(dtls->sslsession);
|
||||
if (appdata) {
|
||||
capwap_free(appdata);
|
||||
}
|
||||
|
||||
SSL_free(dtls->sslsession);
|
||||
}
|
||||
|
||||
memset(dtls, 0, sizeof(struct capwap_dtls));
|
||||
}
|
||||
|
||||
/* TODO: con SSL vengono utilizzati gli indirizzi predefiniti invece quelli specificati nella funzione. Reingegnerizzarla basandosi sul concetto di connessione */
|
||||
int capwap_crypt_sendto(struct capwap_dtls* dtls, int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr) {
|
||||
ASSERT(sock >= 0);
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(size > 0);
|
||||
ASSERT(sendtoaddr != NULL);
|
||||
|
||||
if (!dtls || !dtls->enable) {
|
||||
return capwap_sendto(sock, buffer, size, sendfromaddr, sendtoaddr);
|
||||
}
|
||||
|
||||
/* Valid DTLS status */
|
||||
if (dtls->action != CAPWAP_DTLS_ACTION_DATA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
return SSL_write(dtls->sslsession, buffer, size);
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize) {
|
||||
int sslerror;
|
||||
int result = -1;
|
||||
char* clone = NULL;
|
||||
|
||||
ASSERT(dtls != NULL);
|
||||
ASSERT(dtls->enable != 0);
|
||||
ASSERT((dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE) || (dtls->action == CAPWAP_DTLS_ACTION_DATA));
|
||||
ASSERT(dtls->buffer == NULL);
|
||||
ASSERT(dtls->length == 0);
|
||||
ASSERT(encrybuffer != NULL);
|
||||
ASSERT(size > 0);
|
||||
ASSERT(maxsize > 0);
|
||||
|
||||
/* */
|
||||
if (!plainbuffer) {
|
||||
clone = capwap_clone(encrybuffer, size);
|
||||
}
|
||||
|
||||
dtls->buffer = (clone ? clone : encrybuffer);
|
||||
dtls->length = size;
|
||||
|
||||
/* */
|
||||
if (dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE) {
|
||||
if (capwap_crypt_handshake(dtls) == CAPWAP_HANDSHAKE_ERROR) {
|
||||
capwap_logging_debug("Error in DTLS handshake");
|
||||
result = CAPWAP_ERROR_CLOSE; /* Error handshake */
|
||||
} else {
|
||||
result = CAPWAP_ERROR_AGAIN; /* Don't parsing DTLS packet */
|
||||
}
|
||||
} else if (dtls->action == CAPWAP_DTLS_ACTION_DATA) {
|
||||
ERR_clear_error();
|
||||
result = SSL_read(dtls->sslsession, (plainbuffer ? plainbuffer : encrybuffer), maxsize);
|
||||
if (!result) {
|
||||
int shutdown;
|
||||
|
||||
/* Check shutdown status */
|
||||
shutdown = SSL_get_shutdown(dtls->sslsession);
|
||||
if (shutdown & SSL_RECEIVED_SHUTDOWN) {
|
||||
dtls->action = CAPWAP_DTLS_ACTION_SHUTDOWN;
|
||||
result = CAPWAP_ERROR_SHUTDOWN;
|
||||
} else {
|
||||
result = CAPWAP_ERROR_AGAIN;
|
||||
}
|
||||
} else if (result < 0) {
|
||||
/* Check error */
|
||||
sslerror = SSL_get_error(dtls->sslsession, result);
|
||||
if ((sslerror == SSL_ERROR_WANT_READ) || (sslerror == SSL_ERROR_WANT_WRITE)) {
|
||||
result = CAPWAP_ERROR_AGAIN; /* DTLS Renegotiation */
|
||||
} else {
|
||||
result = CAPWAP_ERROR_CLOSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify BIO read */
|
||||
ASSERT(dtls->buffer == NULL);
|
||||
ASSERT(dtls->length == 0);
|
||||
|
||||
/* Free clone */
|
||||
if (clone) {
|
||||
capwap_free(clone);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
108
src/common/capwap_dtls.h
Normal file
108
src/common/capwap_dtls.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef __CAPWAP_DTLS_HEADER__
|
||||
#define __CAPWAP_DTLS_HEADER__
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#define CAPWAP_DTLS_CLIENT 0
|
||||
#define CAPWAP_DTLS_SERVER 1
|
||||
|
||||
#define CAPWAP_DTLS_MODE_NONE 0
|
||||
#define CAPWAP_DTLS_MODE_CERTIFICATE 1
|
||||
#define CAPWAP_DTLS_MODE_PRESHAREDKEY 2
|
||||
|
||||
#define CAPWAP_DTLS_ACTION_NONE 0
|
||||
#define CAPWAP_DTLS_ACTION_HANDSHAKE 1
|
||||
#define CAPWAP_DTLS_ACTION_DATA 2
|
||||
#define CAPWAP_DTLS_ACTION_SHUTDOWN 3
|
||||
#define CAPWAP_DTLS_ACTION_ERROR 4
|
||||
|
||||
#define CAPWAP_HANDSHAKE_ERROR -1
|
||||
#define CAPWAP_HANDSHAKE_CONTINUE 0
|
||||
#define CAPWAP_HANDSHAKE_COMPLETE 1
|
||||
|
||||
#define CAPWAP_DTLS_CONTROL_SESSION 0
|
||||
#define CAPWAP_DTLS_DATA_SESSION 1
|
||||
|
||||
#define CAPWAP_COOKIE_SECRET_LENGTH 16
|
||||
|
||||
#define CAPWAP_ERROR_AGAIN 0
|
||||
#define CAPWAP_ERROR_SHUTDOWN -1
|
||||
#define CAPWAP_ERROR_CLOSE -2
|
||||
|
||||
struct capwap_dtls_param {
|
||||
int type;
|
||||
int mode;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int dummy; /* TODO */
|
||||
} presharedkey;
|
||||
|
||||
struct {
|
||||
/* Certificate files */
|
||||
char* filecert;
|
||||
char* filekey;
|
||||
char* fileca;
|
||||
|
||||
/* Password for private key */
|
||||
char* pwdprivatekey;
|
||||
} cert;
|
||||
};
|
||||
};
|
||||
|
||||
struct capwap_dtls_context {
|
||||
int type;
|
||||
int mode;
|
||||
|
||||
SSL_CTX* sslcontext;
|
||||
|
||||
/* Cookie */
|
||||
unsigned char cookie[CAPWAP_COOKIE_SECRET_LENGTH];
|
||||
|
||||
union {
|
||||
struct {
|
||||
int dummy; /* TODO */
|
||||
} presharedkey;
|
||||
|
||||
struct {
|
||||
char* pwdprivatekey; /* Password for private key */
|
||||
} cert;
|
||||
};
|
||||
};
|
||||
|
||||
struct capwap_dtls {
|
||||
int enable;
|
||||
int action;
|
||||
int session;
|
||||
|
||||
SSL* sslsession;
|
||||
|
||||
/* Buffer read */
|
||||
void* buffer;
|
||||
int length;
|
||||
};
|
||||
|
||||
struct capwap_app_data {
|
||||
unsigned char* cookie;
|
||||
};
|
||||
|
||||
typedef int(*capwap_bio_send)(struct capwap_dtls* dtls, char* buffer, int length, void* param);
|
||||
|
||||
int capwap_crypt_init();
|
||||
void capwap_crypt_free();
|
||||
|
||||
int capwap_crypt_createcontext(struct capwap_dtls_context* dtlscontext, struct capwap_dtls_param* param);
|
||||
void capwap_crypt_freecontext(struct capwap_dtls_context* dtlscontext);
|
||||
|
||||
int capwap_crypt_createsession(struct capwap_dtls* dtls, int sessiontype, struct capwap_dtls_context* dtlscontext, capwap_bio_send biosend, void* param);
|
||||
void capwap_crypt_freesession(struct capwap_dtls* dtls);
|
||||
|
||||
int capwap_crypt_open(struct capwap_dtls* dtls, struct sockaddr_storage* peeraddr);
|
||||
void capwap_crypt_close(struct capwap_dtls* dtls);
|
||||
void capwap_crypt_change_bio_send(struct capwap_dtls* dtls, capwap_bio_send biosend, void* param);
|
||||
void capwap_crypt_change_dtls(struct capwap_dtls* dtls, struct capwap_dtls* newdtls);
|
||||
|
||||
int capwap_crypt_sendto(struct capwap_dtls* dtls, int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
||||
int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize);
|
||||
|
||||
#endif /* __CAPWAP_DTLS_HEADER__ */
|
1373
src/common/capwap_element.c
Normal file
1373
src/common/capwap_element.c
Normal file
File diff suppressed because it is too large
Load Diff
288
src/common/capwap_element.h
Normal file
288
src/common/capwap_element.h
Normal file
@ -0,0 +1,288 @@
|
||||
#ifndef __CAPWAP_ELEMENT_HEADER__
|
||||
#define __CAPWAP_ELEMENT_HEADER__
|
||||
|
||||
#include "capwap_array.h"
|
||||
#include "capwap_list.h"
|
||||
|
||||
/* Standard message elements 1 -> 52 (1 - 1023) */
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_START 1
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_STOP 53
|
||||
#define CAPWAP_MESSAGE_ELEMENTS_COUNT ((CAPWAP_MESSAGE_ELEMENTS_STOP - CAPWAP_MESSAGE_ELEMENTS_START) + 1)
|
||||
#define IS_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
|
||||
|
||||
/* 802.11 message elements 1024 -> 1024 (1024 - 2047) */
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_START 1024
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_STOP 1048
|
||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_COUNT ((CAPWAP_80211_MESSAGE_ELEMENTS_STOP - CAPWAP_80211_MESSAGE_ELEMENTS_START) + 1)
|
||||
#define IS_80211_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_80211_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_80211_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
|
||||
|
||||
/* Message element */
|
||||
struct capwap_message_element {
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
typedef struct capwap_message_element*(*capwap_create_message_element)(void* data, unsigned long length);
|
||||
typedef int(*capwap_validate_message_element)(struct capwap_message_element* element);
|
||||
typedef void*(*capwap_parsing_message_element)(struct capwap_message_element* element);
|
||||
typedef void(*capwap_free_message_element)(void*);
|
||||
|
||||
struct capwap_message_elements_func {
|
||||
capwap_create_message_element create;
|
||||
capwap_validate_message_element check;
|
||||
capwap_parsing_message_element parsing;
|
||||
capwap_free_message_element free;
|
||||
};
|
||||
|
||||
struct capwap_message_elements_func* capwap_get_message_element(unsigned long code);
|
||||
|
||||
/*********************************************************************************************************************/
|
||||
/* Standard message elements */
|
||||
#include "capwap_element_acdescriptor.h" /* 00001 */
|
||||
#include "capwap_element_acipv4list.h" /* 00002 */
|
||||
#include "capwap_element_acipv6list.h" /* 00003 */
|
||||
#include "capwap_element_acname.h" /* 00004 */
|
||||
#include "capwap_element_acnamepriority.h" /* 00005 */
|
||||
/* 00006 */
|
||||
/* 00007 */
|
||||
/* 00008 */
|
||||
/* Reserved */ /* 00009 */
|
||||
#include "capwap_element_controlipv4.h" /* 00010 */
|
||||
#include "capwap_element_controlipv6.h" /* 00011 */
|
||||
#include "capwap_element_timers.h" /* 00012 */
|
||||
/* 00013 */
|
||||
/* 00014 */
|
||||
/* 00015 */
|
||||
#include "capwap_element_decrypterrorreportperiod.h" /* 00016 */
|
||||
/* 00017 */
|
||||
/* 00018 */
|
||||
/* Reserved */ /* 00019 */
|
||||
#include "capwap_element_discoverytype.h" /* 00020 */
|
||||
/* 00021 */
|
||||
/* 00022 */
|
||||
#include "capwap_element_idletimeout.h" /* 00023 */
|
||||
/* 00024 */
|
||||
#include "capwap_element_imageidentifier.h" /* 00025 */
|
||||
/* 00026 */
|
||||
/* 00027 */
|
||||
#include "capwap_element_location.h" /* 00028 */
|
||||
#include "capwap_element_maximumlength.h" /* 00029 */
|
||||
#include "capwap_element_localipv4.h" /* 00030 */
|
||||
#include "capwap_element_radioadmstate.h" /* 00031 */
|
||||
#include "capwap_element_radiooprstate.h" /* 00032 */
|
||||
#include "capwap_element_resultcode.h" /* 00033 */
|
||||
#include "capwap_element_returnedmessage.h" /* 00034 */
|
||||
#include "capwap_element_sessionid.h" /* 00035 */
|
||||
#include "capwap_element_statisticstimer.h" /* 00036 */
|
||||
#include "capwap_element_vendorpayload.h" /* 00037 */
|
||||
#include "capwap_element_wtpboarddata.h" /* 00038 */
|
||||
#include "capwap_element_wtpdescriptor.h" /* 00039 */
|
||||
#include "capwap_element_wtpfallback.h" /* 00040 */
|
||||
#include "capwap_element_wtpframetunnelmode.h" /* 00041 */
|
||||
/* Reserved */ /* 00042 */
|
||||
/* Reserved */ /* 00043 */
|
||||
#include "capwap_element_wtpmactype.h" /* 00044 */
|
||||
#include "capwap_element_wtpname.h" /* 00045 */
|
||||
/* Reserved */ /* 00046 */
|
||||
/* 00047 */
|
||||
#include "capwap_element_wtprebootstat.h" /* 00048 */
|
||||
#include "capwap_element_wtpstaticipaddress.h" /* 00049 */
|
||||
#include "capwap_element_localipv6.h" /* 00050 */
|
||||
#include "capwap_element_transport.h" /* 00051 */
|
||||
#include "capwap_element_mtudiscovery.h" /* 00052 */
|
||||
#include "capwap_element_ecnsupport.h" /* 00053 */
|
||||
|
||||
/* IEEE 802.11 message elements */
|
||||
#include "capwap_element_80211_wtpradioinformation.h" /* 01048 */
|
||||
|
||||
/*********************************************************************************************************************/
|
||||
struct capwap_element_discovery_request {
|
||||
struct capwap_discoverytype_element* discoverytype;
|
||||
struct capwap_wtpboarddata_element* wtpboarddata;
|
||||
struct capwap_wtpdescriptor_element* wtpdescriptor;
|
||||
struct capwap_wtpframetunnelmode_element* wtpframetunnel;
|
||||
struct capwap_wtpmactype_element* wtpmactype;
|
||||
struct capwap_mtudiscovery_element* mtudiscovery;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct capwap_array* wtpradioinformation;
|
||||
} ieee80211;
|
||||
} binding;
|
||||
};
|
||||
|
||||
void capwap_init_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding);
|
||||
int capwap_parsing_element_discovery_request(struct capwap_element_discovery_request* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_discovery_response {
|
||||
struct capwap_acdescriptor_element* acdescriptor;
|
||||
struct capwap_acname_element* acname;
|
||||
struct capwap_array* controlipv4;
|
||||
struct capwap_array* controlipv6;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct capwap_array* wtpradioinformation;
|
||||
} ieee80211;
|
||||
} binding;
|
||||
};
|
||||
|
||||
void capwap_init_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding);
|
||||
int capwap_parsing_element_discovery_response(struct capwap_element_discovery_response* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_join_request {
|
||||
struct capwap_location_element* locationdata;
|
||||
struct capwap_wtpboarddata_element* wtpboarddata;
|
||||
struct capwap_wtpdescriptor_element* wtpdescriptor;
|
||||
struct capwap_wtpname_element* wtpname;
|
||||
struct capwap_sessionid_element* sessionid;
|
||||
struct capwap_wtpframetunnelmode_element* wtpframetunnel;
|
||||
struct capwap_wtpmactype_element* wtpmactype;
|
||||
struct capwap_ecnsupport_element* ecnsupport;
|
||||
struct capwap_localipv4_element* localipv4;
|
||||
struct capwap_localipv6_element* localipv6;
|
||||
struct capwap_transport_element* trasport;
|
||||
struct capwap_maximumlength_element* maxiumlength;
|
||||
struct capwap_wtprebootstat_element* wtprebootstat;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct capwap_array* wtpradioinformation;
|
||||
} ieee80211;
|
||||
} binding;
|
||||
};
|
||||
|
||||
void capwap_init_element_join_request(struct capwap_element_join_request* element, unsigned short binding);
|
||||
int capwap_parsing_element_join_request(struct capwap_element_join_request* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_join_request(struct capwap_element_join_request* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_join_response {
|
||||
struct capwap_resultcode_element* resultcode;
|
||||
struct capwap_array* returnedmessage;
|
||||
struct capwap_acdescriptor_element* acdescriptor;
|
||||
struct capwap_acname_element* acname;
|
||||
struct capwap_ecnsupport_element* ecnsupport;
|
||||
struct capwap_array* controlipv4;
|
||||
struct capwap_array* controlipv6;
|
||||
struct capwap_localipv4_element* localipv4;
|
||||
struct capwap_localipv6_element* localipv6;
|
||||
capwap_acipv4list_element_array* acipv4list;
|
||||
capwap_acipv6list_element_array* acipv6list;
|
||||
struct capwap_transport_element* trasport;
|
||||
struct capwap_imageidentifier_element* imageidentifier;
|
||||
struct capwap_maximumlength_element* maxiumlength;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct capwap_array* wtpradioinformation;
|
||||
} ieee80211;
|
||||
} binding;
|
||||
};
|
||||
|
||||
void capwap_init_element_join_response(struct capwap_element_join_response* element, unsigned short binding);
|
||||
int capwap_parsing_element_join_response(struct capwap_element_join_response* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_join_response(struct capwap_element_join_response* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_configurationstatus_request {
|
||||
struct capwap_acname_element* acname;
|
||||
struct capwap_array* radioadmstatus;
|
||||
struct capwap_statisticstimer_element* statisticstimer;
|
||||
struct capwap_wtprebootstat_element* wtprebootstat;
|
||||
struct capwap_array* acnamepriority;
|
||||
struct capwap_transport_element* trasport;
|
||||
struct capwap_wtpstaticipaddress_element* wtpstaticipaddress;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding);
|
||||
int capwap_parsing_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_configurationstatus_response {
|
||||
struct capwap_timers_element* timers;
|
||||
struct capwap_array* decrypterrorresultperiod;
|
||||
struct capwap_idletimeout_element* idletimeout;
|
||||
struct capwap_wtpfallback_element* wtpfallback;
|
||||
capwap_acipv4list_element_array* acipv4list;
|
||||
capwap_acipv6list_element_array* acipv6list;
|
||||
struct capwap_array* radiooprstatus;
|
||||
struct capwap_wtpstaticipaddress_element* wtpstaticipaddress;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding);
|
||||
int capwap_parsing_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_changestateevent_request {
|
||||
struct capwap_array* radiooprstatus;
|
||||
struct capwap_resultcode_element* resultcode;
|
||||
struct capwap_array* returnedmessage;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding);
|
||||
int capwap_parsing_element_changestateevent_request(struct capwap_element_changestateevent_request* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_changestateevent_response {
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding);
|
||||
int capwap_parsing_element_changestateevent_response(struct capwap_element_changestateevent_response* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_echo_request {
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding);
|
||||
int capwap_parsing_element_echo_request(struct capwap_element_echo_request* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_echo_response {
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding);
|
||||
int capwap_parsing_element_echo_response(struct capwap_element_echo_response* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_reset_request {
|
||||
struct capwap_imageidentifier_element* imageidentifier;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding);
|
||||
int capwap_parsing_element_reset_request(struct capwap_element_reset_request* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding);
|
||||
|
||||
/* */
|
||||
struct capwap_element_reset_response {
|
||||
struct capwap_resultcode_element* resultcode;
|
||||
struct capwap_vendorpayload_element* vendorpayload;
|
||||
};
|
||||
|
||||
void capwap_init_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding);
|
||||
int capwap_parsing_element_reset_response(struct capwap_element_reset_response* element, struct capwap_list_item* item);
|
||||
void capwap_free_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding);
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_HEADER__ */
|
88
src/common/capwap_element_80211_wtpradioinformation.c
Normal file
88
src/common/capwap_element_80211_wtpradioinformation.c
Normal file
@ -0,0 +1,88 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Radio ID | Radio Type |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Radio Type |
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 1048 for IEEE 802.11 WTP Radio Information
|
||||
|
||||
Length: 5
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_80211_wtpradioinformation_raw_element {
|
||||
unsigned char radioid;
|
||||
unsigned long radiotype;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_80211_wtpradioinformation_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_80211_wtpradioinformation_raw_element* dataraw;
|
||||
struct capwap_80211_wtpradioinformation_element* dataelement = (struct capwap_80211_wtpradioinformation_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_80211_wtpradioinformation_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_wtpradioinformation_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_wtpradioinformation_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
|
||||
element->length = htons(sizeof(struct capwap_80211_wtpradioinformation_raw_element));
|
||||
dataraw = (struct capwap_80211_wtpradioinformation_raw_element*)element->data;
|
||||
|
||||
dataraw->radioid = dataelement->radioid;
|
||||
dataraw->radiotype = htonl(dataelement->radiotype);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_80211_wtpradioinformation_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_80211_wtpradioinformation_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_80211_wtpradioinformation_element* data;
|
||||
struct capwap_80211_wtpradioinformation_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
|
||||
|
||||
if (ntohs(element->length) != 5) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dataraw = (struct capwap_80211_wtpradioinformation_raw_element*)element->data;
|
||||
|
||||
/* */
|
||||
data = (struct capwap_80211_wtpradioinformation_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioinformation_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->radioid = dataraw->radioid;
|
||||
data->radiotype = ntohl(dataraw->radiotype);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_80211_wtpradioinformation_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
27
src/common/capwap_element_80211_wtpradioinformation.h
Normal file
27
src/common/capwap_element_80211_wtpradioinformation.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__
|
||||
#define __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION 1048
|
||||
|
||||
struct capwap_80211_wtpradioinformation_element {
|
||||
unsigned char radioid;
|
||||
unsigned long radiotype;
|
||||
};
|
||||
|
||||
#define CAPWAP_RADIO_TYPE_80211N 0x08
|
||||
#define CAPWAP_RADIO_TYPE_80211G 0x04
|
||||
#define CAPWAP_RADIO_TYPE_80211A 0x02
|
||||
#define CAPWAP_RADIO_TYPE_80211B 0x01
|
||||
|
||||
struct capwap_message_element* capwap_80211_wtpradioinformation_element_create(void* data, unsigned long length);
|
||||
int capwap_80211_wtpradioinformation_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_80211_wtpradioinformation_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_80211_wtpradioinformation_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); \
|
||||
f->create(x, sizeof(struct capwap_80211_wtpradioinformation_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__ */
|
199
src/common/capwap_element_acdescriptor.c
Normal file
199
src/common/capwap_element_acdescriptor.c
Normal file
@ -0,0 +1,199 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Stations | Limit |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Active WTPs | Max WTPs |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Security | R-MAC Field | Reserved1 | DTLS Policy |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| AC Information 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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| AC Information Vendor Identifier |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| AC Information Type | AC Information Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| AC Information Data...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 1 for AC Descriptor
|
||||
Length: >= 12
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_acdescriptor_raw_element {
|
||||
unsigned short stations;
|
||||
unsigned short limit;
|
||||
unsigned short activewtp;
|
||||
unsigned short maxwtp;
|
||||
unsigned char security;
|
||||
unsigned char rmacfield;
|
||||
unsigned char reserved;
|
||||
unsigned char dtlspolicy;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct capwap_acdescriptor_raw_desc_subelement {
|
||||
unsigned long vendor;
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_acdescriptor_element_create(void* data, unsigned long datalength) {
|
||||
char* pos;
|
||||
unsigned long i;
|
||||
unsigned short length;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_acdescriptor_raw_element* dataraw;
|
||||
struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_acdescriptor_element));
|
||||
ASSERT(dataelement->descsubelement != NULL);
|
||||
|
||||
/* Calc length packet */
|
||||
length = sizeof(struct capwap_acdescriptor_raw_element);
|
||||
for (i = 0; i < dataelement->descsubelement->count; i++) {
|
||||
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i);
|
||||
length += sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desc->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_ACDESCRIPTION);
|
||||
element->length = htons(length);
|
||||
|
||||
/* Descriptor */
|
||||
dataraw = (struct capwap_acdescriptor_raw_element*)element->data;
|
||||
dataraw->stations = htons(dataelement->station);
|
||||
dataraw->limit = htons(dataelement->stationlimit);
|
||||
dataraw->activewtp = htons(dataelement->wtp);
|
||||
dataraw->maxwtp = htons(dataelement->wtplimit);
|
||||
dataraw->security = dataelement->security;
|
||||
dataraw->rmacfield = dataelement->rmacfield;
|
||||
dataraw->dtlspolicy = dataelement->dtlspolicy;
|
||||
|
||||
/* Descriptor Sub-Element */
|
||||
pos = dataraw->data;
|
||||
for (i = 0; i < dataelement->descsubelement->count; i++) {
|
||||
struct capwap_acdescriptor_raw_desc_subelement* descraw = (struct capwap_acdescriptor_raw_desc_subelement*)pos;
|
||||
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i);
|
||||
|
||||
descraw->vendor = htonl(desc->vendor);
|
||||
descraw->type = htons(desc->type);
|
||||
descraw->length = htons(desc->length);
|
||||
memcpy(descraw->data, desc->data, desc->length);
|
||||
|
||||
pos += sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desc->length;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_acdescriptor_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned char i;
|
||||
long length;
|
||||
char* pos;
|
||||
struct capwap_acdescriptor_element* data;
|
||||
struct capwap_acdescriptor_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACDESCRIPTION);
|
||||
|
||||
length = (long)ntohs(element->length);
|
||||
if (length < 12) {
|
||||
capwap_logging_debug("Invalid AC Descriptor element");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_acdescriptor_raw_element*)element->data;
|
||||
if ((dataraw->stations > dataraw->limit) || (dataraw->activewtp > dataraw->maxwtp)) {
|
||||
capwap_logging_debug("Invalid AC Descriptor element");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_acdescriptor_element*)capwap_alloc(sizeof(struct capwap_acdescriptor_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
data->descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0);
|
||||
|
||||
/* */
|
||||
data->station = htons(dataraw->stations);
|
||||
data->stationlimit = htons(dataraw->limit);
|
||||
data->wtp = htons(dataraw->activewtp);
|
||||
data->wtplimit = htons(dataraw->maxwtp);
|
||||
data->security = dataraw->security;
|
||||
data->rmacfield = dataraw->rmacfield;
|
||||
data->dtlspolicy = dataraw->dtlspolicy;
|
||||
|
||||
pos = dataraw->data;
|
||||
length -= sizeof(struct capwap_acdescriptor_raw_element);
|
||||
|
||||
/* Description Subelement */
|
||||
i = 0;
|
||||
while (length > 0) {
|
||||
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, i);
|
||||
struct capwap_acdescriptor_raw_desc_subelement* descraw = (struct capwap_acdescriptor_raw_desc_subelement*)pos;
|
||||
unsigned short desclength = ntohs(descraw->length);
|
||||
unsigned short descrawlength = sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desclength;
|
||||
|
||||
if ((desclength > CAPWAP_ACDESC_SUBELEMENT_MAXDATA) || (length < descrawlength)) {
|
||||
capwap_logging_debug("Invalid AC Descriptor element");
|
||||
capwap_acdescriptor_element_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
desc->vendor = ntohl(descraw->vendor);
|
||||
desc->type = ntohs(descraw->type);
|
||||
desc->length = desclength;
|
||||
memcpy(desc->data, descraw->data, desclength);
|
||||
|
||||
/* */
|
||||
i++;
|
||||
pos += descrawlength;
|
||||
length -= descrawlength;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_acdescriptor_element_free(void* data) {
|
||||
struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data;
|
||||
|
||||
ASSERT(dataelement != NULL);
|
||||
ASSERT(dataelement->descsubelement != NULL);
|
||||
|
||||
capwap_array_free(dataelement->descsubelement);
|
||||
capwap_free(dataelement);
|
||||
}
|
48
src/common/capwap_element_acdescriptor.h
Normal file
48
src/common/capwap_element_acdescriptor.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__
|
||||
#define __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_ACDESCRIPTION 1
|
||||
|
||||
#define CAPWAP_ACDESC_SECURITY_PRESHARED_KEY 0x04
|
||||
#define CAPWAP_ACDESC_SECURITY_X509_CERT 0x02
|
||||
|
||||
#define CAPWAP_ACDESC_RMACFIELD_SUPPORTED 1
|
||||
#define CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED 2
|
||||
|
||||
#define CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED 0x04
|
||||
#define CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED 0x02
|
||||
|
||||
struct capwap_acdescriptor_element {
|
||||
unsigned short station;
|
||||
unsigned short stationlimit;
|
||||
unsigned short wtp;
|
||||
unsigned short wtplimit;
|
||||
unsigned char security;
|
||||
unsigned char rmacfield;
|
||||
unsigned char dtlspolicy;
|
||||
struct capwap_array* descsubelement;
|
||||
};
|
||||
|
||||
#define CAPWAP_ACDESC_SUBELEMENT_HARDWAREVERSION 4
|
||||
#define CAPWAP_ACDESC_SUBELEMENT_SOFTWAREVERSION 5
|
||||
#define CAPWAP_ACDESC_SUBELEMENT_MAXDATA 1024
|
||||
|
||||
struct capwap_acdescriptor_desc_subelement {
|
||||
unsigned long vendor;
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
char data[CAPWAP_ACDESC_SUBELEMENT_MAXDATA];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_acdescriptor_element_create(void* data, unsigned long length);
|
||||
int capwap_acdescriptor_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_acdescriptor_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACDESCRIPTION); \
|
||||
f->create(x, sizeof(struct capwap_acdescriptor_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__ */
|
103
src/common/capwap_element_acipv4list.c
Normal file
103
src/common/capwap_element_acipv4list.c
Normal file
@ -0,0 +1,103 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address[] |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 2 for AC IPv4 List
|
||||
Length: >= 4
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_acipv4list_raw_element {
|
||||
unsigned long address;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_acipv4list_element_create(void* data, unsigned long datalength) {
|
||||
int i;
|
||||
int items;
|
||||
unsigned short sizeitems;
|
||||
struct capwap_message_element* element;
|
||||
capwap_acipv4list_element_array* dataarray = (capwap_acipv4list_element_array*)data;
|
||||
struct capwap_acipv4list_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(capwap_acipv4list_element_array));
|
||||
|
||||
items = min(dataarray->count, CAPWAP_ACIPV4LIST_MAX_ELEMENTS);
|
||||
|
||||
/* Alloc block of memory */
|
||||
sizeitems = sizeof(struct capwap_acipv4list_raw_element) * items;
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeitems);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeitems);
|
||||
element->type = htons(CAPWAP_ELEMENT_ACIPV4LIST);
|
||||
element->length = htons(sizeitems);
|
||||
|
||||
dataraw = (struct capwap_acipv4list_raw_element*)element->data;
|
||||
for (i = 0; i < items; i++) {
|
||||
struct capwap_acipv4list_element* dataelement = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(dataarray, i);
|
||||
dataraw->address = dataelement->address.s_addr;
|
||||
|
||||
/* Next raw item */
|
||||
dataraw++;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_acipv4list_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_acipv4list_element_parsing(struct capwap_message_element* element) {
|
||||
int i;
|
||||
int items;
|
||||
unsigned short length;
|
||||
capwap_acipv4list_element_array* data;
|
||||
struct capwap_acipv4list_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACIPV4LIST);
|
||||
|
||||
length = ntohs(element->length);
|
||||
if ((length > 0) && ((length % sizeof(struct capwap_acipv4list_raw_element)) != 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
items = length / sizeof(struct capwap_acipv4list_raw_element);
|
||||
data = (capwap_acipv4list_element_array*)capwap_array_create(sizeof(struct capwap_acipv4list_element), items);
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_acipv4list_raw_element*)element->data;
|
||||
for (i = 0; i < items; i++) {
|
||||
struct capwap_acipv4list_element* dataelement = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(data, i);
|
||||
dataelement->address.s_addr = dataraw->address;
|
||||
|
||||
/* Next raw item */
|
||||
dataraw++;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_acipv4list_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_array_free((capwap_acipv4list_element_array*)data);
|
||||
}
|
25
src/common/capwap_element_acipv4list.h
Normal file
25
src/common/capwap_element_acipv4list.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__
|
||||
#define __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_ACIPV4LIST 2
|
||||
|
||||
#define CAPWAP_ACIPV4LIST_MAX_ELEMENTS 1024
|
||||
|
||||
typedef struct capwap_array capwap_acipv4list_element_array;
|
||||
struct capwap_acipv4list_element {
|
||||
struct in_addr address;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_acipv4list_element_create(void* data, unsigned long datalength);
|
||||
int capwap_acipv4list_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_acipv4list_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_acipv4list_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_ACIPV4LIST_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACIPV4LIST); \
|
||||
f->create(x, sizeof(capwap_acipv4list_element_array)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__ */
|
109
src/common/capwap_element_acipv6list.c
Normal file
109
src/common/capwap_element_acipv6list.c
Normal file
@ -0,0 +1,109 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 3 for AC IPV6 List
|
||||
Length: >= 16
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_acipv6list_raw_element {
|
||||
unsigned long address[4];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_acipv6list_element_create(void* data, unsigned long datalength) {
|
||||
int i;
|
||||
int items;
|
||||
unsigned short sizeitems;
|
||||
struct capwap_message_element* element;
|
||||
capwap_acipv6list_element_array* dataarray = (capwap_acipv6list_element_array*)data;
|
||||
struct capwap_acipv6list_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(capwap_acipv6list_element_array));
|
||||
|
||||
items = min(dataarray->count, CAPWAP_ACIPV6LIST_MAX_ELEMENTS);
|
||||
|
||||
/* Alloc block of memory */
|
||||
sizeitems = sizeof(struct capwap_acipv6list_raw_element) * items;
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeitems);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeitems);
|
||||
element->type = htons(CAPWAP_ELEMENT_ACIPV6LIST);
|
||||
element->length = htons(sizeitems);
|
||||
|
||||
dataraw = (struct capwap_acipv6list_raw_element*)element->data;
|
||||
for (i = 0; i < items; i++) {
|
||||
struct capwap_acipv6list_element* dataelement = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(dataarray, i);
|
||||
memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4);
|
||||
|
||||
/* Next raw item */
|
||||
dataraw++;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_acipv6list_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_acipv6list_element_parsing(struct capwap_message_element* element) {
|
||||
int i;
|
||||
int items;
|
||||
unsigned short length;
|
||||
capwap_acipv6list_element_array* data;
|
||||
struct capwap_acipv6list_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACIPV6LIST);
|
||||
|
||||
length = ntohs(element->length);
|
||||
if ((length > 0) && ((length % sizeof(struct capwap_acipv6list_raw_element)) != 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
items = length / sizeof(struct capwap_acipv6list_raw_element);
|
||||
data = (capwap_acipv6list_element_array*)capwap_array_create(sizeof(struct capwap_acipv6list_element), items);
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_acipv6list_raw_element*)element->data;
|
||||
for (i = 0; i < items; i++) {
|
||||
struct capwap_acipv6list_element* dataelement = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(data, i);
|
||||
memcpy(dataelement->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4);
|
||||
|
||||
/* Next raw item */
|
||||
dataraw++;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_acipv6list_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_array_free((capwap_acipv6list_element_array*)data);
|
||||
}
|
25
src/common/capwap_element_acipv6list.h
Normal file
25
src/common/capwap_element_acipv6list.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__
|
||||
#define __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_ACIPV6LIST 3
|
||||
|
||||
#define CAPWAP_ACIPV6LIST_MAX_ELEMENTS 1024
|
||||
|
||||
typedef struct capwap_array capwap_acipv6list_element_array;
|
||||
struct capwap_acipv6list_element {
|
||||
struct in6_addr address;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_acipv6list_element_create(void* data, unsigned long datalength);
|
||||
int capwap_acipv6list_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_acipv6list_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_acipv6list_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_ACIPV6LIST_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACIPV6LIST); \
|
||||
f->create(x, sizeof(capwap_acipv6list_element_array)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__ */
|
86
src/common/capwap_element_acname.c
Normal file
86
src/common/capwap_element_acname.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Name ...
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 4 for AC Name
|
||||
Length: >= 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_acname_raw_element {
|
||||
char name[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_acname_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short namelength;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_acname_raw_element* dataraw;
|
||||
struct capwap_acname_element* dataelement = (struct capwap_acname_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_acname_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
namelength = strlen(dataelement->name);
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + namelength);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + namelength);
|
||||
element->type = htons(CAPWAP_ELEMENT_ACNAME);
|
||||
element->length = htons(namelength);
|
||||
|
||||
dataraw = (struct capwap_acname_raw_element*)element->data;
|
||||
memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_acname_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_acname_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short namelength;
|
||||
struct capwap_acname_element* data;
|
||||
struct capwap_acname_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACNAME);
|
||||
|
||||
namelength = ntohs(element->length);
|
||||
if (!namelength || (namelength > CAPWAP_ACNAME_MAXLENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_acname_raw_element*)element->data;
|
||||
data = (struct capwap_acname_element*)capwap_alloc(sizeof(struct capwap_acname_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
memcpy(&data->name[0], &dataraw->name[0], namelength);
|
||||
data->name[namelength] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_acname_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_acname.h
Normal file
24
src/common/capwap_element_acname.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_ACNAME_HEADER__
|
||||
#define __CAPWAP_ELEMENT_ACNAME_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_ACNAME 4
|
||||
|
||||
#define CAPWAP_ACNAME_MAXLENGTH 512
|
||||
|
||||
struct capwap_acname_element {
|
||||
char name[CAPWAP_ACNAME_MAXLENGTH + 1];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_acname_element_create(void* data, unsigned long datalength);
|
||||
int capwap_acname_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_acname_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_acname_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_ACNAME_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAME); \
|
||||
f->create(x, sizeof(struct capwap_acname_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_ACNAME_HEADER__ */
|
91
src/common/capwap_element_acnamepriority.c
Normal file
91
src/common/capwap_element_acnamepriority.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Priority | AC Name...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 5 for AC Name with Priority
|
||||
Length: >= 2
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_acnamepriority_raw_element {
|
||||
unsigned char priority;
|
||||
char name[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_acnamepriority_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short namelength;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_acnamepriority_raw_element* dataraw;
|
||||
struct capwap_acnamepriority_element* dataelement = (struct capwap_acnamepriority_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_acnamepriority_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
namelength = strlen(dataelement->name);
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_acnamepriority_raw_element) + namelength);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_acnamepriority_raw_element) + namelength);
|
||||
element->type = htons(CAPWAP_ELEMENT_ACNAMEPRIORITY);
|
||||
element->length = htons(sizeof(struct capwap_acnamepriority_raw_element) + namelength);
|
||||
|
||||
dataraw = (struct capwap_acnamepriority_raw_element*)element->data;
|
||||
dataraw->priority = dataelement->priority;
|
||||
memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_acnamepriority_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_acnamepriority_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short namelength;
|
||||
struct capwap_acnamepriority_element* data;
|
||||
struct capwap_acnamepriority_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACNAMEPRIORITY);
|
||||
|
||||
namelength = ntohs(element->length) - sizeof(struct capwap_acnamepriority_raw_element);
|
||||
if (!namelength || (namelength > CAPWAP_ACNAMEPRIORITY_MAXLENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_acnamepriority_raw_element*)element->data;
|
||||
data = (struct capwap_acnamepriority_element*)capwap_alloc(sizeof(struct capwap_acnamepriority_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->priority = dataraw->priority;
|
||||
memcpy(&data->name[0], &dataraw->name[0], namelength);
|
||||
data->name[namelength] = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_acnamepriority_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
25
src/common/capwap_element_acnamepriority.h
Normal file
25
src/common/capwap_element_acnamepriority.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__
|
||||
#define __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_ACNAMEPRIORITY 5
|
||||
|
||||
#define CAPWAP_ACNAMEPRIORITY_MAXLENGTH 512
|
||||
|
||||
struct capwap_acnamepriority_element {
|
||||
unsigned char priority;
|
||||
char name[CAPWAP_ACNAMEPRIORITY_MAXLENGTH + 1];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_acnamepriority_element_create(void* data, unsigned long datalength);
|
||||
int capwap_acnamepriority_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_acnamepriority_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_acnamepriority_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_ACNAMEPRIORITY_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAMEPRIORITY); \
|
||||
f->create(x, sizeof(struct capwap_acnamepriority_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__ */
|
88
src/common/capwap_element_controlipv4.c
Normal file
88
src/common/capwap_element_controlipv4.c
Normal file
@ -0,0 +1,88 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| WTP Count |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 10 for CAPWAP Control IPv4 Address
|
||||
Length: 6
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_controlipv4_raw_element {
|
||||
unsigned long address;
|
||||
unsigned short wtpcount;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_controlipv4_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_controlipv4_element* dataelement = (struct capwap_controlipv4_element*)data;
|
||||
struct capwap_controlipv4_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_controlipv4_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv4_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv4_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_CONTROLIPV4);
|
||||
element->length = htons(sizeof(struct capwap_controlipv4_raw_element));
|
||||
|
||||
dataraw = (struct capwap_controlipv4_raw_element*)element->data;
|
||||
dataraw->address = dataelement->address.s_addr;
|
||||
dataraw->wtpcount = htons(dataelement->wtpcount);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_controlipv4_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_controlipv4_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_controlipv4_element* data;
|
||||
struct capwap_controlipv4_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_CONTROLIPV4);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_controlipv4_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_controlipv4_element*)capwap_alloc(sizeof(struct capwap_controlipv4_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_controlipv4_raw_element*)element->data;
|
||||
data->address.s_addr = dataraw->address;
|
||||
data->wtpcount = ntohs(dataraw->wtpcount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_controlipv4_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
23
src/common/capwap_element_controlipv4.h
Normal file
23
src/common/capwap_element_controlipv4.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__
|
||||
#define __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_CONTROLIPV4 10
|
||||
|
||||
struct capwap_controlipv4_element {
|
||||
struct in_addr address;
|
||||
unsigned short wtpcount;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_controlipv4_element_create(void* data, unsigned long datalength);
|
||||
int capwap_controlipv4_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_controlipv4_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_controlipv4_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_CONTROLIPV4_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV4); \
|
||||
f->create(x, sizeof(struct capwap_controlipv4_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */
|
94
src/common/capwap_element_controlipv6.c
Normal file
94
src/common/capwap_element_controlipv6.c
Normal file
@ -0,0 +1,94 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| WTP Count |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 11 for CAPWAP Control IPv6 Address
|
||||
Length: 18
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_controlipv6_raw_element {
|
||||
unsigned long address[4];
|
||||
unsigned short wtpcount;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_controlipv6_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_controlipv6_element* dataelement = (struct capwap_controlipv6_element*)data;
|
||||
struct capwap_controlipv6_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_controlipv6_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv6_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv6_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_CONTROLIPV6);
|
||||
element->length = htons(sizeof(struct capwap_controlipv6_raw_element));
|
||||
|
||||
dataraw = (struct capwap_controlipv6_raw_element*)element->data;
|
||||
memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4);
|
||||
dataraw->wtpcount = htons(dataelement->wtpcount);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_controlipv6_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_controlipv6_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_controlipv6_element* data;
|
||||
struct capwap_controlipv6_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_CONTROLIPV6);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_controlipv6_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_controlipv6_element*)capwap_alloc(sizeof(struct capwap_controlipv6_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_controlipv6_raw_element*)element->data;
|
||||
memcpy(data->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4);
|
||||
data->wtpcount = ntohs(dataraw->wtpcount);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_controlipv6_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
23
src/common/capwap_element_controlipv6.h
Normal file
23
src/common/capwap_element_controlipv6.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __CAPWAP_ELEMENT_CONTROLIPV6_HEADER__
|
||||
#define __CAPWAP_ELEMENT_CONTROLIPV6_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_CONTROLIPV6 11
|
||||
|
||||
struct capwap_controlipv6_element {
|
||||
struct in6_addr address;
|
||||
unsigned short wtpcount;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_controlipv6_element_create(void* data, unsigned long datalength);
|
||||
int capwap_controlipv6_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_controlipv6_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_controlipv6_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_CONTROLIPV6_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV6); \
|
||||
f->create(x, sizeof(struct capwap_controlipv6_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */
|
86
src/common/capwap_element_decrypterrorreportperiod.c
Normal file
86
src/common/capwap_element_decrypterrorreportperiod.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Radio ID | Report Interval |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 16 for Decryption Error Report Period
|
||||
Length: 3
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_decrypterrorreportperiod_raw_element {
|
||||
unsigned char radioid;
|
||||
unsigned short interval;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_decrypterrorreportperiod_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_decrypterrorreportperiod_element* dataelement = (struct capwap_decrypterrorreportperiod_element*)data;
|
||||
struct capwap_decrypterrorreportperiod_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_decrypterrorreportperiod_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_decrypterrorreportperiod_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_decrypterrorreportperiod_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD);
|
||||
element->length = htons(sizeof(struct capwap_decrypterrorreportperiod_raw_element));
|
||||
|
||||
dataraw = (struct capwap_decrypterrorreportperiod_raw_element*)element->data;
|
||||
dataraw->radioid = dataelement->radioid;
|
||||
dataraw->interval = htons(dataelement->interval);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_decrypterrorreportperiod_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_decrypterrorreportperiod_element* data;
|
||||
struct capwap_decrypterrorreportperiod_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_decrypterrorreportperiod_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_decrypterrorreportperiod_element*)capwap_alloc(sizeof(struct capwap_decrypterrorreportperiod_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_decrypterrorreportperiod_raw_element*)element->data;
|
||||
data->radioid = dataraw->radioid;
|
||||
data->interval = ntohs(dataraw->interval);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_decrypterrorreportperiod_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
22
src/common/capwap_element_decrypterrorreportperiod.h
Normal file
22
src/common/capwap_element_decrypterrorreportperiod.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__
|
||||
#define __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD 16
|
||||
|
||||
struct capwap_decrypterrorreportperiod_element {
|
||||
unsigned char radioid;
|
||||
unsigned short interval;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_decrypterrorreportperiod_element_create(void* data, unsigned long length);
|
||||
int capwap_decrypterrorreportperiod_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_decrypterrorreportperiod_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD); \
|
||||
f->create(x, sizeof(struct capwap_decrypterrorreportperiod_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__ */
|
75
src/common/capwap_element_discoverytype.c
Normal file
75
src/common/capwap_element_discoverytype.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Discovery Type|
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 20 for Discovery Type
|
||||
Length: 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_discoverytype_raw_element {
|
||||
unsigned char type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_discoverytype_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_discoverytype_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_discoverytype_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_discoverytype_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_DISCOVERYTYPE);
|
||||
element->length = htons(sizeof(struct capwap_discoverytype_raw_element));
|
||||
((struct capwap_discoverytype_raw_element*)element->data)->type = ((struct capwap_discoverytype_element*)data)->type;
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_discoverytype_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_discoverytype_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_discoverytype_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_DISCOVERYTYPE);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_discoverytype_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_discoverytype_element*)capwap_alloc(sizeof(struct capwap_discoverytype_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->type = ((struct capwap_discoverytype_raw_element*)element->data)->type;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_discoverytype_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
28
src/common/capwap_element_discoverytype.h
Normal file
28
src/common/capwap_element_discoverytype.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE 20
|
||||
|
||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_UNKNOWN 0
|
||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_STATIC 1
|
||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_DHCP 2
|
||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_DNS 3
|
||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_ACREFERRAL 4
|
||||
|
||||
struct capwap_discoverytype_element {
|
||||
unsigned char type;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_discoverytype_element_create(void* data, unsigned long datalength);
|
||||
int capwap_discoverytype_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_discoverytype_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_discoverytype_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_DISCOVERYTYPE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_DISCOVERYTYPE); \
|
||||
f->create(x, sizeof(struct capwap_discoverytype_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__ */
|
77
src/common/capwap_element_ecnsupport.c
Normal file
77
src/common/capwap_element_ecnsupport.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| ECN Support |
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 53 for ECN Support
|
||||
Length: 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_ecnsupport_raw_element {
|
||||
char flag;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_ecnsupport_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_ecnsupport_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_ecnsupport_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_ecnsupport_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_ECNSUPPORT);
|
||||
element->length = htons(sizeof(struct capwap_ecnsupport_raw_element));
|
||||
|
||||
((struct capwap_ecnsupport_raw_element*)element->data)->flag = ((struct capwap_ecnsupport_element*)data)->flag;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_ecnsupport_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_ecnsupport_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ECNSUPPORT);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_ecnsupport_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_ecnsupport_element*)capwap_alloc(sizeof(struct capwap_ecnsupport_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->flag = ((struct capwap_ecnsupport_raw_element*)element->data)->flag;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_ecnsupport_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_ecnsupport.h
Normal file
24
src/common/capwap_element_ecnsupport.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__
|
||||
#define __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_ECNSUPPORT 53
|
||||
|
||||
struct capwap_ecnsupport_element {
|
||||
char flag;
|
||||
};
|
||||
|
||||
#define CAPWAP_LIMITED_ECN_SUPPORT 0
|
||||
#define CAPWAP_FULL_ECN_SUPPORT 1
|
||||
|
||||
struct capwap_message_element* capwap_ecnsupport_element_create(void* data, unsigned long length);
|
||||
int capwap_ecnsupport_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_ecnsupport_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_ECNSUPPORT_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ECNSUPPORT); \
|
||||
f->create(x, sizeof(struct capwap_ecnsupport_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__ */
|
77
src/common/capwap_element_idletimeout.c
Normal file
77
src/common/capwap_element_idletimeout.c
Normal file
@ -0,0 +1,77 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Timeout |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 23 for Idle Timeout
|
||||
Length: 4
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_idletimeout_raw_element {
|
||||
unsigned long timeout;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_idletimeout_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_idletimeout_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_idletimeout_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_idletimeout_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_IDLETIMEOUT);
|
||||
element->length = htons(sizeof(struct capwap_idletimeout_raw_element));
|
||||
|
||||
((struct capwap_idletimeout_raw_element*)element->data)->timeout = htonl(((struct capwap_idletimeout_element*)data)->timeout);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_idletimeout_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_idletimeout_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_idletimeout_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_IDLETIMEOUT);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_idletimeout_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_idletimeout_element*)capwap_alloc(sizeof(struct capwap_idletimeout_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->timeout = ntohl(((struct capwap_idletimeout_raw_element*)element->data)->timeout);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_idletimeout_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
21
src/common/capwap_element_idletimeout.h
Normal file
21
src/common/capwap_element_idletimeout.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__
|
||||
#define __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_IDLETIMEOUT 23
|
||||
|
||||
struct capwap_idletimeout_element {
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_idletimeout_element_create(void* data, unsigned long length);
|
||||
int capwap_idletimeout_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_idletimeout_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_idletimeout_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_IDLETIMEOUT); \
|
||||
f->create(x, sizeof(struct capwap_idletimeout_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__ */
|
93
src/common/capwap_element_imageidentifier.c
Normal file
93
src/common/capwap_element_imageidentifier.c
Normal file
@ -0,0 +1,93 @@
|
||||
#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 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Data...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 25 for Image Identifier
|
||||
Length: >= 5
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_imageidentifier_raw_element {
|
||||
unsigned long vendor;
|
||||
char name[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_imageidentifier_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short namelength;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_imageidentifier_raw_element* dataraw;
|
||||
struct capwap_imageidentifier_element* dataelement = (struct capwap_imageidentifier_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_imageidentifier_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
namelength = strlen(dataelement->name);
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_imageidentifier_raw_element) + namelength);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_imageidentifier_raw_element) + namelength);
|
||||
element->type = htons(CAPWAP_ELEMENT_IMAGEIDENTIFIER);
|
||||
element->length = htons(sizeof(struct capwap_imageidentifier_raw_element) + namelength);
|
||||
|
||||
dataraw = (struct capwap_imageidentifier_raw_element*)element->data;
|
||||
dataraw->vendor = htonl(dataelement->vendor);
|
||||
memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_imageidentifier_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_imageidentifier_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short namelength;
|
||||
struct capwap_imageidentifier_element* data;
|
||||
struct capwap_imageidentifier_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_IMAGEIDENTIFIER);
|
||||
|
||||
namelength = ntohs(element->length) - sizeof(struct capwap_imageidentifier_raw_element);
|
||||
if (!namelength || (namelength > CAPWAP_IMAGEIDENTIFIER_MAXLENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_imageidentifier_raw_element*)element->data;
|
||||
data = (struct capwap_imageidentifier_element*)capwap_alloc(sizeof(struct capwap_imageidentifier_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->vendor = ntohl(dataraw->vendor);
|
||||
memcpy(&data->name[0], &dataraw->name[0], namelength);
|
||||
data->name[namelength] = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_imageidentifier_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
25
src/common/capwap_element_imageidentifier.h
Normal file
25
src/common/capwap_element_imageidentifier.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__
|
||||
#define __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_IMAGEIDENTIFIER 25
|
||||
|
||||
#define CAPWAP_IMAGEIDENTIFIER_MAXLENGTH 1024
|
||||
|
||||
struct capwap_imageidentifier_element {
|
||||
unsigned long vendor;
|
||||
char name[CAPWAP_IMAGEIDENTIFIER_MAXLENGTH + 1];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_imageidentifier_element_create(void* data, unsigned long datalength);
|
||||
int capwap_imageidentifier_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_imageidentifier_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_imageidentifier_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_IMAGEIDENTIFIER); \
|
||||
f->create(x, sizeof(struct capwap_imageidentifier_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__ */
|
83
src/common/capwap_element_localipv4.c
Normal file
83
src/common/capwap_element_localipv4.c
Normal file
@ -0,0 +1,83 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 30 for CAPWAP Local IPv4 Address
|
||||
Length: 4
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_localipv4_raw_element {
|
||||
unsigned long address;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_localipv4_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_localipv4_element* dataelement = (struct capwap_localipv4_element*)data;
|
||||
struct capwap_localipv4_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_localipv4_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv4_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv4_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_LOCALIPV4);
|
||||
element->length = htons(sizeof(struct capwap_localipv4_raw_element));
|
||||
|
||||
dataraw = (struct capwap_localipv4_raw_element*)element->data;
|
||||
dataraw->address = dataelement->address.s_addr;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_localipv4_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_localipv4_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_localipv4_element* data;
|
||||
struct capwap_localipv4_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCALIPV4);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_localipv4_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_localipv4_element*)capwap_alloc(sizeof(struct capwap_localipv4_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_localipv4_raw_element*)element->data;
|
||||
data->address.s_addr = dataraw->address;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_localipv4_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
22
src/common/capwap_element_localipv4.h
Normal file
22
src/common/capwap_element_localipv4.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __CAPWAP_ELEMENT_LOCALIPV4_HEADER__
|
||||
#define __CAPWAP_ELEMENT_LOCALIPV4_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_LOCALIPV4 30
|
||||
|
||||
struct capwap_localipv4_element {
|
||||
struct in_addr address;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_localipv4_element_create(void* data, unsigned long datalength);
|
||||
int capwap_localipv4_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_localipv4_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_localipv4_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_LOCALIPV4_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV4); \
|
||||
f->create(x, sizeof(struct capwap_localipv4_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_LOCALIPV4_HEADER__ */
|
89
src/common/capwap_element_localipv6.c
Normal file
89
src/common/capwap_element_localipv6.c
Normal file
@ -0,0 +1,89 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 50 for CAPWAP Local IPv6 Address
|
||||
Length: 16
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_localipv6_raw_element {
|
||||
unsigned long address[4];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_localipv6_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_localipv6_element* dataelement = (struct capwap_localipv6_element*)data;
|
||||
struct capwap_localipv6_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_localipv6_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv6_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv6_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_LOCALIPV6);
|
||||
element->length = htons(sizeof(struct capwap_localipv6_raw_element));
|
||||
|
||||
dataraw = (struct capwap_localipv6_raw_element*)element->data;
|
||||
memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_localipv6_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_localipv6_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_localipv6_element* data;
|
||||
struct capwap_localipv6_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCALIPV6);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_localipv6_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_localipv6_element*)capwap_alloc(sizeof(struct capwap_localipv6_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_localipv6_raw_element*)element->data;
|
||||
memcpy(data->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_localipv6_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
22
src/common/capwap_element_localipv6.h
Normal file
22
src/common/capwap_element_localipv6.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __CAPWAP_ELEMENT_LOCALIPV6_HEADER__
|
||||
#define __CAPWAP_ELEMENT_LOCALIPV6_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_LOCALIPV6 50
|
||||
|
||||
struct capwap_localipv6_element {
|
||||
struct in6_addr address;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_localipv6_element_create(void* data, unsigned long datalength);
|
||||
int capwap_localipv6_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_localipv6_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_localipv6_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_LOCALIPV6_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV6); \
|
||||
f->create(x, sizeof(struct capwap_localipv6_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */
|
86
src/common/capwap_element_location.c
Normal file
86
src/common/capwap_element_location.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Location ...
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 28 for Location Data
|
||||
Length: >= 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_location_raw_element {
|
||||
char value[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_location_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short namelength;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_location_raw_element* dataraw;
|
||||
struct capwap_location_element* dataelement = (struct capwap_location_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_location_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
namelength = strlen(dataelement->value);
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + namelength);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + namelength);
|
||||
element->type = htons(CAPWAP_ELEMENT_LOCATION);
|
||||
element->length = htons(namelength);
|
||||
|
||||
dataraw = (struct capwap_location_raw_element*)element->data;
|
||||
memcpy(&dataraw->value[0], &dataelement->value[0], namelength);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_location_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_location_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short namelength;
|
||||
struct capwap_location_element* data;
|
||||
struct capwap_location_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCATION);
|
||||
|
||||
namelength = ntohs(element->length);
|
||||
if (!namelength || (namelength > CAPWAP_LOCATION_MAXLENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_location_raw_element*)element->data;
|
||||
data = (struct capwap_location_element*)capwap_alloc(sizeof(struct capwap_location_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
memcpy(&data->value[0], &dataraw->value[0], namelength);
|
||||
data->value[namelength] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_location_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_location.h
Normal file
24
src/common/capwap_element_location.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_LOCATION_HEADER__
|
||||
#define __CAPWAP_ELEMENT_LOCATION_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_LOCATION 28
|
||||
|
||||
#define CAPWAP_LOCATION_MAXLENGTH 1024
|
||||
|
||||
struct capwap_location_element {
|
||||
char value[CAPWAP_LOCATION_MAXLENGTH + 1];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_location_element_create(void* data, unsigned long datalength);
|
||||
int capwap_location_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_location_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_location_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_LOCATION_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCATION); \
|
||||
f->create(x, sizeof(struct capwap_location_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_LOCATION_HEADER__ */
|
77
src/common/capwap_element_maximumlength.c
Normal file
77
src/common/capwap_element_maximumlength.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Maximum Message Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 29 for Maximum Message Length
|
||||
Length: 2
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_maximumlength_raw_element {
|
||||
unsigned short length;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_maximumlength_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_maximumlength_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_maximumlength_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_maximumlength_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_MAXIMUMLENGTH);
|
||||
element->length = htons(sizeof(struct capwap_maximumlength_raw_element));
|
||||
|
||||
((struct capwap_maximumlength_raw_element*)element->data)->length = htons(((struct capwap_maximumlength_element*)data)->length);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_maximumlength_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_maximumlength_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_maximumlength_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_MAXIMUMLENGTH);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_maximumlength_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_maximumlength_element*)capwap_alloc(sizeof(struct capwap_maximumlength_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->length = ntohs(((struct capwap_maximumlength_raw_element*)element->data)->length);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_maximumlength_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
21
src/common/capwap_element_maximumlength.h
Normal file
21
src/common/capwap_element_maximumlength.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__
|
||||
#define __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_MAXIMUMLENGTH 29
|
||||
|
||||
struct capwap_maximumlength_element {
|
||||
unsigned short length;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_maximumlength_element_create(void* data, unsigned long length);
|
||||
int capwap_maximumlength_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_maximumlength_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_maximumlength_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_MAXIMUMLENGTH_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_MAXIMUMLENGTH); \
|
||||
f->create(x, sizeof(struct capwap_maximumlength_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__ */
|
72
src/common/capwap_element_mtudiscovery.c
Normal file
72
src/common/capwap_element_mtudiscovery.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Padding...
|
||||
+-+-+-+-+-+-+-+-
|
||||
|
||||
Type: 52 for MTU Discovery Padding
|
||||
Length: variable
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_mtudiscovery_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_mtudiscovery_element* dataelement = (struct capwap_mtudiscovery_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_mtudiscovery_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + dataelement->length);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_MTUDISCOVERY);
|
||||
element->length = htons(dataelement->length);
|
||||
|
||||
if (dataelement->length > 0) {
|
||||
memset(element->data, 0xff, dataelement->length);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_mtudiscovery_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_mtudiscovery_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_mtudiscovery_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_MTUDISCOVERY);
|
||||
|
||||
/* */
|
||||
data = (struct capwap_mtudiscovery_element*)capwap_alloc(sizeof(struct capwap_mtudiscovery_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->length = ntohs(element->length);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_mtudiscovery_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
21
src/common/capwap_element_mtudiscovery.h
Normal file
21
src/common/capwap_element_mtudiscovery.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__
|
||||
#define __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_MTUDISCOVERY 52
|
||||
|
||||
struct capwap_mtudiscovery_element {
|
||||
unsigned short length;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_mtudiscovery_element_create(void* data, unsigned long length);
|
||||
int capwap_mtudiscovery_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_mtudiscovery_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_mtudiscovery_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_MTUDISCOVERY_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_MTUDISCOVERY); \
|
||||
f->create(x, sizeof(struct capwap_mtudiscovery_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__ */
|
86
src/common/capwap_element_radioadmstate.c
Normal file
86
src/common/capwap_element_radioadmstate.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Radio ID | Admin State |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 31 for Radio Administrative State
|
||||
Length: 2
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_radioadmstate_raw_element {
|
||||
unsigned char radioid;
|
||||
unsigned char state;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_radioadmstate_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_radioadmstate_element* dataelement = (struct capwap_radioadmstate_element*)data;
|
||||
struct capwap_radioadmstate_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_radioadmstate_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_radioadmstate_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_radioadmstate_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_RADIOADMSTATE);
|
||||
element->length = htons(sizeof(struct capwap_radioadmstate_raw_element));
|
||||
|
||||
dataraw = (struct capwap_radioadmstate_raw_element*)element->data;
|
||||
dataraw->radioid = dataelement->radioid;
|
||||
dataraw->state = dataelement->state;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_radioadmstate_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_radioadmstate_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_radioadmstate_element* data;
|
||||
struct capwap_radioadmstate_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RADIOADMSTATE);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_radioadmstate_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_radioadmstate_element*)capwap_alloc(sizeof(struct capwap_radioadmstate_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_radioadmstate_raw_element*)element->data;
|
||||
data->radioid = dataraw->radioid;
|
||||
data->state = dataraw->state;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_radioadmstate_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
25
src/common/capwap_element_radioadmstate.h
Normal file
25
src/common/capwap_element_radioadmstate.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_RADIOADMSTATE 31
|
||||
|
||||
struct capwap_radioadmstate_element {
|
||||
unsigned char radioid;
|
||||
unsigned char state;
|
||||
};
|
||||
|
||||
#define CAPWAP_RADIO_ADMIN_STATE_ENABLED 1
|
||||
#define CAPWAP_RADIO_ADMIN_STATE_DISABLED 2
|
||||
|
||||
struct capwap_message_element* capwap_radioadmstate_element_create(void* data, unsigned long length);
|
||||
int capwap_radioadmstate_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_radioadmstate_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_radioadmstate_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_RADIOADMSTATE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOADMSTATE); \
|
||||
f->create(x, sizeof(struct capwap_radioadmstate_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__ */
|
89
src/common/capwap_element_radiooprstate.c
Normal file
89
src/common/capwap_element_radiooprstate.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Radio ID | State | Cause |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 32 for Radio Operational State
|
||||
Length: 3
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_radiooprstate_raw_element {
|
||||
unsigned char radioid;
|
||||
unsigned char state;
|
||||
unsigned char cause;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_radiooprstate_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_radiooprstate_element* dataelement = (struct capwap_radiooprstate_element*)data;
|
||||
struct capwap_radiooprstate_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_radiooprstate_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_radiooprstate_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_radiooprstate_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_RADIOOPRSTATE);
|
||||
element->length = htons(sizeof(struct capwap_radiooprstate_raw_element));
|
||||
|
||||
dataraw = (struct capwap_radiooprstate_raw_element*)element->data;
|
||||
dataraw->radioid = dataelement->radioid;
|
||||
dataraw->state = dataelement->state;
|
||||
dataraw->cause = dataelement->cause;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_radiooprstate_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_radiooprstate_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_radiooprstate_element* data;
|
||||
struct capwap_radiooprstate_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RADIOOPRSTATE);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_radiooprstate_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_radiooprstate_element*)capwap_alloc(sizeof(struct capwap_radiooprstate_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_radiooprstate_raw_element*)element->data;
|
||||
data->radioid = dataraw->radioid;
|
||||
data->state = dataraw->state;
|
||||
data->cause = dataraw->cause;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_radiooprstate_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
31
src/common/capwap_element_radiooprstate.h
Normal file
31
src/common/capwap_element_radiooprstate.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_RADIOOPRSTATE 32
|
||||
|
||||
struct capwap_radiooprstate_element {
|
||||
unsigned char radioid;
|
||||
unsigned char state;
|
||||
unsigned char cause;
|
||||
};
|
||||
|
||||
#define CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED 1
|
||||
#define CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED 2
|
||||
|
||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_NORMAL 0
|
||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_RADIOFAILURE 1
|
||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE 2
|
||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET 3
|
||||
|
||||
struct capwap_message_element* capwap_radiooprstate_element_create(void* data, unsigned long length);
|
||||
int capwap_radiooprstate_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_radiooprstate_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_radiooprstate_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOOPRSTATE); \
|
||||
f->create(x, sizeof(struct capwap_radiooprstate_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__ */
|
77
src/common/capwap_element_resultcode.c
Normal file
77
src/common/capwap_element_resultcode.c
Normal file
@ -0,0 +1,77 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Result Code |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 33 for Result Code
|
||||
Length: 4
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_resultcode_raw_element {
|
||||
unsigned long code;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_resultcode_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_resultcode_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_resultcode_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_resultcode_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_RESULTCODE);
|
||||
element->length = htons(sizeof(struct capwap_resultcode_raw_element));
|
||||
|
||||
((struct capwap_resultcode_raw_element*)element->data)->code = htonl(((struct capwap_resultcode_element*)data)->code);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_resultcode_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_resultcode_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_resultcode_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RESULTCODE);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_resultcode_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_resultcode_element*)capwap_alloc(sizeof(struct capwap_resultcode_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->code = ntohl(((struct capwap_resultcode_raw_element*)element->data)->code);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_resultcode_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
45
src/common/capwap_element_resultcode.h
Normal file
45
src/common/capwap_element_resultcode.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef __CAPWAP_ELEMENT_RESULTCODE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_RESULTCODE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_RESULTCODE 33
|
||||
|
||||
#define CAPWAP_RESULTCODE_SUCCESS 0
|
||||
#define CAPWAP_RESULTCODE_FAILURE 1
|
||||
#define CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED 2
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_UNSPECIFIED 3
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_RESOURCE_DEPLETION 4
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE 5
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_INCORRECT_DATA 6
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE 7
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_WTP_HARDWARE_NOT_SUPPORTED 8
|
||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED 9
|
||||
#define CAPWAP_RESULTCODE_RESET_FAILURE_UNABLE_TO_RESET 10
|
||||
#define CAPWAP_RESULTCODE_RESET_FAILURE_FIRMWARE_WRITE_ERROR 11
|
||||
#define CAPWAP_RESULTCODE_CONF_FAILURE_SERVICE_PROVIDED_ANYHOW 12
|
||||
#define CAPWAP_RESULTCODE_CONF_FAILURE_SERVICE_NOT_PROVIDED 13
|
||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_INVALID_CHECKSUM 14
|
||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_INVALID_DATA_LENGTH 15
|
||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_OTHER_ERROR 16
|
||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_IMAGE_ALREADY_PRESENT 17
|
||||
#define CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE 18
|
||||
#define CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST 19
|
||||
#define CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT 20
|
||||
#define CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT 21
|
||||
#define CAPWAP_RESULTCODE_DATA_TRANSFER_ERROR 22
|
||||
|
||||
struct capwap_resultcode_element {
|
||||
unsigned long code;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_resultcode_element_create(void* data, unsigned long length);
|
||||
int capwap_resultcode_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_resultcode_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_resultcode_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_RESULTCODE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE); \
|
||||
f->create(x, sizeof(struct capwap_resultcode_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_RESULTCODE_HEADER__ */
|
93
src/common/capwap_element_returnedmessage.c
Normal file
93
src/common/capwap_element_returnedmessage.c
Normal file
@ -0,0 +1,93 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Reason | Length | Message Element...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 34 for Returned Message Element
|
||||
Length: >= 6
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_returnedmessage_raw_element {
|
||||
unsigned char reason;
|
||||
unsigned char length;
|
||||
char message[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_returnedmessage_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short length;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_returnedmessage_raw_element* dataraw;
|
||||
struct capwap_returnedmessage_element* dataelement = (struct capwap_returnedmessage_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_returnedmessage_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
length = sizeof(struct capwap_returnedmessage_raw_element) + dataelement->length;
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + length);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_RETURNEDMESSAGE);
|
||||
element->length = htons(length);
|
||||
|
||||
dataraw = (struct capwap_returnedmessage_raw_element*)element->data;
|
||||
dataraw->reason = dataelement->reason;
|
||||
dataraw->length = dataelement->length;
|
||||
memcpy(&dataraw->message[0], &dataelement->message[0], dataelement->length);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_returnedmessage_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_returnedmessage_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short length;
|
||||
struct capwap_returnedmessage_element* data;
|
||||
struct capwap_returnedmessage_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RETURNEDMESSAGE);
|
||||
|
||||
length = ntohs(element->length) - sizeof(struct capwap_returnedmessage_raw_element);
|
||||
if (length > CAPWAP_RETURNED_MESSAGE_MAX_LENGTH) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_returnedmessage_raw_element*)element->data;
|
||||
data = (struct capwap_returnedmessage_element*)capwap_alloc(sizeof(struct capwap_returnedmessage_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->reason = dataraw->reason;
|
||||
data->length = dataraw->length;
|
||||
memcpy(&data->message[0], &dataraw->message[0], dataraw->length);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_returnedmessage_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
30
src/common/capwap_element_returnedmessage.h
Normal file
30
src/common/capwap_element_returnedmessage.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_RETURNEDMESSAGE 34
|
||||
|
||||
#define CAPWAP_REASON_UNKNOWN_MESSAGE_ELEMENT 1
|
||||
#define CAPWAP_REASON_UNSUPPORTED_MESSAGE_ELEMENT 2
|
||||
#define CAPWAP_REASON_UNKNOWN_MESSAGE_ELEMENT_VALUE 3
|
||||
#define CAPWAP_REASON_UNSUPPORTED_MESSAGE_ELEMENT_VALUE 4
|
||||
|
||||
#define CAPWAP_RETURNED_MESSAGE_MAX_LENGTH 255
|
||||
|
||||
struct capwap_returnedmessage_element {
|
||||
unsigned char reason;
|
||||
unsigned char length;
|
||||
char message[CAPWAP_RETURNED_MESSAGE_MAX_LENGTH];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_returnedmessage_element_create(void* data, unsigned long length);
|
||||
int capwap_returnedmessage_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_returnedmessage_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_returnedmessage_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RETURNEDMESSAGE); \
|
||||
f->create(x, sizeof(struct capwap_returnedmessage_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__ */
|
115
src/common/capwap_element_sessionid.c
Normal file
115
src/common/capwap_element_sessionid.c
Normal file
@ -0,0 +1,115 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Session ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Session ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Session ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Session ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
|
||||
Type: 35 for Session ID
|
||||
Length: 16
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_sessionid_raw_element {
|
||||
unsigned char id[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_sessionid_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_sessionid_raw_element* dataraw;
|
||||
struct capwap_sessionid_element* dataelement = (struct capwap_sessionid_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_sessionid_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_sessionid_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_sessionid_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_SESSIONID);
|
||||
element->length = htons(sizeof(struct capwap_sessionid_element));
|
||||
|
||||
dataraw = (struct capwap_sessionid_raw_element*)element->data;
|
||||
memcpy(&dataraw->id[0], &dataelement->id[0], sizeof(unsigned char) * 16);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_sessionid_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_sessionid_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_sessionid_element* data;
|
||||
struct capwap_sessionid_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_SESSIONID);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_sessionid_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_sessionid_raw_element*)element->data;
|
||||
data = (struct capwap_sessionid_element*)capwap_alloc(sizeof(struct capwap_sessionid_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
memcpy(&data->id[0], &dataraw->id[0], sizeof(unsigned char) * 16);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_sessionid_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_sessionid_generate(struct capwap_sessionid_element* session) {
|
||||
int i;
|
||||
|
||||
ASSERT(session != NULL);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
session->id[i] = (unsigned char)capwap_get_rand(256);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_sessionid_printf(struct capwap_sessionid_element* session, char* string) {
|
||||
int i;
|
||||
char* pos = string;
|
||||
|
||||
ASSERT(session != NULL);
|
||||
ASSERT(string != NULL);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
sprintf(pos, "%02x", session->id[i]);
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
*pos = 0;
|
||||
}
|
24
src/common/capwap_element_sessionid.h
Normal file
24
src/common/capwap_element_sessionid.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_SESSIONID_HEADER__
|
||||
#define __CAPWAP_ELEMENT_SESSIONID_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_SESSIONID 35
|
||||
|
||||
struct capwap_sessionid_element {
|
||||
unsigned char id[16];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_sessionid_element_create(void* data, unsigned long datalength);
|
||||
int capwap_sessionid_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_sessionid_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_sessionid_element_free(void* data);
|
||||
|
||||
void capwap_sessionid_generate(struct capwap_sessionid_element* session);
|
||||
void capwap_sessionid_printf(struct capwap_sessionid_element* session, char* string);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_SESSIONID_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_SESSIONID); \
|
||||
f->create(x, sizeof(struct capwap_sessionid_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_SESSIONID_HEADER__ */
|
77
src/common/capwap_element_statisticstimer.c
Normal file
77
src/common/capwap_element_statisticstimer.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Statistics Timer |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 36 for Statistics Timer
|
||||
Length: 2
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_statisticstimer_raw_element {
|
||||
unsigned short timer;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_statisticstimer_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_statisticstimer_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_statisticstimer_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_statisticstimer_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_STATISTICSTIMER);
|
||||
element->length = htons(sizeof(struct capwap_statisticstimer_raw_element));
|
||||
|
||||
((struct capwap_statisticstimer_raw_element*)element->data)->timer = htons(((struct capwap_statisticstimer_element*)data)->timer);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_statisticstimer_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_statisticstimer_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_statisticstimer_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_STATISTICSTIMER);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_statisticstimer_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_statisticstimer_element*)capwap_alloc(sizeof(struct capwap_statisticstimer_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->timer = ntohs(((struct capwap_statisticstimer_raw_element*)element->data)->timer);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_statisticstimer_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
21
src/common/capwap_element_statisticstimer.h
Normal file
21
src/common/capwap_element_statisticstimer.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__
|
||||
#define __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_STATISTICSTIMER 36
|
||||
|
||||
struct capwap_statisticstimer_element {
|
||||
unsigned short timer;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_statisticstimer_element_create(void* data, unsigned long length);
|
||||
int capwap_statisticstimer_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_statisticstimer_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_statisticstimer_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_STATISTICSTIMER_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_STATISTICSTIMER); \
|
||||
f->create(x, sizeof(struct capwap_statisticstimer_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__ */
|
86
src/common/capwap_element_timers.c
Normal file
86
src/common/capwap_element_timers.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Discovery | Echo Request |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 12 for CAPWAP Timers
|
||||
Length: 2
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_timers_raw_element {
|
||||
unsigned char discovery;
|
||||
unsigned char echorequest;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_timers_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_timers_element* dataelement = (struct capwap_timers_element*)data;
|
||||
struct capwap_timers_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_timers_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_timers_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_timers_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_TIMERS);
|
||||
element->length = htons(sizeof(struct capwap_timers_raw_element));
|
||||
|
||||
dataraw = (struct capwap_timers_raw_element*)element->data;
|
||||
dataraw->discovery = dataelement->discovery;
|
||||
dataraw->echorequest = dataelement->echorequest;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_timers_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_timers_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_timers_element* data;
|
||||
struct capwap_timers_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_TIMERS);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_timers_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_timers_element*)capwap_alloc(sizeof(struct capwap_timers_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_timers_raw_element*)element->data;
|
||||
data->discovery = dataraw->discovery;
|
||||
data->echorequest = dataraw->echorequest;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_timers_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
22
src/common/capwap_element_timers.h
Normal file
22
src/common/capwap_element_timers.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __CAPWAP_ELEMENT_TIMERS_HEADER__
|
||||
#define __CAPWAP_ELEMENT_TIMERS_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_TIMERS 12
|
||||
|
||||
struct capwap_timers_element {
|
||||
unsigned char discovery;
|
||||
unsigned char echorequest;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_timers_element_create(void* data, unsigned long length);
|
||||
int capwap_timers_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_timers_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_timers_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_TIMERS_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_TIMERS); \
|
||||
f->create(x, sizeof(struct capwap_timers_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_TIMERS_HEADER__ */
|
77
src/common/capwap_element_transport.c
Normal file
77
src/common/capwap_element_transport.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Transport |
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 51 for CAPWAP Transport Protocol
|
||||
Length: 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_transport_raw_element {
|
||||
char type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_transport_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_transport_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_transport_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_transport_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_TRANSPORT);
|
||||
element->length = htons(sizeof(struct capwap_transport_raw_element));
|
||||
|
||||
((struct capwap_transport_raw_element*)element->data)->type = ((struct capwap_transport_element*)data)->type;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_transport_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_transport_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_transport_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_TRANSPORT);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_transport_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_transport_element*)capwap_alloc(sizeof(struct capwap_transport_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->type = ((struct capwap_transport_raw_element*)element->data)->type;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_transport_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_transport.h
Normal file
24
src/common/capwap_element_transport.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_TRANSPORT_HEADER__
|
||||
#define __CAPWAP_ELEMENT_TRANSPORT_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_TRANSPORT 51
|
||||
|
||||
struct capwap_transport_element {
|
||||
char type;
|
||||
};
|
||||
|
||||
#define CAPWAP_UDPLITE_TRANSPORT 1
|
||||
#define CAPWAP_UDP_TRANSPORT 2
|
||||
|
||||
struct capwap_message_element* capwap_transport_element_create(void* data, unsigned long length);
|
||||
int capwap_transport_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_transport_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_transport_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_TRANSPORT_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_TRANSPORT); \
|
||||
f->create(x, sizeof(struct capwap_transport_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_TRANSPORT_HEADER__ */
|
99
src/common/capwap_element_vendorpayload.c
Normal file
99
src/common/capwap_element_vendorpayload.c
Normal file
@ -0,0 +1,99 @@
|
||||
#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
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_vendorpayload_raw_element {
|
||||
unsigned long vendorid;
|
||||
unsigned short elementid;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_vendorpayload_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short elementlength;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_vendorpayload_raw_element* dataraw;
|
||||
struct capwap_vendorpayload_element* dataelement = (struct capwap_vendorpayload_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_vendorpayload_element));
|
||||
|
||||
/* */
|
||||
if (!dataelement->datalength || (dataelement->datalength > CAPWAP_VENDORPAYLOAD_MAXLENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Alloc block of memory */
|
||||
elementlength = sizeof(struct capwap_vendorpayload_raw_element) + dataelement->datalength;
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + elementlength);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + elementlength);
|
||||
element->type = htons(CAPWAP_ELEMENT_VENDORPAYLOAD);
|
||||
element->length = htons(elementlength);
|
||||
|
||||
dataraw = (struct capwap_vendorpayload_raw_element*)element->data;
|
||||
dataraw->vendorid = htonl(dataelement->vendorid);
|
||||
dataraw->elementid = htons(dataelement->elementid);
|
||||
memcpy(&dataraw->data[0], &dataelement->data[0], dataelement->datalength);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_vendorpayload_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_vendorpayload_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short elementlength;
|
||||
struct capwap_vendorpayload_element* data;
|
||||
struct capwap_vendorpayload_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_VENDORPAYLOAD);
|
||||
|
||||
elementlength = ntohs(element->length);
|
||||
if (elementlength > sizeof(struct capwap_vendorpayload_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_vendorpayload_raw_element*)element->data;
|
||||
data = (struct capwap_vendorpayload_element*)capwap_alloc(sizeof(struct capwap_vendorpayload_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->vendorid = ntohl(dataraw->vendorid);
|
||||
data->elementid = ntohs(dataraw->elementid);
|
||||
data->datalength = elementlength - sizeof(struct capwap_vendorpayload_element);
|
||||
memcpy(&data->data[0], &dataraw->data[0], data->datalength);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_vendorpayload_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
27
src/common/capwap_element_vendorpayload.h
Normal file
27
src/common/capwap_element_vendorpayload.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__
|
||||
#define __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_VENDORPAYLOAD 37
|
||||
|
||||
#define CAPWAP_VENDORPAYLOAD_MAXLENGTH 2048
|
||||
|
||||
struct capwap_vendorpayload_element {
|
||||
unsigned long vendorid;
|
||||
unsigned short elementid;
|
||||
unsigned short datalength;
|
||||
char data[CAPWAP_VENDORPAYLOAD_MAXLENGTH];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_vendorpayload_element_create(void* data, unsigned long datalength);
|
||||
int capwap_vendorpayload_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_vendorpayload_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_vendorpayload_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_VENDORPAYLOAD_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_VENDORPAYLOAD_MAXLENGTH); \
|
||||
f->create(x, sizeof(struct capwap_vendorpayload_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__ */
|
161
src/common/capwap_element_wtpboarddata.c
Normal file
161
src/common/capwap_element_wtpboarddata.c
Normal file
@ -0,0 +1,161 @@
|
||||
#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);
|
||||
}
|
35
src/common/capwap_element_wtpboarddata.h
Normal file
35
src/common/capwap_element_wtpboarddata.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPBOARDDATA_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPBOARDDATA_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPBOARDDATA 38
|
||||
|
||||
struct capwap_wtpboarddata_element {
|
||||
unsigned long vendor;
|
||||
struct capwap_array* boardsubelement;
|
||||
};
|
||||
|
||||
#define CAPWAP_BOARD_SUBELEMENT_MODELNUMBER 0
|
||||
#define CAPWAP_BOARD_SUBELEMENT_SERIALNUMBER 1
|
||||
#define CAPWAP_BOARD_SUBELEMENT_ID 2
|
||||
#define CAPWAP_BOARD_SUBELEMENT_REVISION 3
|
||||
#define CAPWAP_BOARD_SUBELEMENT_MACADDRESS 4
|
||||
#define CAPWAP_BOARD_SUBELEMENT_MAXDATA 1024
|
||||
|
||||
struct capwap_wtpboarddata_board_subelement {
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
char data[CAPWAP_BOARD_SUBELEMENT_MAXDATA];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_wtpboarddata_element_create(void* data, unsigned long datalength);
|
||||
int capwap_wtpboarddata_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpboarddata_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpboarddata_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPBOARDDATA_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPBOARDDATA); \
|
||||
f->create(x, sizeof(struct capwap_wtpboarddata_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPBOARDDATA_HEADER__ */
|
241
src/common/capwap_element_wtpdescriptor.c
Normal file
241
src/common/capwap_element_wtpdescriptor.c
Normal file
@ -0,0 +1,241 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 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
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtpdescriptor_raw_element {
|
||||
unsigned char maxradios;
|
||||
unsigned char radiosinuse;
|
||||
unsigned char encryptcount;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct capwap_wtpdescriptor_raw_encrypt_subelement {
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
unsigned char reserved : 3;
|
||||
unsigned char wbid : 5;
|
||||
#else
|
||||
unsigned char wbid : 5;
|
||||
unsigned char reserved : 3;
|
||||
#endif
|
||||
unsigned short capabilities;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct capwap_wtpdescriptor_raw_desc_subelement {
|
||||
unsigned long vendor;
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtpdescriptor_element_create(void* data, unsigned long datalength) {
|
||||
char* pos;
|
||||
unsigned long i;
|
||||
unsigned short length;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_wtpdescriptor_raw_element* dataraw;
|
||||
struct capwap_wtpdescriptor_element* dataelement = (struct capwap_wtpdescriptor_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_wtpdescriptor_element));
|
||||
ASSERT(dataelement->encryptsubelement != NULL);
|
||||
ASSERT(dataelement->descsubelement != NULL);
|
||||
|
||||
/* Calc length packet */
|
||||
length = sizeof(struct capwap_wtpdescriptor_raw_element);
|
||||
length += dataelement->encryptsubelement->count * sizeof(struct capwap_wtpdescriptor_raw_encrypt_subelement);
|
||||
for (i = 0; i < dataelement->descsubelement->count; i++) {
|
||||
struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i);
|
||||
length += sizeof(struct capwap_wtpdescriptor_raw_desc_subelement) + desc->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_WTPDESCRIPTOR);
|
||||
element->length = htons(length);
|
||||
|
||||
/* Descriptor */
|
||||
dataraw = (struct capwap_wtpdescriptor_raw_element*)element->data;
|
||||
dataraw->maxradios = dataelement->maxradios;
|
||||
dataraw->radiosinuse = dataelement->radiosinuse;
|
||||
dataraw->encryptcount = (unsigned char)dataelement->encryptsubelement->count;
|
||||
pos = dataraw->data;
|
||||
|
||||
/* Encryption Sub-Element */
|
||||
for (i = 0; i < dataelement->encryptsubelement->count; i++) {
|
||||
struct capwap_wtpdescriptor_raw_encrypt_subelement* encryptraw = (struct capwap_wtpdescriptor_raw_encrypt_subelement*)pos;
|
||||
struct capwap_wtpdescriptor_encrypt_subelement* encrypt = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(dataelement->encryptsubelement, i);
|
||||
|
||||
encryptraw->wbid = encrypt->wbid;
|
||||
encryptraw->capabilities = htons(encrypt->capabilities);
|
||||
|
||||
pos += sizeof(struct capwap_wtpdescriptor_raw_encrypt_subelement);
|
||||
}
|
||||
|
||||
/* Descriptor Sub-Element */
|
||||
for (i = 0; i < dataelement->descsubelement->count; i++) {
|
||||
struct capwap_wtpdescriptor_raw_desc_subelement* descraw = (struct capwap_wtpdescriptor_raw_desc_subelement*)pos;
|
||||
struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i);
|
||||
|
||||
descraw->vendor = htonl(desc->vendor);
|
||||
descraw->type = htons(desc->type);
|
||||
descraw->length = htons(desc->length);
|
||||
memcpy(descraw->data, desc->data, desc->length);
|
||||
|
||||
pos += sizeof(struct capwap_wtpdescriptor_raw_desc_subelement) + desc->length;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtpdescriptor_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtpdescriptor_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned char i;
|
||||
long length;
|
||||
char* pos;
|
||||
struct capwap_wtpdescriptor_element* data;
|
||||
struct capwap_wtpdescriptor_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPDESCRIPTOR);
|
||||
|
||||
length = (long)ntohs(element->length);
|
||||
if (length < 33) {
|
||||
capwap_logging_debug("Invalid WTP Descriptor element");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_wtpdescriptor_raw_element*)element->data;
|
||||
if ((dataraw->radiosinuse > dataraw->maxradios) || (dataraw->encryptcount == 0)) {
|
||||
capwap_logging_debug("Invalid WTP Descriptor element");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_wtpdescriptor_element*)capwap_alloc(sizeof(struct capwap_wtpdescriptor_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
data->encryptsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_encrypt_subelement), 0);
|
||||
data->descsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_desc_subelement), 0);
|
||||
|
||||
/* */
|
||||
data->maxradios = dataraw->maxradios;
|
||||
data->radiosinuse = dataraw->radiosinuse;
|
||||
capwap_array_resize(data->encryptsubelement, dataraw->encryptcount);
|
||||
|
||||
pos = dataraw->data;
|
||||
length -= sizeof(struct capwap_wtpdescriptor_raw_element);
|
||||
|
||||
/* Encrypt Subelement */
|
||||
for (i = 0; i < dataraw->encryptcount; i++) {
|
||||
struct capwap_wtpdescriptor_encrypt_subelement* encrypt = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(data->encryptsubelement, i);
|
||||
struct capwap_wtpdescriptor_raw_encrypt_subelement* encryptraw = (struct capwap_wtpdescriptor_raw_encrypt_subelement*)pos;
|
||||
|
||||
if (length < sizeof(struct capwap_wtpdescriptor_raw_element)) {
|
||||
capwap_logging_debug("Invalid WTP Descriptor element");
|
||||
capwap_wtpdescriptor_element_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
encrypt->wbid = encryptraw->wbid;
|
||||
encrypt->capabilities = ntohs(encryptraw->capabilities);
|
||||
|
||||
/* */
|
||||
pos += sizeof(struct capwap_wtpdescriptor_raw_encrypt_subelement);
|
||||
length -= sizeof(struct capwap_wtpdescriptor_raw_element);
|
||||
}
|
||||
|
||||
if (length < 0) {
|
||||
capwap_logging_debug("Invalid WTP Descriptor element");
|
||||
capwap_wtpdescriptor_element_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Description Subelement */
|
||||
i = 0;
|
||||
while (length > 0) {
|
||||
struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, i);
|
||||
struct capwap_wtpdescriptor_raw_desc_subelement* descraw = (struct capwap_wtpdescriptor_raw_desc_subelement*)pos;
|
||||
unsigned short desclength = ntohs(descraw->length);
|
||||
unsigned short descrawlength = sizeof(struct capwap_wtpdescriptor_raw_desc_subelement) + desclength;
|
||||
|
||||
if ((desclength > CAPWAP_WTPDESC_SUBELEMENT_MAXDATA) || (length < descrawlength)) {
|
||||
capwap_logging_debug("Invalid WTP Descriptor element");
|
||||
capwap_wtpdescriptor_element_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
desc->vendor = ntohl(descraw->vendor);
|
||||
desc->type = ntohs(descraw->type);
|
||||
desc->length = desclength;
|
||||
memcpy(desc->data, descraw->data, desclength);
|
||||
|
||||
/* */
|
||||
i++;
|
||||
pos += descrawlength;
|
||||
length -= descrawlength;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtpdescriptor_element_free(void* data) {
|
||||
struct capwap_wtpdescriptor_element* dataelement = (struct capwap_wtpdescriptor_element*)data;
|
||||
|
||||
ASSERT(dataelement != NULL);
|
||||
ASSERT(dataelement->encryptsubelement != NULL);
|
||||
ASSERT(dataelement->descsubelement != NULL);
|
||||
|
||||
capwap_array_free(dataelement->encryptsubelement);
|
||||
capwap_array_free(dataelement->descsubelement);
|
||||
capwap_free(dataelement);
|
||||
}
|
42
src/common/capwap_element_wtpdescriptor.h
Normal file
42
src/common/capwap_element_wtpdescriptor.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPDESCRIPTOR_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPDESCRIPTOR_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPDESCRIPTOR 39
|
||||
|
||||
struct capwap_wtpdescriptor_element {
|
||||
unsigned char maxradios;
|
||||
unsigned char radiosinuse;
|
||||
struct capwap_array* encryptsubelement;
|
||||
struct capwap_array* descsubelement;
|
||||
};
|
||||
|
||||
struct capwap_wtpdescriptor_encrypt_subelement {
|
||||
unsigned char wbid;
|
||||
unsigned short capabilities;
|
||||
};
|
||||
|
||||
#define CAPWAP_WTPDESC_SUBELEMENT_HARDWAREVERSION 0
|
||||
#define CAPWAP_WTPDESC_SUBELEMENT_SOFTWAREVERSION 1
|
||||
#define CAPWAP_WTPDESC_SUBELEMENT_BOOTVERSION 2
|
||||
#define CAPWAP_WTPDESC_SUBELEMENT_OTHERVERSION 3
|
||||
#define CAPWAP_WTPDESC_SUBELEMENT_MAXDATA 1024
|
||||
|
||||
struct capwap_wtpdescriptor_desc_subelement {
|
||||
unsigned long vendor;
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
char data[CAPWAP_WTPDESC_SUBELEMENT_MAXDATA];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_wtpdescriptor_element_create(void* data, unsigned long datalength);
|
||||
int capwap_wtpdescriptor_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpdescriptor_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpdescriptor_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPDESCRIPTOR_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPDESCRIPTOR); \
|
||||
f->create(x, sizeof(struct capwap_wtpdescriptor_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPDESCRIPTOR_HEADER__ */
|
77
src/common/capwap_element_wtpfallback.c
Normal file
77
src/common/capwap_element_wtpfallback.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Mode |
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 40 for WTP Fallback
|
||||
Length: 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtpfallback_raw_element {
|
||||
char mode;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtpfallback_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_wtpfallback_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpfallback_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpfallback_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_WTPFALLBACK);
|
||||
element->length = htons(sizeof(struct capwap_wtpfallback_raw_element));
|
||||
|
||||
((struct capwap_wtpfallback_raw_element*)element->data)->mode = ((struct capwap_wtpfallback_element*)data)->mode;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtpfallback_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtpfallback_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_wtpfallback_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPFALLBACK);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_wtpfallback_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_wtpfallback_element*)capwap_alloc(sizeof(struct capwap_wtpfallback_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->mode = ((struct capwap_wtpfallback_raw_element*)element->data)->mode;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtpfallback_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_wtpfallback.h
Normal file
24
src/common/capwap_element_wtpfallback.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPFALLBACK_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPFALLBACK_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPFALLBACK 40
|
||||
|
||||
struct capwap_wtpfallback_element {
|
||||
char mode;
|
||||
};
|
||||
|
||||
#define CAPWAP_WTP_FALLBACK_ENABLED 1
|
||||
#define CAPWAP_WTP_FALLBACK_DISABLED 2
|
||||
|
||||
struct capwap_message_element* capwap_wtpfallback_element_create(void* data, unsigned long length);
|
||||
int capwap_wtpfallback_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpfallback_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpfallback_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPFALLBACK_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPFALLBACK); \
|
||||
f->create(x, sizeof(struct capwap_ecnsupport_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPFALLBACK_HEADER__ */
|
81
src/common/capwap_element_wtpframetunnelmode.c
Normal file
81
src/common/capwap_element_wtpframetunnelmode.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|Reservd|N|E|L|U|
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 41 for WTP Frame Tunnel Mode
|
||||
Length: 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtpframetunnelmode_raw_element {
|
||||
unsigned char mode;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtpframetunnelmode_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_wtpframetunnelmode_raw_element* dataraw;
|
||||
struct capwap_wtpframetunnelmode_element* dataelement = (struct capwap_wtpframetunnelmode_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_wtpframetunnelmode_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpframetunnelmode_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpframetunnelmode_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE);
|
||||
element->length = htons(sizeof(struct capwap_wtpframetunnelmode_raw_element));
|
||||
|
||||
dataraw = (struct capwap_wtpframetunnelmode_raw_element*)element->data;
|
||||
dataraw->mode = dataelement->mode & CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK;
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtpframetunnelmode_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtpframetunnelmode_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_wtpframetunnelmode_element* data;
|
||||
struct capwap_wtpframetunnelmode_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPFRAMETUNNELMODE);
|
||||
|
||||
if (ntohs(element->length) != 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_wtpframetunnelmode_raw_element*)element->data;
|
||||
data = (struct capwap_wtpframetunnelmode_element*)capwap_alloc(sizeof(struct capwap_wtpframetunnelmode_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->mode = dataraw->mode & CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtpframetunnelmode_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
26
src/common/capwap_element_wtpframetunnelmode.h
Normal file
26
src/common/capwap_element_wtpframetunnelmode.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPFRAMETUNNELMODE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPFRAMETUNNELMODE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPFRAMETUNNELMODE 41
|
||||
|
||||
struct capwap_wtpframetunnelmode_element {
|
||||
unsigned char mode;
|
||||
};
|
||||
|
||||
#define CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK 0x0e
|
||||
#define CAPWAP_WTP_NATIVE_FRAME_TUNNEL 0x08
|
||||
#define CAPWAP_WTP_8023_FRAME_TUNNEL 0x04
|
||||
#define CAPWAP_WTP_LOCAL_BRIDGING 0x02
|
||||
|
||||
struct capwap_message_element* capwap_wtpframetunnelmode_element_create(void* data, unsigned long datalength);
|
||||
int capwap_wtpframetunnelmode_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpframetunnelmode_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpframetunnelmode_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPFRAMETUNNELMODE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE); \
|
||||
f->create(x, sizeof(struct capwap_wtpframetunnelmode_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPFRAMETUNNELMODE_HEADER__ */
|
77
src/common/capwap_element_wtpmactype.c
Normal file
77
src/common/capwap_element_wtpmactype.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| MAC Type |
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 44 for WTP MAC Type
|
||||
Length: 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtpmactype_raw_element {
|
||||
char type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtpmactype_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_wtpmactype_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpmactype_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpmactype_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_WTPMACTYPE);
|
||||
element->length = htons(sizeof(struct capwap_wtpmactype_raw_element));
|
||||
|
||||
((struct capwap_wtpmactype_raw_element*)element->data)->type = ((struct capwap_wtpmactype_element*)data)->type;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtpmactype_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtpmactype_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_wtpmactype_element* data;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPMACTYPE);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_wtpmactype_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_wtpmactype_element*)capwap_alloc(sizeof(struct capwap_wtpmactype_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->type = ((struct capwap_wtpmactype_raw_element*)element->data)->type;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtpmactype_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_wtpmactype.h
Normal file
24
src/common/capwap_element_wtpmactype.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPMACTYPE_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPMACTYPE_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPMACTYPE 44
|
||||
|
||||
struct capwap_wtpmactype_element {
|
||||
char type;
|
||||
};
|
||||
|
||||
#define CAPWAP_LOCALMAC 0
|
||||
#define CAPWAP_SPLITMAC 1
|
||||
|
||||
struct capwap_message_element* capwap_wtpmactype_element_create(void* data, unsigned long length);
|
||||
int capwap_wtpmactype_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpmactype_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpmactype_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPMACTYPE_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPMACTYPE); \
|
||||
f->create(x, sizeof(struct capwap_wtpmactype_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPMACTYPE_HEADER__ */
|
86
src/common/capwap_element_wtpname.c
Normal file
86
src/common/capwap_element_wtpname.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/********************************************************************
|
||||
|
||||
0
|
||||
0 1 2 3 4 5 6 7
|
||||
+-+-+-+-+-+-+-+-+
|
||||
| Name ...
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 45 for WTP Name
|
||||
Length: >= 1
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtpname_raw_element {
|
||||
char name[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtpname_element_create(void* data, unsigned long datalength) {
|
||||
unsigned short namelength;
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_wtpname_raw_element* dataraw;
|
||||
struct capwap_wtpname_element* dataelement = (struct capwap_wtpname_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength >= sizeof(struct capwap_wtpname_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
namelength = strlen(dataelement->name);
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + namelength);
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + namelength);
|
||||
element->type = htons(CAPWAP_ELEMENT_WTPNAME);
|
||||
element->length = htons(namelength);
|
||||
|
||||
dataraw = (struct capwap_wtpname_raw_element*)element->data;
|
||||
memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtpname_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtpname_element_parsing(struct capwap_message_element* element) {
|
||||
unsigned short namelength;
|
||||
struct capwap_wtpname_element* data;
|
||||
struct capwap_wtpname_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPNAME);
|
||||
|
||||
namelength = ntohs(element->length);
|
||||
if (!namelength || (namelength > CAPWAP_WTPNAME_MAXLENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_wtpname_raw_element*)element->data;
|
||||
data = (struct capwap_wtpname_element*)capwap_alloc(sizeof(struct capwap_wtpname_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
memcpy(&data->name[0], &dataraw->name[0], namelength);
|
||||
data->name[namelength] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtpname_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_wtpname.h
Normal file
24
src/common/capwap_element_wtpname.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPNAME_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPNAME_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPNAME 45
|
||||
|
||||
#define CAPWAP_WTPNAME_MAXLENGTH 512
|
||||
|
||||
struct capwap_wtpname_element {
|
||||
char name[CAPWAP_WTPNAME_MAXLENGTH + 1];
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_wtpname_element_create(void* data, unsigned long datalength);
|
||||
int capwap_wtpname_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpname_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpname_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPNAME_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPNAME); \
|
||||
f->create(x, sizeof(struct capwap_wtpname_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPNAME_HEADER__ */
|
109
src/common/capwap_element_wtprebootstat.c
Normal file
109
src/common/capwap_element_wtprebootstat.c
Normal file
@ -0,0 +1,109 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Reboot Count | AC Initiated Count |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Link Failure Count | SW Failure Count |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| HW Failure Count | Other Failure Count |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Unknown Failure Count |Last Failure Ty|
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 48 for WTP Reboot Statistics
|
||||
Length: 15
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtprebootstat_raw_element {
|
||||
unsigned short rebootcount;
|
||||
unsigned short acinitiatedcount;
|
||||
unsigned short linkfailurecount;
|
||||
unsigned short swfailurecount;
|
||||
unsigned short hwfailurecount;
|
||||
unsigned short otherfailurecount;
|
||||
unsigned short unknownfailurecount;
|
||||
unsigned char lastfailuretype;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtprebootstat_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_wtprebootstat_raw_element* dataraw;
|
||||
struct capwap_wtprebootstat_element* dataelement = (struct capwap_wtprebootstat_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_wtprebootstat_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtprebootstat_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtprebootstat_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_WTPREBOOTSTAT);
|
||||
element->length = htons(sizeof(struct capwap_wtprebootstat_raw_element));
|
||||
|
||||
dataraw = (struct capwap_wtprebootstat_raw_element*)element->data;
|
||||
dataraw->rebootcount = htons(dataelement->rebootcount);
|
||||
dataraw->acinitiatedcount = htons(dataelement->acinitiatedcount);
|
||||
dataraw->linkfailurecount = htons(dataelement->linkfailurecount);
|
||||
dataraw->swfailurecount = htons(dataelement->swfailurecount);
|
||||
dataraw->hwfailurecount = htons(dataelement->hwfailurecount);
|
||||
dataraw->otherfailurecount = htons(dataelement->otherfailurecount);
|
||||
dataraw->unknownfailurecount = htons(dataelement->unknownfailurecount);
|
||||
dataraw->lastfailuretype = dataelement->lastfailuretype;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtprebootstat_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtprebootstat_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_wtprebootstat_element* data;
|
||||
struct capwap_wtprebootstat_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPREBOOTSTAT);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_wtprebootstat_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_wtprebootstat_raw_element*)element->data;
|
||||
data = (struct capwap_wtprebootstat_element*)capwap_alloc(sizeof(struct capwap_wtprebootstat_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
data->rebootcount = ntohs(dataraw->rebootcount);
|
||||
data->acinitiatedcount = ntohs(dataraw->acinitiatedcount);
|
||||
data->linkfailurecount = ntohs(dataraw->linkfailurecount);
|
||||
data->swfailurecount = ntohs(dataraw->swfailurecount);
|
||||
data->hwfailurecount = ntohs(dataraw->hwfailurecount);
|
||||
data->otherfailurecount = ntohs(dataraw->otherfailurecount);
|
||||
data->unknownfailurecount = ntohs(dataraw->unknownfailurecount);
|
||||
data->lastfailuretype = dataraw->lastfailuretype;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtprebootstat_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
40
src/common/capwap_element_wtprebootstat.h
Normal file
40
src/common/capwap_element_wtprebootstat.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPREBOOTSTAT_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPREBOOTSTAT_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPREBOOTSTAT 48
|
||||
|
||||
#define CAPWAP_NOTAVAILABLE_REBOOT_COUNT 65535
|
||||
#define CAPWAP_NOTAVAILABLE_ACINIT_COUNT 65535
|
||||
|
||||
#define CAPWAP_LAST_FAILURE_NOTSUPPORTED 0
|
||||
#define CAPWAP_LAST_FAILURE_ACINITIATED 1
|
||||
#define CAPWAP_LAST_FAILURE_LINK 2
|
||||
#define CAPWAP_LAST_FAILURE_SOFTWARE 3
|
||||
#define CAPWAP_LAST_FAILURE_HARDWARE 4
|
||||
#define CAPWAP_LAST_FAILURE_OTHER 5
|
||||
#define CAPWAP_LAST_FAILURE_UNKNOWN 255
|
||||
|
||||
struct capwap_wtprebootstat_element {
|
||||
unsigned short rebootcount;
|
||||
unsigned short acinitiatedcount;
|
||||
unsigned short linkfailurecount;
|
||||
unsigned short swfailurecount;
|
||||
unsigned short hwfailurecount;
|
||||
unsigned short otherfailurecount;
|
||||
unsigned short unknownfailurecount;
|
||||
unsigned char lastfailuretype;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_wtprebootstat_element_create(void* data, unsigned long datalength);
|
||||
int capwap_wtprebootstat_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtprebootstat_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtprebootstat_element_free(void* data);
|
||||
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPREBOOTSTAT_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPREBOOTSTAT); \
|
||||
f->create(x, sizeof(struct capwap_wtprebootstat_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPREBOOTSTAT_HEADER__ */
|
98
src/common/capwap_element_wtpstaticipaddress.c
Normal file
98
src/common/capwap_element_wtpstaticipaddress.c
Normal file
@ -0,0 +1,98 @@
|
||||
#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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| IP Address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Netmask |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Gateway |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Static |
|
||||
+-+-+-+-+-+-+-+-+
|
||||
|
||||
Type: 49 for WTP Static IP Address Information
|
||||
Length: 13
|
||||
|
||||
********************************************************************/
|
||||
|
||||
struct capwap_wtpstaticipaddress_raw_element {
|
||||
unsigned long address;
|
||||
unsigned long netmask;
|
||||
unsigned long gateway;
|
||||
unsigned char staticip;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* */
|
||||
struct capwap_message_element* capwap_wtpstaticipaddress_element_create(void* data, unsigned long datalength) {
|
||||
struct capwap_message_element* element;
|
||||
struct capwap_wtpstaticipaddress_element* dataelement = (struct capwap_wtpstaticipaddress_element*)data;
|
||||
struct capwap_wtpstaticipaddress_raw_element* dataraw;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(datalength == sizeof(struct capwap_wtpstaticipaddress_element));
|
||||
|
||||
/* Alloc block of memory */
|
||||
element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpstaticipaddress_raw_element));
|
||||
if (!element) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* Create message element */
|
||||
memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpstaticipaddress_raw_element));
|
||||
element->type = htons(CAPWAP_ELEMENT_WTPSTATICIPADDRESS);
|
||||
element->length = htons(sizeof(struct capwap_wtpstaticipaddress_raw_element));
|
||||
|
||||
dataraw = (struct capwap_wtpstaticipaddress_raw_element*)element->data;
|
||||
dataraw->address = dataelement->address.s_addr;
|
||||
dataraw->netmask = dataelement->netmask.s_addr;
|
||||
dataraw->gateway = dataelement->gateway.s_addr;
|
||||
dataraw->staticip = dataelement->staticip;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_wtpstaticipaddress_element_validate(struct capwap_message_element* element) {
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void* capwap_wtpstaticipaddress_element_parsing(struct capwap_message_element* element) {
|
||||
struct capwap_wtpstaticipaddress_element* data;
|
||||
struct capwap_wtpstaticipaddress_raw_element* dataraw;
|
||||
|
||||
ASSERT(element);
|
||||
ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPSTATICIPADDRESS);
|
||||
|
||||
if (ntohs(element->length) != sizeof(struct capwap_wtpstaticipaddress_raw_element)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
data = (struct capwap_wtpstaticipaddress_element*)capwap_alloc(sizeof(struct capwap_wtpstaticipaddress_element));
|
||||
if (!data) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
/* */
|
||||
dataraw = (struct capwap_wtpstaticipaddress_raw_element*)element->data;
|
||||
data->address.s_addr = dataraw->address;
|
||||
data->netmask.s_addr = dataraw->netmask;
|
||||
data->gateway.s_addr = dataraw->gateway;
|
||||
data->staticip = dataraw->staticip;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_wtpstaticipaddress_element_free(void* data) {
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
24
src/common/capwap_element_wtpstaticipaddress.h
Normal file
24
src/common/capwap_element_wtpstaticipaddress.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CAPWAP_ELEMENT_WTPSTATICIPADDRESS_HEADER__
|
||||
#define __CAPWAP_ELEMENT_WTPSTATICIPADDRESS_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_WTPSTATICIPADDRESS 49
|
||||
|
||||
struct capwap_wtpstaticipaddress_element {
|
||||
struct in_addr address;
|
||||
struct in_addr netmask;
|
||||
struct in_addr gateway;
|
||||
unsigned char staticip;
|
||||
};
|
||||
|
||||
struct capwap_message_element* capwap_wtpstaticipaddress_element_create(void* data, unsigned long length);
|
||||
int capwap_wtpstaticipaddress_element_validate(struct capwap_message_element* element);
|
||||
void* capwap_wtpstaticipaddress_element_parsing(struct capwap_message_element* element);
|
||||
void capwap_wtpstaticipaddress_element_free(void* data);
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT(x) ({ \
|
||||
struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPSTATICIPADDRESS); \
|
||||
f->create(x, sizeof(struct capwap_wtpstaticipaddress_element)); \
|
||||
})
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_WTPSTATICIPADDRESS_HEADER__ */
|
10
src/common/capwap_error.h
Normal file
10
src/common/capwap_error.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef __CAPWAP_ERROR_HEADER__
|
||||
#define __CAPWAP_ERROR_HEADER__
|
||||
|
||||
#define CAPWAP_SUCCESSFUL 0
|
||||
#define CAPWAP_ASSERT_CONDITION -1
|
||||
#define CAPWAP_OUT_OF_MEMORY -2
|
||||
#define CAPWAP_REQUEST_ROOT -3
|
||||
#define CAPWAP_CRYPT_ERROR -4
|
||||
|
||||
#endif /* __CAPWAP_ERROR_HEADER__*/
|
99
src/common/capwap_event.c
Normal file
99
src/common/capwap_event.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_event.h"
|
||||
|
||||
#ifndef CAPWAP_MULTITHREADING_ENABLE
|
||||
#error "Warning: multithreading is disabled\n"
|
||||
#endif
|
||||
|
||||
/* */
|
||||
int capwap_event_init(capwap_event_t* e) {
|
||||
ASSERT(e != NULL);
|
||||
|
||||
e->set = 0;
|
||||
|
||||
if (pthread_cond_init(&e->event, NULL) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&e->mutex, NULL) != 0) {
|
||||
pthread_cond_destroy(&e->event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_event_destroy(capwap_event_t* e) {
|
||||
ASSERT(e != NULL);
|
||||
|
||||
pthread_cond_destroy(&e->event);
|
||||
pthread_mutex_destroy(&e->mutex);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_event_signal(capwap_event_t* e) {
|
||||
ASSERT(e != NULL);
|
||||
|
||||
pthread_mutex_lock(&e->mutex);
|
||||
|
||||
e->set = 1;
|
||||
pthread_cond_signal(&e->event);
|
||||
|
||||
pthread_mutex_unlock(&e->mutex);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_event_reset(capwap_event_t* e) {
|
||||
ASSERT(e != NULL);
|
||||
|
||||
pthread_mutex_lock(&e->mutex);
|
||||
|
||||
e->set = 0;
|
||||
|
||||
pthread_mutex_unlock(&e->mutex);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_event_wait(capwap_event_t* e) {
|
||||
capwap_event_wait_timeout(e, -1);
|
||||
}
|
||||
|
||||
/* */
|
||||
int capwap_event_wait_timeout(capwap_event_t* e, long timeout) {
|
||||
int result = 0;
|
||||
|
||||
ASSERT(e != NULL);
|
||||
|
||||
pthread_mutex_lock(&e->mutex);
|
||||
|
||||
if (e->set) {
|
||||
result = 1;
|
||||
} else if (timeout < 0) {
|
||||
if (!pthread_cond_wait(&e->event, &e->mutex)) {
|
||||
result = 1;
|
||||
}
|
||||
} else {
|
||||
struct timeval tp;
|
||||
|
||||
gettimeofday(&tp, NULL);
|
||||
tp.tv_sec += timeout / 1000;
|
||||
tp.tv_usec += ((timeout % 1000) * 1000);
|
||||
if (tp.tv_usec > 1000000) {
|
||||
tp.tv_sec++;
|
||||
tp.tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
struct timespec ts;
|
||||
ts.tv_sec = tp.tv_sec;
|
||||
ts.tv_nsec = tp.tv_usec * 1000;
|
||||
if (!pthread_cond_timedwait(&e->event, &e->mutex, &ts)) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
e->set = 0;
|
||||
pthread_mutex_unlock(&e->mutex);
|
||||
|
||||
return result;
|
||||
}
|
23
src/common/capwap_event.h
Normal file
23
src/common/capwap_event.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __CAPWAP_EVENT_HEADER__
|
||||
#define __CAPWAP_EVENT_HEADER__
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct {
|
||||
char set;
|
||||
pthread_cond_t event;
|
||||
pthread_mutex_t mutex;
|
||||
} capwap_event_t;
|
||||
|
||||
int capwap_event_init(capwap_event_t* e);
|
||||
void capwap_event_destroy(capwap_event_t* e);
|
||||
void capwap_event_signal(capwap_event_t* e);
|
||||
void capwap_event_reset(capwap_event_t* e);
|
||||
void capwap_event_wait(capwap_event_t* e);
|
||||
int capwap_event_wait_timeout(capwap_event_t* e, long timeout);
|
||||
|
||||
#endif /* CAPWAP_MULTITHREADING_ENABLE */
|
||||
|
||||
#endif /* __CAPWAP_EVENT_HEADER__ */
|
190
src/common/capwap_list.c
Normal file
190
src/common/capwap_list.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_list.h"
|
||||
|
||||
/* */
|
||||
struct capwap_list* capwap_list_create(void) {
|
||||
struct capwap_list* list;
|
||||
|
||||
list = (struct capwap_list*)capwap_alloc(sizeof(struct capwap_list));
|
||||
if (!list) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
memset(list, 0, sizeof(struct capwap_list));
|
||||
return list;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_list_free(struct capwap_list* list) {
|
||||
ASSERT(list != NULL);
|
||||
|
||||
capwap_list_flush(list);
|
||||
capwap_free(list);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_list_flush(struct capwap_list* list) {
|
||||
struct capwap_list_item* item;
|
||||
struct capwap_list_item* next;
|
||||
|
||||
ASSERT(list != NULL);
|
||||
|
||||
item = list->first;
|
||||
while (item) {
|
||||
next = item->next;
|
||||
capwap_itemlist_free(item);
|
||||
item = next;
|
||||
}
|
||||
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_list_item* capwap_itemlist_create_with_item(void* item, int size) {
|
||||
struct capwap_list_item* itemlist;
|
||||
|
||||
itemlist = (struct capwap_list_item*)capwap_alloc(sizeof(struct capwap_list_item));
|
||||
if (!itemlist) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
memset(itemlist, 0, sizeof(struct capwap_list_item));
|
||||
itemlist->item = item;
|
||||
itemlist->itemsize = size;
|
||||
itemlist->autodelete = 1;
|
||||
|
||||
return itemlist;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_list_item* capwap_itemlist_create(int size) {
|
||||
void* item;
|
||||
|
||||
ASSERT(size > 0);
|
||||
|
||||
item = capwap_alloc(size);
|
||||
if (!item) {
|
||||
capwap_outofmemory();
|
||||
}
|
||||
|
||||
return capwap_itemlist_create_with_item(item, size);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_itemlist_free(struct capwap_list_item* item) {
|
||||
ASSERT(item != NULL);
|
||||
ASSERT(item->item != NULL);
|
||||
|
||||
if (item->autodelete) {
|
||||
capwap_free(item->item);
|
||||
}
|
||||
|
||||
capwap_free(item);
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_list_item* capwap_itemlist_remove(struct capwap_list* list, struct capwap_list_item* item) {
|
||||
ASSERT(list != NULL);
|
||||
ASSERT(item != NULL);
|
||||
|
||||
if (item->prev) {
|
||||
item->prev->next = item->next;
|
||||
} else {
|
||||
list->first = item->next;
|
||||
}
|
||||
|
||||
if (item->next) {
|
||||
item->next->prev = item->prev;
|
||||
} else {
|
||||
list->last = item->prev;
|
||||
}
|
||||
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
list->count--;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct capwap_list_item* capwap_itemlist_remove_head(struct capwap_list* list) {
|
||||
struct capwap_list_item* item;
|
||||
|
||||
ASSERT(list != NULL);
|
||||
|
||||
item = list->first;
|
||||
if (item != NULL) {
|
||||
list->first = item->next;
|
||||
if (list->first) {
|
||||
list->first->prev = NULL;
|
||||
} else {
|
||||
list->last = NULL;
|
||||
}
|
||||
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
list->count--;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_itemlist_insert_before(struct capwap_list* list, struct capwap_list_item* before, struct capwap_list_item* item) {
|
||||
ASSERT(list != NULL);
|
||||
ASSERT(item != NULL);
|
||||
|
||||
list->count++;
|
||||
|
||||
if (!before) {
|
||||
if (list->first) {
|
||||
before = list->first;
|
||||
} else {
|
||||
list->first = item;
|
||||
list->last = item;
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item->prev = before->prev;
|
||||
item->next = before;
|
||||
if (!before->prev) {
|
||||
list->first = item;
|
||||
} else {
|
||||
before->prev->next = item;
|
||||
}
|
||||
before->prev = item;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_itemlist_insert_after(struct capwap_list* list, struct capwap_list_item* after, struct capwap_list_item* item) {
|
||||
ASSERT(list != NULL);
|
||||
ASSERT(item != NULL);
|
||||
|
||||
list->count++;
|
||||
|
||||
if (!after) {
|
||||
if (list->last) {
|
||||
after = list->last;
|
||||
} else {
|
||||
list->first = item;
|
||||
list->last = item;
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item->prev = after;
|
||||
item->next = after->next;
|
||||
if (!after->next) {
|
||||
list->last = item;
|
||||
} else {
|
||||
after->next->prev = item;
|
||||
}
|
||||
after->next = item;
|
||||
}
|
33
src/common/capwap_list.h
Normal file
33
src/common/capwap_list.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef __CAPWAP_LIST_HEADER__
|
||||
#define __CAPWAP_LIST_HEADER__
|
||||
|
||||
/* Item */
|
||||
struct capwap_list_item {
|
||||
void* item;
|
||||
int itemsize;
|
||||
int autodelete;
|
||||
struct capwap_list_item* next;
|
||||
struct capwap_list_item* prev;
|
||||
};
|
||||
|
||||
/* List */
|
||||
struct capwap_list {
|
||||
unsigned long count;
|
||||
struct capwap_list_item* first;
|
||||
struct capwap_list_item* last;
|
||||
};
|
||||
|
||||
struct capwap_list* capwap_list_create(void);
|
||||
void capwap_list_free(struct capwap_list* list);
|
||||
void capwap_list_flush(struct capwap_list* list);
|
||||
|
||||
struct capwap_list_item* capwap_itemlist_create(int size);
|
||||
struct capwap_list_item* capwap_itemlist_create_with_item(void* item, int size);
|
||||
void capwap_itemlist_free(struct capwap_list_item* item);
|
||||
|
||||
struct capwap_list_item* capwap_itemlist_remove(struct capwap_list* list, struct capwap_list_item* item);
|
||||
struct capwap_list_item* capwap_itemlist_remove_head(struct capwap_list* list);
|
||||
void capwap_itemlist_insert_before(struct capwap_list* list, struct capwap_list_item* before, struct capwap_list_item* item);
|
||||
void capwap_itemlist_insert_after(struct capwap_list* list, struct capwap_list_item* after, struct capwap_list_item* item);
|
||||
|
||||
#endif /* __CAPWAP_LIST_HEADER__ */
|
41
src/common/capwap_lock.c
Normal file
41
src/common/capwap_lock.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_lock.h"
|
||||
|
||||
#ifndef CAPWAP_MULTITHREADING_ENABLE
|
||||
#error "Warning: multithreading is disabled\n"
|
||||
#endif
|
||||
|
||||
/* */
|
||||
int capwap_lock_init(capwap_lock_t* lock) {
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
ASSERT(lock != NULL);
|
||||
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (pthread_mutex_init(&lock->mutex, &attr) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_lock_destroy(capwap_lock_t* lock) {
|
||||
ASSERT(lock != NULL);
|
||||
|
||||
pthread_mutex_destroy(&lock->mutex);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_lock_enter(capwap_lock_t* lock) {
|
||||
ASSERT(lock != NULL);
|
||||
|
||||
pthread_mutex_lock(&lock->mutex);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_lock_exit(capwap_lock_t* lock) {
|
||||
ASSERT(lock != NULL);
|
||||
|
||||
pthread_mutex_unlock(&lock->mutex);
|
||||
}
|
19
src/common/capwap_lock.h
Normal file
19
src/common/capwap_lock.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __CAPWAP_LOCK_HEADER__
|
||||
#define __CAPWAP_LOCK_HEADER__
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
|
||||
#include "pthread.h"
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex;
|
||||
} capwap_lock_t;
|
||||
|
||||
int capwap_lock_init(capwap_lock_t* lock);
|
||||
void capwap_lock_destroy(capwap_lock_t* lock);
|
||||
void capwap_lock_enter(capwap_lock_t* lock);
|
||||
void capwap_lock_exit(capwap_lock_t* lock);
|
||||
|
||||
#endif /* CAPWAP_MULTITHREADING_ENABLE */
|
||||
|
||||
#endif /* __CAPWAP_LOCK_HEADER__ */
|
115
src/common/capwap_logging.c
Normal file
115
src/common/capwap_logging.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_logging.h"
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
#include "capwap_lock.h"
|
||||
|
||||
static capwap_lock_t l_loglock;
|
||||
#endif
|
||||
|
||||
/* */
|
||||
static int logginglevel = CAPWAP_LOGGING_NONE;
|
||||
static int loggingoutputstdout = 0;
|
||||
static int loggingoutputstderr = 0;
|
||||
|
||||
/* */
|
||||
static char logginglevelid[] = { 'N', 'F', 'E', 'W', 'I', 'D' };
|
||||
|
||||
/* */
|
||||
static void prefix_logging(int level, char* buffer) {
|
||||
time_t timenow;
|
||||
struct tm* tmnow;
|
||||
|
||||
time(&timenow);
|
||||
tmnow = localtime(&timenow);
|
||||
sprintf(buffer, "[%02d/%02d/%04d %02d:%02d:%02d] <%c> ", tmnow->tm_mday, tmnow->tm_mon + 1, tmnow->tm_year + 1900, tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec, logginglevelid[level]);
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_logging_init() {
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_init(&l_loglock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_logging_close() {
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_destroy(&l_loglock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_logging_verboselevel(unsigned int level) {
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_enter(&l_loglock);
|
||||
#endif
|
||||
|
||||
logginglevel = level;
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_exit(&l_loglock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_logging_disable_allinterface() {
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_enter(&l_loglock);
|
||||
#endif
|
||||
|
||||
loggingoutputstdout = 0;
|
||||
loggingoutputstderr = 0;
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_exit(&l_loglock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_logging_enable_console(int error) {
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_enter(&l_loglock);
|
||||
#endif
|
||||
|
||||
/* Enable only one of stdout/stderr */
|
||||
loggingoutputstdout = (error ? 0 : 1);
|
||||
loggingoutputstderr = !loggingoutputstdout;
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_exit(&l_loglock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* */
|
||||
#ifdef ENABLE_LOGGING
|
||||
void capwap_logging_printf(int level, const char* format, ...) {
|
||||
va_list args;
|
||||
char prefix[256];
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_enter(&l_loglock);
|
||||
#endif
|
||||
|
||||
if ((logginglevel != CAPWAP_LOGGING_NONE) && (level <= logginglevel)) {
|
||||
prefix_logging(level, prefix);
|
||||
|
||||
if (loggingoutputstdout || loggingoutputstderr) {
|
||||
FILE* output = (loggingoutputstdout ? stdout : stderr);
|
||||
|
||||
fprintf(output, prefix);
|
||||
vfprintf(output, format, args);
|
||||
fprintf(output, "\n");
|
||||
fflush(output);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CAPWAP_MULTITHREADING_ENABLE
|
||||
capwap_lock_exit(&l_loglock);
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
37
src/common/capwap_logging.h
Normal file
37
src/common/capwap_logging.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef __CAPWAP_LOGGING_HEADER__
|
||||
#define __CAPWAP_LOGGING_HEADER__
|
||||
|
||||
/* Logging level */
|
||||
#define CAPWAP_LOGGING_NONE 0
|
||||
#define CAPWAP_LOGGING_FATAL 1
|
||||
#define CAPWAP_LOGGING_ERROR 2
|
||||
#define CAPWAP_LOGGING_WARNING 3
|
||||
#define CAPWAP_LOGGING_INFO 4
|
||||
#define CAPWAP_LOGGING_DEBUG 5
|
||||
|
||||
/* Logging initialize function */
|
||||
void capwap_logging_init();
|
||||
void capwap_logging_close();
|
||||
|
||||
/* */
|
||||
void capwap_logging_verboselevel(unsigned int level);
|
||||
|
||||
/* */
|
||||
void capwap_logging_disable_allinterface();
|
||||
void capwap_logging_enable_console(int error);
|
||||
|
||||
/* */
|
||||
#ifdef ENABLE_LOGGING
|
||||
void capwap_logging_printf(int level, const char *format, ...);
|
||||
#else
|
||||
#define capwap_logging_printf(l, f, args...) (0)
|
||||
#endif
|
||||
|
||||
/* */
|
||||
#define capwap_logging_fatal(f, args...) capwap_logging_printf(CAPWAP_LOGGING_FATAL, f, ##args)
|
||||
#define capwap_logging_error(f, args...) capwap_logging_printf(CAPWAP_LOGGING_ERROR, f, ##args)
|
||||
#define capwap_logging_warning(f, args...) capwap_logging_printf(CAPWAP_LOGGING_WARNING, f, ##args)
|
||||
#define capwap_logging_info(f, args...) capwap_logging_printf(CAPWAP_LOGGING_INFO, f, ##args)
|
||||
#define capwap_logging_debug(f, args...) capwap_logging_printf(CAPWAP_LOGGING_DEBUG, f, ##args)
|
||||
|
||||
#endif /* __CAPWAP_LOGGING_HEADER__ */
|
1240
src/common/capwap_network.c
Normal file
1240
src/common/capwap_network.c
Normal file
File diff suppressed because it is too large
Load Diff
87
src/common/capwap_network.h
Normal file
87
src/common/capwap_network.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef __CAPWAP_NETWORK_HEADER__
|
||||
#define __CAPWAP_NETWORK_HEADER__
|
||||
|
||||
#include "capwap_array.h"
|
||||
#include "capwap_list.h"
|
||||
|
||||
/* Standard Configuration */
|
||||
#define CAPWAP_CONTROL_PORT 5246
|
||||
#define CAPWAP_MAX_PACKET_SIZE 65535
|
||||
|
||||
#define CAPWAP_MACADDRESS_NONE 0
|
||||
#define CAPWAP_MACADDRESS_EUI48 6
|
||||
#define CAPWAP_MACADDRESS_EUI64 8
|
||||
#define CAPWAP_MACADDRESS_MAX_SIZE CAPWAP_MACADDRESS_EUI64
|
||||
|
||||
/* Helper */
|
||||
#define CAPWAP_GET_NETWORK_PORT(address) ntohs((((address)->ss_family == AF_INET) ? ((struct sockaddr_in*)(address))->sin_port : ((struct sockaddr_in6*)(address))->sin6_port))
|
||||
#define CAPWAP_SET_NETWORK_PORT(address, port) if ((address)->ss_family == AF_INET) { \
|
||||
((struct sockaddr_in*)(address))->sin_port = htons(port); \
|
||||
} else if ((address)->ss_family == AF_INET6) { \
|
||||
((struct sockaddr_in6*)(address))->sin6_port = htons(port); \
|
||||
}
|
||||
|
||||
/* */
|
||||
#define CAPWAP_MAX_SOCKETS 4
|
||||
#define CAPWAP_SOCKET_IPV4_UDP 0
|
||||
#define CAPWAP_SOCKET_IPV4_UDPLITE 1
|
||||
#define CAPWAP_SOCKET_IPV6_UDP 2
|
||||
#define CAPWAP_SOCKET_IPV6_UDPLITE 3
|
||||
|
||||
/* */
|
||||
#define CAPWAP_RECV_ERROR_SOCKET -1
|
||||
#define CAPWAP_RECV_ERROR_TIMEOUT -2
|
||||
#define CAPWAP_RECV_ERROR_INTR -3
|
||||
|
||||
/* Socket Flags */
|
||||
#define CAPWAP_IPV6ONLY_FLAG 0x00000001
|
||||
|
||||
/* Network struct */
|
||||
struct capwap_network {
|
||||
int sock_family; /* Address family used by the server. */
|
||||
unsigned short bind_sock_ctrl_port; /* Port number to listen control protocol. */
|
||||
char bind_interface[IFNAMSIZ];
|
||||
|
||||
int sock_ctrl[CAPWAP_MAX_SOCKETS];
|
||||
int bind_ctrl_flags;
|
||||
|
||||
int sock_data[CAPWAP_MAX_SOCKETS];
|
||||
int bind_data_flags;
|
||||
};
|
||||
|
||||
#define CAPWAP_SOCKET_UDP 0
|
||||
#define CAPWAP_SOCKET_UDPLITE 1
|
||||
|
||||
/* Network socket */
|
||||
struct capwap_socket {
|
||||
int type;
|
||||
int family;
|
||||
int socket[2];
|
||||
int isctrlsocket;
|
||||
};
|
||||
|
||||
void capwap_network_init(struct capwap_network* net);
|
||||
int capwap_network_set_pollfd(struct capwap_network* net, struct pollfd* fds, int fdscount);
|
||||
void capwap_interface_list(struct capwap_network* net, struct capwap_list* list);
|
||||
|
||||
int capwap_get_macaddress_from_interface(const char* interface, char* macaddress);
|
||||
|
||||
#define CAPWAP_DATA_SOCKET 0
|
||||
#define CAPWAP_CTRL_SOCKET 1
|
||||
int capwap_get_socket(struct capwap_network* net, int socketfamily, int socketprotocol, int isctrlsocket);
|
||||
void capwap_get_network_socket(struct capwap_network* net, struct capwap_socket* sock, int fd);
|
||||
|
||||
int capwap_bind_sockets(struct capwap_network* net);
|
||||
void capwap_close_sockets(struct capwap_network* net);
|
||||
|
||||
int capwap_compare_ip(struct sockaddr_storage* addr1, struct sockaddr_storage* addr2);
|
||||
|
||||
int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
||||
int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, struct timeout_control* timeout);
|
||||
|
||||
int capwap_ipv4_mapped_ipv6(struct sockaddr_storage* source, struct sockaddr_storage* dest);
|
||||
int capwap_address_from_string(const char* ip, struct sockaddr_storage* address);
|
||||
|
||||
int capwap_get_localaddress_by_remoteaddress(struct sockaddr_storage* local, struct sockaddr_storage* remote, char* oif, int ipv6dualstack);
|
||||
|
||||
#endif /* __CAPWAP_NETWORK_HEADER__ */
|
1327
src/common/capwap_protocol.c
Normal file
1327
src/common/capwap_protocol.c
Normal file
File diff suppressed because it is too large
Load Diff
278
src/common/capwap_protocol.h
Normal file
278
src/common/capwap_protocol.h
Normal file
@ -0,0 +1,278 @@
|
||||
#ifndef __CAPWAP_PROTOCOL_HEADER__
|
||||
#define __CAPWAP_PROTOCOL_HEADER__
|
||||
|
||||
#include "capwap_element.h"
|
||||
#include "capwap_network.h"
|
||||
#include "capwap_dtls.h"
|
||||
|
||||
#define CAPWAP_PROTOCOL_VERSION 0
|
||||
|
||||
#define CAPWAP_MTU_DEFAULT 1400
|
||||
#define CAPWAP_DONT_FRAGMENT 0
|
||||
|
||||
/* Capwap preamble */
|
||||
#define CAPWAP_PREAMBLE_HEADER 0
|
||||
#define CAPWAP_PREAMBLE_DTLS_HEADER 1
|
||||
|
||||
struct capwap_preamble {
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
unsigned char version : 4;
|
||||
unsigned char type : 4;
|
||||
#else
|
||||
unsigned char type : 4;
|
||||
unsigned char version : 4;
|
||||
#endif
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* Capwap DTLS header */
|
||||
struct capwap_dtls_header {
|
||||
struct capwap_preamble preamble;
|
||||
unsigned char reserved1;
|
||||
unsigned char reserved2;
|
||||
unsigned char reserved3;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* Capwap header: 8 (header) + 12 (radio mac) + 256 (wireless info) */
|
||||
#define CAPWAP_HEADER_MAX_SIZE 276
|
||||
struct capwap_header {
|
||||
struct capwap_preamble preamble;
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
unsigned short hlen : 5;
|
||||
unsigned short rid : 5;
|
||||
unsigned short wbid : 5;
|
||||
unsigned short flag_t : 1;
|
||||
unsigned char flag_f : 1;
|
||||
unsigned char flag_l : 1;
|
||||
unsigned char flag_w : 1;
|
||||
unsigned char flag_m : 1;
|
||||
unsigned char flag_k : 1;
|
||||
unsigned char flag_res : 3;
|
||||
#else
|
||||
unsigned short _rid_hi : 3;
|
||||
unsigned short hlen : 5;
|
||||
unsigned short flag_t : 1;
|
||||
unsigned short wbid : 5;
|
||||
unsigned short _rid_lo : 2;
|
||||
unsigned char flag_res : 3;
|
||||
unsigned char flag_k : 1;
|
||||
unsigned char flag_m : 1;
|
||||
unsigned char flag_w : 1;
|
||||
unsigned char flag_l : 1;
|
||||
unsigned char flag_f : 1;
|
||||
#endif
|
||||
unsigned short frag_id;
|
||||
unsigned short frag_off; /* Only first 13 bit */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define FRAGMENT_OFFSET_MASK 0xfff8
|
||||
|
||||
/* Mac Address */
|
||||
struct capwap_mac_address {
|
||||
unsigned char length;
|
||||
char address[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* Wireless Information */
|
||||
struct capwap_wireless_information {
|
||||
unsigned char length;
|
||||
char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* Control Message Type */
|
||||
#define CAPWAP_FIRST_MESSAGE_TYPE 1
|
||||
#define CAPWAP_DISCOVERY_REQUEST 1
|
||||
#define CAPWAP_DISCOVERY_RESPONSE 2
|
||||
#define CAPWAP_JOIN_REQUEST 3
|
||||
#define CAPWAP_JOIN_RESPONSE 4
|
||||
#define CAPWAP_CONFIGURATION_STATUS_REQUEST 5
|
||||
#define CAPWAP_CONFIGURATION_STATUS_RESPONSE 6
|
||||
#define CAPWAP_CONFIGURATION_UPDATE_REQUEST 7
|
||||
#define CAPWAP_CONFIGURATION_UPDATE_RESPONSE 8
|
||||
#define CAPWAP_WTP_EVENT_REQUEST 9
|
||||
#define CAPWAP_WTP_EVENT_RESPONSE 10
|
||||
#define CAPWAP_CHANGE_STATE_EVENT_REQUEST 11
|
||||
#define CAPWAP_CHANGE_STATE_EVENT_RESPONSE 12
|
||||
#define CAPWAP_ECHO_REQUEST 13
|
||||
#define CAPWAP_ECHO_RESPONSE 14
|
||||
#define CAPWAP_IMAGE_DATA_REQUEST 15
|
||||
#define CAPWAP_IMAGE_DATA_RESPONSE 16
|
||||
#define CAPWAP_RESET_REQUEST 17
|
||||
#define CAPWAP_RESET_RESPONSE 18
|
||||
#define CAPWAP_PRIMARY_DISCOVERY_REQUEST 19
|
||||
#define CAPWAP_PRIMARY_DISCOVERY_RESPONSE 20
|
||||
#define CAPWAP_DATA_TRANSFER_REQUEST 21
|
||||
#define CAPWAP_DATA_TRANSFER_RESPONSE 22
|
||||
#define CAPWAP_CLEAR_CONFIGURATION_REQUEST 23
|
||||
#define CAPWAP_CLEAR_CONFIGURATION_RESPONSE 24
|
||||
#define CAPWAP_STATION_CONFIGURATION_REQUEST 25
|
||||
#define CAPWAP_STATION_CONFIGURATION_RESPONSE 26
|
||||
#define CAPWAP_LAST_MESSAGE_TYPE 26
|
||||
|
||||
/* Control Message */
|
||||
struct capwap_control_message {
|
||||
unsigned long type;
|
||||
unsigned char seq;
|
||||
unsigned short length;
|
||||
unsigned char flags;
|
||||
char elements[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* Data Message */
|
||||
struct capwap_data_message {
|
||||
unsigned short length;
|
||||
char elements[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* Capwap dtls header helper */
|
||||
#define GET_DTLS_BODY(x) (void*)(((char*)(x)) + sizeof(struct capwap_dtls_header))
|
||||
|
||||
/* Capwap header helper */
|
||||
#define GET_VERSION_HEADER(x) ((x)->preamble.version)
|
||||
#define SET_VERSION_HEADER(x, y) ((x)->preamble.version = (unsigned char)(y))
|
||||
#define GET_TYPE_HEADER(x) ((x)->preamble.type)
|
||||
#define SET_TYPE_HEADER(x, y) ((x)->preamble.type = (unsigned char)(y))
|
||||
|
||||
#define GET_HLEN_HEADER(x) ((x)->hlen)
|
||||
#define SET_HLEN_HEADER(x, y) ((x)->hlen = (unsigned short)(y))
|
||||
#ifdef CAPWAP_BIG_ENDIAN
|
||||
#define GET_RID_HEADER(x) ((x)->rid)
|
||||
#define SET_RID_HEADER(x, y) ((x)->rid = (unsigned short)(y))
|
||||
#else
|
||||
#define GET_RID_HEADER(x) ((unsigned short)((x)->_rid_hi << 2 | (x)->_rid_lo))
|
||||
#define SET_RID_HEADER(x, y) ({ (x)->_rid_hi = (unsigned short)((y) >> 2); (x)->_rid_lo = (unsigned short)((y) & 0x0003); })
|
||||
#endif
|
||||
#define GET_WBID_HEADER(x) ((x)->wbid)
|
||||
#define SET_WBID_HEADER(x, y) ((x)->wbid = (unsigned short)(y))
|
||||
|
||||
#define IS_FLAG_T_HEADER(x) ((x)->flag_t)
|
||||
#define SET_FLAG_T_HEADER(x, y) ((x)->flag_t = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_F_HEADER(x) ((x)->flag_f)
|
||||
#define SET_FLAG_F_HEADER(x, y) ((x)->flag_f = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_L_HEADER(x) ((x)->flag_l)
|
||||
#define SET_FLAG_L_HEADER(x, y) ((x)->flag_l = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_W_HEADER(x) ((x)->flag_w)
|
||||
#define SET_FLAG_W_HEADER(x, y) ((x)->flag_w = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_M_HEADER(x) ((x)->flag_m)
|
||||
#define SET_FLAG_M_HEADER(x, y) ((x)->flag_m = ((y) ? 1 : 0))
|
||||
#define IS_FLAG_K_HEADER(x) ((x)->flag_k)
|
||||
#define SET_FLAG_K_HEADER(x, y) ((x)->flag_k = ((y) ? 1 : 0))
|
||||
|
||||
#define GET_FRAGMENT_ID_HEADER(x) (ntohs((x)->frag_id))
|
||||
#define SET_FRAGMENT_ID_HEADER(x, y) ((x)->frag_id = htons((unsigned short)(y)))
|
||||
#define GET_FRAGMENT_OFFSET_HEADER(x) (ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK)
|
||||
#define SET_FRAGMENT_OFFSET_HEADER(x, y) ((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((unsigned short)(y) & FRAGMENT_OFFSET_MASK))
|
||||
|
||||
#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((char*)(x)) + sizeof(struct capwap_header)))
|
||||
#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((char*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0)))
|
||||
#define GET_PAYLOAD_HEADER(x) ((void*)(((char*)(x)) + GET_HLEN_HEADER(x) * 4))
|
||||
|
||||
#define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0)
|
||||
|
||||
/*********************************************************************************************************************/
|
||||
/* Sanity check packet */
|
||||
#define CAPWAP_WRONG_PACKET -1
|
||||
#define CAPWAP_NONE_PACKET 0
|
||||
#define CAPWAP_PLAIN_PACKET 1
|
||||
#define CAPWAP_DTLS_PACKET 2
|
||||
int capwap_sanity_check(int isctrlsocket, int state, void* buffer, int buffersize, int dtlsctrlenable, int dtlsdataenable);
|
||||
|
||||
/* Fragment packet */
|
||||
struct capwap_fragment_packet {
|
||||
void* buffer;
|
||||
int size;
|
||||
unsigned short offset;
|
||||
};
|
||||
|
||||
/* Fragment control list */
|
||||
struct capwap_fragment_sender {
|
||||
struct sockaddr_storage sendaddr;
|
||||
unsigned short fragment_id;
|
||||
int islastrecv;
|
||||
|
||||
/* Packet */
|
||||
struct capwap_header* header;
|
||||
struct capwap_list* packetlist;
|
||||
};
|
||||
|
||||
typedef struct capwap_list capwap_fragment_list;
|
||||
|
||||
/* Packet */
|
||||
struct capwap_packet {
|
||||
unsigned short packetsize;
|
||||
struct capwap_header* header;
|
||||
void* payload;
|
||||
struct sockaddr_storage localaddr;
|
||||
struct sockaddr_storage remoteaddr;
|
||||
struct capwap_socket socket;
|
||||
};
|
||||
|
||||
#define CAPWAP_WRONG_FRAGMENT -1
|
||||
#define CAPWAP_REQUEST_MORE_FRAGMENT 0
|
||||
#define CAPWAP_RECEIVE_COMPLETE_PACKET 1
|
||||
int capwap_defragment_packets(struct sockaddr_storage* sendaddr, void* buffer, int buffersize, capwap_fragment_list* defraglist, struct capwap_packet* packet);
|
||||
|
||||
capwap_fragment_list* capwap_defragment_init_list(void);
|
||||
void capwap_defragment_flush_list(capwap_fragment_list* defraglist);
|
||||
void capwap_defragment_free_list(capwap_fragment_list* defraglist);
|
||||
|
||||
int capwap_defragment_remove_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr);
|
||||
struct capwap_fragment_sender* capwap_defragment_find_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr);
|
||||
|
||||
void capwap_free_packet(struct capwap_packet* packet);
|
||||
|
||||
/* Build tx packet */
|
||||
struct capwap_build_packet {
|
||||
union {
|
||||
struct capwap_header header;
|
||||
char headerbuffer[CAPWAP_HEADER_MAX_SIZE];
|
||||
};
|
||||
|
||||
/* Control Packet */
|
||||
int isctrlmsg;
|
||||
union {
|
||||
struct capwap_control_message ctrlmsg;
|
||||
struct capwap_data_message datamsg;
|
||||
};
|
||||
|
||||
/* Message element */
|
||||
struct capwap_list* elementslist;
|
||||
};
|
||||
|
||||
#define CAPWAP_RADIOID_NONE 0
|
||||
#define CAPWAP_WIRELESS_BINDING_NONE 0
|
||||
#define CAPWAP_WIRELESS_BINDING_IEEE80211 1
|
||||
#define CAPWAP_WIRELESS_BINDING_EPCGLOBAL 3
|
||||
|
||||
struct capwap_build_packet* capwap_tx_packet_create(unsigned short radioid, unsigned short binding);
|
||||
struct capwap_build_packet* capwap_rx_packet_create(void* buffer, int buffersize, int isctrlpacket);
|
||||
void capwap_build_packet_free(struct capwap_build_packet* buildpacket);
|
||||
void capwap_build_packet_set_radio_macaddress(struct capwap_build_packet* buildpacket, int radiotype, char* macaddress);
|
||||
void capwap_build_packet_set_wireless_information(struct capwap_build_packet* buildpacket, void* buffer, unsigned char length);
|
||||
void capwap_build_packet_set_control_message_type(struct capwap_build_packet* buildpacket, unsigned long type, unsigned char seq);
|
||||
void capwap_build_packet_add_message_element(struct capwap_build_packet* buildpacket, struct capwap_message_element* element);
|
||||
|
||||
#define CAPWAP_VALID_PACKET 0x00000000
|
||||
#define CAPWAP_MISSING_MANDATORY_MSG_ELEMENT 0x00000001
|
||||
#define CAPWAP_UNRECOGNIZED_MSG_ELEMENT 0x00000002
|
||||
|
||||
struct unrecognized_info {
|
||||
unsigned short element;
|
||||
unsigned char reason;
|
||||
};
|
||||
|
||||
typedef struct capwap_array capwap_unrecognized_element_array;
|
||||
unsigned long capwap_build_packet_validate(struct capwap_build_packet* buildpacket, capwap_unrecognized_element_array* reasonarray);
|
||||
|
||||
typedef struct capwap_array capwap_fragment_packet_array;
|
||||
int capwap_fragment_build_packet(struct capwap_build_packet* buildpacket, capwap_fragment_packet_array* packets, unsigned short mtu, unsigned short fragmentid);
|
||||
void capwap_fragment_free(capwap_fragment_packet_array* packets);
|
||||
|
||||
int capwap_is_request_type(unsigned long type);
|
||||
void capwap_get_packet_digest(void* buffer, unsigned long length, unsigned char packetdigest[16]);
|
||||
int capwap_recv_retrasmitted_request(struct capwap_dtls* dtls, struct capwap_packet* packet, unsigned char lastseqnumber, unsigned char packetdigest[16], struct capwap_socket* sock, capwap_fragment_packet_array* txfragmentpacket, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
||||
|
||||
int capwap_check_message_type(struct capwap_dtls* dtls, struct capwap_packet* packet, unsigned short mtu);
|
||||
|
||||
int capwap_get_sessionid_from_keepalive(struct capwap_build_packet* buildpacket, struct capwap_sessionid_element* session);
|
||||
|
||||
#endif /* __CAPWAP_PROTOCOL_HEADER__ */
|
264
src/common/md5.c
Normal file
264
src/common/md5.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
** md5.c **
|
||||
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* -- include the following line if the md5.h header file is separate -- */
|
||||
#include "md5.h"
|
||||
|
||||
/* forward declaration */
|
||||
static void Transform(UINT4* buf, UINT4* in);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* F, G and H are basic MD5 functions: selection, majority, parity */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
void MD5Init(MD5_CTX* mdContext)
|
||||
{
|
||||
mdContext->i[0] = mdContext->i[1] = (UINT4)0;
|
||||
|
||||
/* Load magic initialization constants.
|
||||
*/
|
||||
mdContext->buf[0] = (UINT4)0x67452301;
|
||||
mdContext->buf[1] = (UINT4)0xefcdab89;
|
||||
mdContext->buf[2] = (UINT4)0x98badcfe;
|
||||
mdContext->buf[3] = (UINT4)0x10325476;
|
||||
}
|
||||
|
||||
void MD5Update(MD5_CTX* mdContext, unsigned char* inBuf, unsigned int inLen)
|
||||
{
|
||||
UINT4 in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* update number of bits */
|
||||
if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
|
||||
mdContext->i[1]++;
|
||||
mdContext->i[0] += ((UINT4)inLen << 3);
|
||||
mdContext->i[1] += ((UINT4)inLen >> 29);
|
||||
|
||||
while (inLen--) {
|
||||
/* add new character to buffer, increment mdi */
|
||||
mdContext->in[mdi++] = *inBuf++;
|
||||
|
||||
/* transform if necessary */
|
||||
if (mdi == 0x40) {
|
||||
for (i = 0, ii = 0; i < 16; i++, ii += 4)
|
||||
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
|
||||
(((UINT4)mdContext->in[ii+2]) << 16) |
|
||||
(((UINT4)mdContext->in[ii+1]) << 8) |
|
||||
((UINT4)mdContext->in[ii]);
|
||||
Transform (mdContext->buf, in);
|
||||
mdi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MD5Final(MD5_CTX* mdContext)
|
||||
{
|
||||
UINT4 in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
unsigned int padLen;
|
||||
|
||||
/* save number of bits */
|
||||
in[14] = mdContext->i[0];
|
||||
in[15] = mdContext->i[1];
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* pad out to 56 mod 64 */
|
||||
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
|
||||
MD5Update (mdContext, PADDING, padLen);
|
||||
|
||||
/* append length in bits and transform */
|
||||
for (i = 0, ii = 0; i < 14; i++, ii += 4)
|
||||
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
|
||||
(((UINT4)mdContext->in[ii+2]) << 16) |
|
||||
(((UINT4)mdContext->in[ii+1]) << 8) |
|
||||
((UINT4)mdContext->in[ii]);
|
||||
Transform (mdContext->buf, in);
|
||||
|
||||
/* store buffer in digest */
|
||||
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
|
||||
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
|
||||
mdContext->digest[ii+1] =
|
||||
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
|
||||
mdContext->digest[ii+2] =
|
||||
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
|
||||
mdContext->digest[ii+3] =
|
||||
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Basic MD5 step. Transform buf based on in.
|
||||
*/
|
||||
static void Transform(UINT4* buf, UINT4* in)
|
||||
{
|
||||
UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
/* Round 1 */
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
|
||||
FF ( a, b, c, d, in[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF ( d, a, b, c, in[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF ( c, d, a, b, in[ 2], S13, 0x242070db); /* 3 */
|
||||
FF ( b, c, d, a, in[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF ( a, b, c, d, in[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF ( d, a, b, c, in[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF ( c, d, a, b, in[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF ( b, c, d, a, in[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF ( a, b, c, d, in[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF ( d, a, b, c, in[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF ( c, d, a, b, in[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF ( b, c, d, a, in[11], S14, 0x895cd7be); /* 12 */
|
||||
FF ( a, b, c, d, in[12], S11, 0x6b901122); /* 13 */
|
||||
FF ( d, a, b, c, in[13], S12, 0xfd987193); /* 14 */
|
||||
FF ( c, d, a, b, in[14], S13, 0xa679438e); /* 15 */
|
||||
FF ( b, c, d, a, in[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
GG ( a, b, c, d, in[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG ( d, a, b, c, in[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG ( c, d, a, b, in[11], S23, 0x265e5a51); /* 19 */
|
||||
GG ( b, c, d, a, in[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG ( a, b, c, d, in[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG ( d, a, b, c, in[10], S22, 0x02441453); /* 22 */
|
||||
GG ( c, d, a, b, in[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG ( b, c, d, a, in[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG ( a, b, c, d, in[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG ( d, a, b, c, in[14], S22, 0xc33707d6); /* 26 */
|
||||
GG ( c, d, a, b, in[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG ( b, c, d, a, in[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG ( a, b, c, d, in[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG ( d, a, b, c, in[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG ( c, d, a, b, in[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG ( b, c, d, a, in[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
HH ( a, b, c, d, in[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH ( d, a, b, c, in[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH ( c, d, a, b, in[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH ( b, c, d, a, in[14], S34, 0xfde5380c); /* 36 */
|
||||
HH ( a, b, c, d, in[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH ( d, a, b, c, in[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH ( c, d, a, b, in[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH ( b, c, d, a, in[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH ( a, b, c, d, in[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH ( d, a, b, c, in[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH ( c, d, a, b, in[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH ( b, c, d, a, in[ 6], S34, 0x04881d05); /* 44 */
|
||||
HH ( a, b, c, d, in[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH ( d, a, b, c, in[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH ( c, d, a, b, in[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH ( b, c, d, a, in[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
II ( a, b, c, d, in[ 0], S41, 0xf4292244); /* 49 */
|
||||
II ( d, a, b, c, in[ 7], S42, 0x432aff97); /* 50 */
|
||||
II ( c, d, a, b, in[14], S43, 0xab9423a7); /* 51 */
|
||||
II ( b, c, d, a, in[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II ( a, b, c, d, in[12], S41, 0x655b59c3); /* 53 */
|
||||
II ( d, a, b, c, in[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II ( c, d, a, b, in[10], S43, 0xffeff47d); /* 55 */
|
||||
II ( b, c, d, a, in[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II ( a, b, c, d, in[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II ( d, a, b, c, in[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II ( c, d, a, b, in[ 6], S43, 0xa3014314); /* 59 */
|
||||
II ( b, c, d, a, in[13], S44, 0x4e0811a1); /* 60 */
|
||||
II ( a, b, c, d, in[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II ( d, a, b, c, in[11], S42, 0xbd3af235); /* 62 */
|
||||
II ( c, d, a, b, in[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II ( b, c, d, a, in[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
53
src/common/md5.h
Normal file
53
src/common/md5.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
** md5.h -- Header file for implementation of MD5 **
|
||||
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
|
||||
** Revised (for MD5): RLR 4/27/91 **
|
||||
** -- G modified to have y&~z instead of y&z **
|
||||
** -- FF, GG, HH modified to add in last register done **
|
||||
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
|
||||
** -- distinct additive constant for each step **
|
||||
** -- round 4 added, working mod 7 **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* typedef a 32 bit type */
|
||||
typedef unsigned long int UINT4;
|
||||
|
||||
/* Data structure for MD5 (Message Digest) computation */
|
||||
typedef struct {
|
||||
UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
|
||||
UINT4 buf[4]; /* scratch buffer */
|
||||
unsigned char in[64]; /* input buffer */
|
||||
unsigned char digest[16]; /* actual digest after MD5Final call */
|
||||
} MD5_CTX;
|
||||
|
||||
void MD5Init(MD5_CTX* mdContext);
|
||||
void MD5Update(MD5_CTX* mdContext, unsigned char* inBuf, unsigned int inLen);
|
||||
void MD5Final(MD5_CTX* mdContext);
|
13
src/common/startap.txt
Normal file
13
src/common/startap.txt
Normal file
@ -0,0 +1,13 @@
|
||||
init
|
||||
deinit
|
||||
getcapability
|
||||
setcountry
|
||||
setfrequency
|
||||
setrts
|
||||
setfragment
|
||||
settxqueue
|
||||
addap
|
||||
deleteap
|
||||
addstation
|
||||
removestation
|
||||
getstat
|
Reference in New Issue
Block a user