First commit

This commit is contained in:
vemax78
2013-05-01 14:52:55 +02:00
commit 7dd6d43954
148 changed files with 32283 additions and 0 deletions

655
src/ac/ac.c Normal file
View File

@ -0,0 +1,655 @@
#include "ac.h"
#include "capwap_dtls.h"
#include <libconfig.h>
#ifndef CAPWAP_MULTITHREADING_ENABLE
#error "AC request multithreading\n"
#endif
struct ac_t g_ac;
#define AC_STANDARD_NAME "Unknown AC"
/* Local param */
static char g_configurationfile[260] = AC_DEFAULT_CONFIGURATION_FILE;
/* Alloc AC */
static int ac_init(void) {
/* Network */
capwap_network_init(&g_ac.net);
g_ac.mtu = CAPWAP_MTU_DEFAULT;
g_ac.binding = capwap_array_create(sizeof(unsigned short), 0);
/* Standard name */
strcpy(g_ac.acname.name, AC_STANDARD_NAME);
/* Descriptor */
g_ac.descriptor.stationlimit = AC_DEFAULT_MAXSTATION;
g_ac.descriptor.wtplimit = AC_DEFAULT_MAXSESSIONS;
g_ac.descriptor.security = 0;
g_ac.descriptor.rmacfield = CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED;
g_ac.descriptor.dtlspolicy = CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
g_ac.descriptor.descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0);
/* */
g_ac.dfa.ecn.flag = CAPWAP_LIMITED_ECN_SUPPORT;
g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
/* */
g_ac.dfa.timers.discovery = AC_DEFAULT_DISCOVERY_INTERVAL;
g_ac.dfa.timers.echorequest = AC_DEFAULT_ECHO_INTERVAL;
g_ac.dfa.decrypterrorreport_interval = AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL;
g_ac.dfa.idletimeout.timeout = AC_DEFAULT_IDLE_TIMEOUT_INTERVAL;
g_ac.dfa.wtpfallback.mode = AC_DEFAULT_WTP_FALLBACK_MODE;
/* */
g_ac.dfa.acipv4list = capwap_array_create(sizeof(struct capwap_acipv4list_element), 0);
g_ac.dfa.acipv6list = capwap_array_create(sizeof(struct capwap_acipv6list_element), 0);
/* */
g_ac.dfa.rfcWaitJoin = AC_DEFAULT_WAITJOIN_INTERVAL;
g_ac.dfa.rfcWaitDTLS = AC_DEFAULT_WAITDTLS_INTERVAL;
g_ac.dfa.rfcChangeStatePendingTimer = AC_DEFAULT_CHANGE_STATE_PENDING_TIMER;
g_ac.dfa.rfcDataCheckTimer = AC_DEFAULT_DATA_CHECK_TIMER;
/* Sessions */
capwap_event_init(&g_ac.changesessionlist);
g_ac.sessions = capwap_list_create();
capwap_lock_init(&g_ac.sessionslock);
g_ac.datasessionshandshake = capwap_list_create();
return 1;
}
/* Destroy AC */
static void ac_destroy(void) {
/* Dtls */
capwap_crypt_freecontext(&g_ac.dtlscontext);
/* */
capwap_array_free(g_ac.descriptor.descsubelement);
capwap_array_free(g_ac.binding);
/* */
capwap_array_free(g_ac.dfa.acipv4list);
capwap_array_free(g_ac.dfa.acipv6list);
/* Sessions */
capwap_list_free(g_ac.sessions);
capwap_lock_destroy(&g_ac.sessionslock);
capwap_event_destroy(&g_ac.changesessionlist);
capwap_list_free(g_ac.datasessionshandshake);
}
/* Help */
static void ac_print_usage(void) {
}
/* Parsing configuration */
static int ac_parsing_configuration_1_0(config_t* config) {
int i;
int configInt;
int configIPv4;
int configIPv6;
long int configLongInt;
const char* configString;
config_setting_t* configSetting;
/* Logging configuration */
if (config_lookup_bool(config, "logging.enable", &configInt) == CONFIG_TRUE) {
if (!configInt) {
capwap_logging_verboselevel(CAPWAP_LOGGING_NONE);
capwap_logging_disable_allinterface();
} else {
if (config_lookup_string(config, "logging.level", &configString) == CONFIG_TRUE) {
if (!strcmp(configString, "fatal")) {
capwap_logging_verboselevel(CAPWAP_LOGGING_FATAL);
} else if (!strcmp(configString, "error")) {
capwap_logging_verboselevel(CAPWAP_LOGGING_ERROR);
} else if (!strcmp(configString, "warning")) {
capwap_logging_verboselevel(CAPWAP_LOGGING_WARNING);
} else if (!strcmp(configString, "info")) {
capwap_logging_verboselevel(CAPWAP_LOGGING_INFO);
} else if (!strcmp(configString, "debug")) {
capwap_logging_verboselevel(CAPWAP_LOGGING_DEBUG);
} else {
capwap_logging_error("Invalid configuration file, unknown logging.level value");
return 0;
}
}
/* Logging output interface */
configSetting = config_lookup(config, "logging.output");
if (configSetting != NULL) {
int count = config_setting_length(configSetting);
/* Disable output interface */
capwap_logging_disable_allinterface();
/* Enable selected interface */
for (i = 0; i < count; i++) {
config_setting_t* configElement = config_setting_get_elem(configSetting, i);
if ((configElement != NULL) && (config_setting_lookup_string(configElement, "mode", &configString) == CONFIG_TRUE)) {
if (!strcmp(configString, "stdout")) {
capwap_logging_enable_console(0);
} else if (!strcmp(configString, "stderr")) {
capwap_logging_enable_console(1);
} else {
capwap_logging_error("Invalid configuration file, unknown logging.output value");
return 0;
}
}
}
}
}
}
/* Set name of AC */
if (config_lookup_string(config, "application.name", &configString) == CONFIG_TRUE) {
if (strlen(configString) > CAPWAP_ACNAME_MAXLENGTH) {
capwap_logging_error("Invalid configuration file, application.name string length exceeded");
return 0;
}
strcpy(g_ac.acname.name, configString);
}
/* Set binding of AC */
configSetting = config_lookup(config, "application.binding");
if (configSetting != NULL) {
int count = config_setting_length(configSetting);
for (i = 0; i < count; i++) {
const char* bindingName = config_setting_get_string_elem(configSetting, i);
if (bindingName != NULL) {
unsigned short* binding = (unsigned short*)capwap_array_get_item_pointer(g_ac.binding, g_ac.binding->count);
if (!strcmp(bindingName, "802.11")) {
*binding = CAPWAP_WIRELESS_BINDING_IEEE80211;
} else if (!strcmp(bindingName, "EPCGlobal")) {
*binding = CAPWAP_WIRELESS_BINDING_EPCGLOBAL;
} else {
capwap_logging_error("Invalid configuration file, unknown application.binding value");
return 0;
}
}
}
}
/* Set max stations of AC */
if (config_lookup_int(config, "application.descriptor.maxstations", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt > 0) && (configLongInt < 65536)) {
g_ac.descriptor.stationlimit = (unsigned short)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, unknown application.descriptor.maxstations value");
return 0;
}
}
/* Set max wtp of AC */
if (config_lookup_int(config, "application.descriptor.maxwtp", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt > 0) && (configLongInt < 65536)) {
g_ac.descriptor.wtplimit = (unsigned short)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, unknown application.descriptor.maxwtp value");
return 0;
}
}
/* Set security of AC */
if (config_lookup(config, "application.descriptor.security") != NULL) {
g_ac.descriptor.security = 0;
if (config_lookup_bool(config, "application.descriptor.security.presharedkey", &configInt) == CONFIG_TRUE) {
if (configInt != 0) {
g_ac.descriptor.security |= CAPWAP_ACDESC_SECURITY_PRESHARED_KEY;
}
}
if (config_lookup_bool(config, "application.descriptor.security.x509", &configInt) == CONFIG_TRUE) {
if (configInt != 0) {
g_ac.descriptor.security |= CAPWAP_ACDESC_SECURITY_X509_CERT;
}
}
}
/* Set rmacfiled of AC */
if (config_lookup_bool(config, "application.descriptor.rmacfiled.supported", &configInt) == CONFIG_TRUE) {
g_ac.descriptor.rmacfield = ((configInt != 0) ? CAPWAP_ACDESC_RMACFIELD_SUPPORTED : CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED);
}
/* Set DTLS policy of AC */
if (config_lookup(config, "application.descriptor.dtlspolicy") != NULL) {
g_ac.descriptor.dtlspolicy = 0;
if (config_lookup_bool(config, "application.descriptor.dtlspolicy.cleardatachannel", &configInt) == CONFIG_TRUE) {
if (configInt != 0) {
g_ac.descriptor.dtlspolicy |= CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
}
}
if (config_lookup_bool(config, "application.descriptor.dtlspolicy.dtlsdatachannel", &configInt) == CONFIG_TRUE) {
if (configInt != 0) {
g_ac.descriptor.dtlspolicy |= CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED;
}
}
}
/* Set info descriptor of AC */
configSetting = config_lookup(config, "application.descriptor.info");
if (configSetting != NULL) {
int count = config_setting_length(configSetting);
for (i = 0; i < count; i++) {
config_setting_t* configElement = config_setting_get_elem(configSetting, i);
if (configElement != NULL) {
long int configVendor;
if (config_setting_lookup_int(configElement, "idvendor", &configVendor) == CONFIG_TRUE) {
const char* configType;
if (config_setting_lookup_string(configElement, "type", &configType) == CONFIG_TRUE) {
const char* configValue;
if (config_setting_lookup_string(configElement, "value", &configValue) == CONFIG_TRUE) {
int lengthValue = strlen(configValue);
if (lengthValue < CAPWAP_ACDESC_SUBELEMENT_MAXDATA) {
unsigned short type;
struct capwap_acdescriptor_desc_subelement* desc;
if (!strcmp(configType, "hardware")) {
type = CAPWAP_ACDESC_SUBELEMENT_HARDWAREVERSION;
} else if (!strcmp(configType, "software")) {
type = CAPWAP_ACDESC_SUBELEMENT_SOFTWAREVERSION;
} else {
capwap_logging_error("Invalid configuration file, unknown application.descriptor.info.type value");
return 0;
}
desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(g_ac.descriptor.descsubelement, g_ac.descriptor.descsubelement->count);
desc->vendor = (unsigned long)configVendor;
desc->type = type;
desc->length = lengthValue;
strcpy(desc->data, configValue);
} else {
capwap_logging_error("Invalid configuration file, application.descriptor.info.value string length exceeded");
return 0;
}
} else {
capwap_logging_error("Invalid configuration file, element application.descriptor.info.value not found");
return 0;
}
} else {
capwap_logging_error("Invalid configuration file, element application.descriptor.info.type not found");
return 0;
}
} else {
capwap_logging_error("Invalid configuration file, element application.descriptor.info.idvendor not found");
return 0;
}
}
}
}
/* Set ECN of AC */
if (config_lookup_string(config, "application.ecn", &configString) == CONFIG_TRUE) {
if (!strcmp(configString, "full")) {
g_ac.dfa.ecn.flag = CAPWAP_FULL_ECN_SUPPORT;
} else if (!strcmp(configString, "limited")) {
g_ac.dfa.ecn.flag = CAPWAP_LIMITED_ECN_SUPPORT;
} else {
capwap_logging_error("Invalid configuration file, unknown application.ecn value");
return 0;
}
}
/* Set Timer of AC */
if (config_lookup_int(config, "application.timer.discovery", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt >= AC_DEFAULT_DISCOVERY_INTERVAL) && (configLongInt <= AC_MAX_DISCOVERY_INTERVAL)) {
g_ac.dfa.timers.discovery = (unsigned char)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, invalid application.timer.discovery value");
return 0;
}
}
if (config_lookup_int(config, "application.timer.echorequest", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt > 0) && (configLongInt < AC_MAX_ECHO_INTERVAL)) {
g_ac.dfa.timers.echorequest = (unsigned char)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, invalid application.timer.echorequest value");
return 0;
}
}
if (config_lookup_int(config, "application.timer.decrypterrorreport", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt > 0) && (configLongInt < 65536)) {
g_ac.dfa.decrypterrorreport_interval = (unsigned short)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, invalid application.timer.decrypterrorreport value");
return 0;
}
}
if (config_lookup_int(config, "application.timer.idletimeout", &configLongInt) == CONFIG_TRUE) {
if (configLongInt > 0) {
g_ac.dfa.idletimeout.timeout = (unsigned long)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, invalid application.timer.idletimeout value");
return 0;
}
}
/* Set wtpfallback of AC */
if (config_lookup_bool(config, "application.wtpfallback", &configInt) == CONFIG_TRUE) {
g_ac.dfa.wtpfallback.mode = ((configInt != 0) ? CAPWAP_WTP_FALLBACK_ENABLED : CAPWAP_WTP_FALLBACK_DISABLED);
}
/* Set DTLS of WTP */
if (config_lookup_bool(config, "application.dtls.enable", &configInt) == CONFIG_TRUE) {
if (configInt != 0) {
struct capwap_dtls_param dtlsparam;
/* Init dtls param */
memset(&dtlsparam, 0, sizeof(struct capwap_dtls_param));
dtlsparam.type = CAPWAP_DTLS_SERVER;
/* Set DTLS type of AC */
if (config_lookup_string(config, "application.dtls.type", &configString) == CONFIG_TRUE) {
if (!strcmp(configString, "x509")) {
dtlsparam.mode = CAPWAP_DTLS_MODE_CERTIFICATE;
} else if (!strcmp(configString, "presharedkey")) {
dtlsparam.mode = CAPWAP_DTLS_MODE_PRESHAREDKEY;
} else {
capwap_logging_error("Invalid configuration file, unknown application.dtls.type value");
return 0;
}
}
/* Set DTLS configuration of AC */
if (dtlsparam.mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
if (config_lookup_string(config, "application.dtls.x509.calist", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
dtlsparam.cert.fileca = capwap_duplicate_string(configString);
}
}
if (config_lookup_string(config, "application.dtls.x509.certificate", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
dtlsparam.cert.filecert = capwap_duplicate_string(configString);
}
}
if (config_lookup_string(config, "application.dtls.x509.privatekey", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
dtlsparam.cert.filekey = capwap_duplicate_string(configString);
}
}
if (config_lookup_string(config, "application.dtls.x509.privatekeypassword", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
dtlsparam.cert.pwdprivatekey = capwap_duplicate_string(configString);
}
}
if (dtlsparam.cert.fileca && dtlsparam.cert.filecert && dtlsparam.cert.filekey) {
if (capwap_crypt_createcontext(&g_ac.dtlscontext, &dtlsparam)) {
g_ac.enabledtls = 1;
}
}
/* Free dtls param */
if (dtlsparam.cert.fileca) {
capwap_free(dtlsparam.cert.fileca);
}
if (dtlsparam.cert.filecert) {
capwap_free(dtlsparam.cert.filecert);
}
if (dtlsparam.cert.filekey) {
capwap_free(dtlsparam.cert.filekey);
}
if (dtlsparam.cert.pwdprivatekey) {
capwap_free(dtlsparam.cert.pwdprivatekey);
}
if (!g_ac.enabledtls) {
return 0;
}
} else if (dtlsparam.mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
/* TODO */
}
}
}
/* Set interface binding of AC */
if (config_lookup_string(config, "application.network.binding", &configString) == CONFIG_TRUE) {
if (strlen(configString) > (IFNAMSIZ - 1)) {
capwap_logging_error("Invalid configuration file, application.network.binding string length exceeded");
return 0;
}
strcpy(g_ac.net.bind_interface, configString);
}
/* Set mtu of AC */
if (config_lookup_int(config, "application.network.mtu", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt > 0) && (configLongInt < 65536)) {
g_ac.mtu = (unsigned short)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, invalid application.network.mtu value");
return 0;
}
}
/* Set transport of AC */
if (config_lookup_string(config, "application.network.transport", &configString) == CONFIG_TRUE) {
if (!strcmp(configString, "udp")) {
g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
} else if (!strcmp(configString, "udplite")) {
g_ac.dfa.transport.type = CAPWAP_UDPLITE_TRANSPORT;
} else {
capwap_logging_error("Invalid configuration file, unknown application.network.transport value");
return 0;
}
}
/* Set ipv4 & ipv6 of AC */
if (config_lookup_bool(config, "application.network.ipv4", &configIPv4) != CONFIG_TRUE) {
configIPv4 = 1;
}
if (config_lookup_bool(config, "application.network.ipv6", &configIPv6) != CONFIG_TRUE) {
configIPv6 = 1;
}
if (configIPv4 && configIPv6) {
g_ac.net.sock_family = AF_UNSPEC;
} else if (!configIPv4 && !configIPv6) {
capwap_logging_error("Invalid configuration file, request enable application.network.ipv4 or application.network.ipv6");
return 0;
} else {
g_ac.net.sock_family = (configIPv4 ? AF_INET : AF_INET6);
}
/* Set ip dual stack of WTP */
if (config_lookup_bool(config, "application.network.ipdualstack", &configInt) == CONFIG_TRUE) {
if (!configInt) {
g_ac.net.bind_ctrl_flags |= CAPWAP_IPV6ONLY_FLAG;
g_ac.net.bind_data_flags |= CAPWAP_IPV6ONLY_FLAG;
} else {
g_ac.net.bind_ctrl_flags &= ~CAPWAP_IPV6ONLY_FLAG;
g_ac.net.bind_data_flags &= ~CAPWAP_IPV6ONLY_FLAG;
}
}
return 1;
}
/* Parsing configuration */
static int ac_parsing_configuration(config_t* config) {
const char* configString;
if (config_lookup_string(config, "version", &configString) == CONFIG_TRUE) {
if (strcmp(configString, "1.0") == 0) {
return ac_parsing_configuration_1_0(config);
}
capwap_logging_error("Invalid configuration file, '%s' is not supported", configString);
} else {
capwap_logging_error("Invalid configuration file, unable to found version tag");
}
return 0;
}
/* Load configuration */
static int ac_load_configuration(int argc, char** argv) {
int c;
int result = 0;
config_t config;
ASSERT(argc >= 0);
ASSERT(argv != NULL);
/* Parsing command line */
opterr = 0;
while ((c = getopt(argc, argv, "hc:")) != -1) {
switch (c) {
case 'h': {
ac_print_usage();
return 0;
}
case 'c': {
if (strlen(optarg) < sizeof(g_configurationfile)) {
strcpy(g_configurationfile, optarg);
} else {
capwap_logging_error("Invalid -%c argument", optopt);
return -1;
}
break;
}
case '?': {
if (optopt == 'c') {
capwap_logging_error("Option -%c requires an argument", optopt);
} else {
capwap_logging_error("Unknown option character `\\x%x'", optopt);
}
ac_print_usage();
return -1;
}
}
}
/* Init libconfig */
config_init(&config);
/* Load configuration */
if (config_read_file(&config, g_configurationfile) == CONFIG_TRUE) {
result = ac_parsing_configuration(&config);
} else {
result = -1;
capwap_logging_error("Unable load the configuration file '%s': %s (%d)", g_configurationfile, config_error_text(&config), config_error_line(&config));
}
/* Free libconfig */
config_destroy(&config);
return result;
}
/* Init AC */
static int ac_configure(void) {
/* Bind to any address */
if (!capwap_bind_sockets(&g_ac.net)) {
capwap_logging_fatal("Cannot bind address");
return AC_ERROR_NETWORK;
}
return CAPWAP_SUCCESSFUL;
}
/* Close AC */
static void ac_close(void) {
ASSERT(g_ac.sessions->count == 0);
/* Close socket */
capwap_close_sockets(&g_ac.net);
}
/* Check is valid binding */
int ac_valid_binding(unsigned short binding) {
int i;
for (i = 0; i < g_ac.binding->count; i++) {
if (binding == *(unsigned short*)capwap_array_get_item_pointer(g_ac.binding, i)) {
return 1;
}
}
return 0;
}
/* Main*/
int main(int argc, char** argv) {
int value;
int result = CAPWAP_SUCCESSFUL;
/* Init logging */
capwap_logging_init();
capwap_logging_verboselevel(CAPWAP_LOGGING_ERROR);
capwap_logging_enable_console(1);
/* Init capwap */
if (geteuid() != 0) {
capwap_logging_fatal("Request root privileges");
return CAPWAP_REQUEST_ROOT;
}
/* Init random generator */
capwap_init_rand();
/* Init crypt */
if (!capwap_crypt_init()) {
capwap_logging_fatal("Error to init crypt engine");
return CAPWAP_CRYPT_ERROR;
}
/* Alloc AC */
if (!ac_init()) {
return AC_ERROR_SYSTEM_FAILER;
}
/* Read configuration file */
value = ac_load_configuration(argc, argv);
if (value < 0) {
result = AC_ERROR_LOAD_CONFIGURATION;
} else if (value > 0) {
/* Complete configuration AC */
result = ac_configure();
if (result == CAPWAP_SUCCESSFUL) {
/* Running AC */
result = ac_execute();
ac_close();
}
}
/* Free memory */
ac_destroy();
/* Free crypt */
capwap_crypt_free();
/* Check memory leak */
if (capwap_check_memory_leak(1)) {
if (result == CAPWAP_SUCCESSFUL)
result = AC_ERROR_MEMORY_LEAK;
}
/* Close logging */
capwap_logging_close();
return result;
}

117
src/ac/ac.h Normal file
View File

@ -0,0 +1,117 @@
#ifndef __CAPWAP_AC_HEADER__
#define __CAPWAP_AC_HEADER__
/* standard include */
#include "capwap.h"
#include "capwap_network.h"
#include "capwap_protocol.h"
#include "capwap_lock.h"
#include "capwap_list.h"
#include "capwap_event.h"
#include "capwap_element.h"
#include <pthread.h>
/* AC Configuration */
#define AC_DEFAULT_CONFIGURATION_FILE "/etc/capwap/ac.conf"
#define AC_DEFAULT_MAXSTATION 128
#define AC_DEFAULT_MAXSESSIONS 128
/* AC runtime error return code */
#define AC_ERROR_SYSTEM_FAILER -1000
#define AC_ERROR_LOAD_CONFIGURATION -1001
#define AC_ERROR_NETWORK -1002
#define AC_ERROR_MEMORY_LEAK 1
/* Min and max dfa values */
#define AC_MIN_WAITDTLS_INTERVAL 30
#define AC_DEFAULT_WAITDTLS_INTERVAL 60
#define AC_MIN_WAITJOIN_INTERVAL 20
#define AC_DEFAULT_WAITJOIN_INTERVAL 60
#define AC_DEFAULT_CHANGE_STATE_PENDING_TIMER 25
#define AC_MIN_DISCOVERY_INTERVAL 2
#define AC_DEFAULT_DISCOVERY_INTERVAL 20
#define AC_MAX_DISCOVERY_INTERVAL 180
#define AC_DEFAULT_ECHO_INTERVAL 30
#define AC_MAX_ECHO_INTERVAL 256
#define AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL 120
#define AC_DEFAULT_IDLE_TIMEOUT_INTERVAL 300
#define AC_DEFAULT_WTP_FALLBACK_MODE CAPWAP_WTP_FALLBACK_ENABLED
#define AC_DEFAULT_DATA_CHECK_TIMER 30
#define AC_DEFAULT_RETRANSMIT_INTERVAL 3
#define AC_MAX_RETRANSMIT 5
#define AC_DEFAULT_DTLS_SESSION_DELETE 5
/* AC DFA */
struct ac_state {
/* */
struct capwap_ecnsupport_element ecn;
struct capwap_transport_element transport;
struct capwap_timers_element timers;
unsigned short decrypterrorreport_interval;
struct capwap_idletimeout_element idletimeout;
struct capwap_wtpfallback_element wtpfallback;
/* */
capwap_acipv4list_element_array* acipv4list;
capwap_acipv6list_element_array* acipv6list;
/* */
int rfcWaitJoin;
int rfcChangeStatePendingTimer;
int rfcDataCheckTimer;
int rfcDTLSSessionDelete;
/* Request retransmit */
int rfcRetransmitInterval;
int rfcRetransmitCount;
int rfcMaxRetransmit;
/* Dtls */
int rfcWaitDTLS;
};
/* Handshake DTLS Data Channel */
struct ac_data_session_handshake {
struct capwap_socket socket;
struct sockaddr_storage acaddress;
struct sockaddr_storage wtpaddress;
struct capwap_dtls dtls;
};
/* AC */
struct ac_t {
int running;
/* */
struct ac_state dfa;
struct capwap_network net;
unsigned short mtu;
struct capwap_array* binding;
struct capwap_acname_element acname;
struct capwap_acdescriptor_element descriptor;
/* Sessions */
capwap_event_t changesessionlist;
struct capwap_list* sessions;
capwap_lock_t sessionslock;
struct capwap_list* datasessionshandshake;
/* Dtls */
int enabledtls;
struct capwap_dtls_context dtlscontext;
};
extern struct ac_t g_ac;
/* Primary thread */
int ac_execute(void);
int ac_valid_binding(unsigned short binding);
void ac_update_statistics(void);
#endif /* __CAPWAP_AC_HEADER__ */

128
src/ac/ac_dfa_configure.c Normal file
View File

@ -0,0 +1,128 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet) {
unsigned long i;
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
unsigned short binding;
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CONFIGURATION_STATUS_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
struct capwap_element_configurationstatus_request configurationstatusrequest;
/* Configuration Status request info*/
capwap_init_element_configurationstatus_request(&configurationstatusrequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_configurationstatus_request(&configurationstatusrequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* responsepacket;
/* TODO: gestione richiesta */
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Prepare configuration status response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CONFIGURATION_STATUS_RESPONSE, buildpacket->ctrlmsg.seq);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TIMERS_ELEMENT(&session->dfa.timers));
for (i = 0; i < configurationstatusrequest.radioadmstatus->count; i++) {
struct capwap_decrypterrorreportperiod_element report;
struct capwap_radioadmstate_element* radioadm = (struct capwap_radioadmstate_element*)capwap_array_get_item_pointer(configurationstatusrequest.radioadmstatus, i);
report.radioid = radioadm->radioid;
report.interval = session->dfa.decrypterrorreport_interval;
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(&report));
}
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(&session->dfa.idletimeout));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_WTPFALLBACK_ELEMENT(&session->dfa.wtpfallback));
if (session->dfa.acipv4list->count > 0) {
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV4LIST_ELEMENT(session->dfa.acipv4list));
}
if (session->dfa.acipv6list->count > 0) {
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV6LIST_ELEMENT(session->dfa.acipv6list));
}
/* CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Send configuration status response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send configuration status response packet");
break;
}
}
/* Change status */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
capwap_set_timeout(session->dfa.rfcChangeStatePendingTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
} else {
capwap_logging_debug("Warning: build invalid configuration status response packet");
}
/* Free memory */
capwap_build_packet_free(responsepacket);
}
/* Free */
capwap_free_element_configurationstatus_request(&configurationstatusrequest, binding);
}
}
/* Free */
capwap_build_packet_free(buildpacket);
}
} else {
/* Configure timeout */
ac_dfa_change_state(session, CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
return status;
}
/* */
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

169
src/ac/ac_dfa_datacheck.c Normal file
View File

@ -0,0 +1,169 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet) {
unsigned long i;
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
unsigned short binding;
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CHANGE_STATE_EVENT_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
struct capwap_element_changestateevent_request changeeventrequest;
/* Change event request info */
capwap_init_element_changestateevent_request(&changeeventrequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_changestateevent_request(&changeeventrequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* responsepacket;
/* TODO: gestione richiesta */
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Prepare change event response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, buildpacket->ctrlmsg.seq);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Send change event response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send change event response packet");
break;
}
}
/* Change status */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
capwap_set_timeout(session->dfa.rfcDataCheckTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
} else {
capwap_logging_debug("Warning: build invalid configuration status response packet");
}
/* Free memory */
capwap_build_packet_free(responsepacket);
}
/* Free */
capwap_free_element_changestateevent_request(&changeeventrequest, binding);
}
}
/* Free */
capwap_build_packet_free(buildpacket);
}
} else {
/* Configure timeout */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
return status;
}
/* */
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
/* Wait Data Channel Keep-Alive packet */
if (!packet->socket.isctrlsocket) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
struct capwap_sessionid_element sessionid;
if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
int result;
capwap_fragment_packet_array* txfragpacket;
/* Receive data packet keepalive, response with same packet */
txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0);
if (!result) {
struct capwap_packet* txpacket;
ASSERT(txfragpacket->count == 1);
txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) {
capwap_logging_debug("Warning: error to send data channel keepalive packet");
result = -1;
}
}
/* */
capwap_fragment_free(txfragpacket);
capwap_array_free(txfragpacket);
if (!result) {
/* Capwap handshake complete */
ac_dfa_change_state(session, CAPWAP_RUN_STATE);
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
}
}
/* Free */
capwap_build_packet_free(buildpacket);
}
}
} else {
/* Configure timeout */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
return status;
}
/* */
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

51
src/ac/ac_dfa_dtls.c Normal file
View File

@ -0,0 +1,51 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* DTLS BIO send */
int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param) {
struct ac_session_t* session = (struct ac_session_t*)param;
struct capwap_socket* socket = ((dtls->session == CAPWAP_DTLS_CONTROL_SESSION) ? &session->ctrlsocket : &session->datasocket);
struct sockaddr_storage* wtpaddress = ((dtls->session == CAPWAP_DTLS_CONTROL_SESSION) ? &session->wtpctrladdress : &session->wtpdataaddress);
struct sockaddr_storage* acaddress = ((dtls->session == CAPWAP_DTLS_CONTROL_SESSION) ? &session->acctrladdress : &session->acdataaddress);
return capwap_sendto(socket->socket[socket->type], buffer, length, acaddress, wtpaddress);
}
/* */
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
ASSERT(packet == NULL);
/* Create DTLS session */
if (!capwap_crypt_createsession(&session->ctrldtls, CAPWAP_DTLS_CONTROL_SESSION, &g_ac.dtlscontext, ac_bio_send, session)) {
ac_dfa_change_state(session, CAPWAP_DTLS_SETUP_TO_IDLE_STATE); /* TODO */
status = AC_DFA_NO_PACKET;
} else {
if (capwap_crypt_open(&session->ctrldtls, &session->wtpctrladdress) == CAPWAP_HANDSHAKE_ERROR) {
ac_dfa_change_state(session, CAPWAP_DTLS_SETUP_TO_IDLE_STATE); /* TODO */
status = AC_DFA_NO_PACKET;
} else {
ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_STATE);
}
}
return status;
}
/* */
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet == NULL);
ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE); /* TODO */
return AC_DFA_NO_PACKET;
}
/* */
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

18
src/ac/ac_dfa_imagedata.c Normal file
View File

@ -0,0 +1,18 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
/* TODO */
return status;
}
/* */
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

272
src/ac/ac_dfa_join.c Normal file
View File

@ -0,0 +1,272 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet) {
int i;
int status = AC_DFA_ACCEPT_PACKET;
struct capwap_resultcode_element resultcode = { CAPWAP_RESULTCODE_FAILURE };
struct capwap_build_packet* responsepacket;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
int validpacket;
unsigned long checkpacket;
struct capwap_array* returnedmessagearray = NULL;
capwap_unrecognized_element_array* unrecognizedarray;
struct capwap_element_join_request joinrequest;
unsigned short binding = GET_WBID_HEADER(&buildpacket->header);
/* */
unrecognizedarray = capwap_array_create(sizeof(struct unrecognized_info), 0);
/* */
checkpacket = capwap_build_packet_validate(buildpacket, unrecognizedarray);
if (!checkpacket) {
if (ac_valid_binding(binding)) {
if (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_JOIN_REQUEST) {
resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
} else {
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
}
} else {
if ((checkpacket & CAPWAP_MISSING_MANDATORY_MSG_ELEMENT) != 0) {
resultcode.code = CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT;
} else if ((checkpacket & CAPWAP_UNRECOGNIZED_MSG_ELEMENT) != 0) {
struct capwap_list_item* itemelement;
resultcode.code = CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT;
returnedmessagearray = capwap_array_create(sizeof(struct capwap_returnedmessage_element), unrecognizedarray->count);
for (i = 0; i < unrecognizedarray->count; i++) {
struct unrecognized_info* reasoninfo = capwap_array_get_item_pointer(unrecognizedarray, i);
/* Search element */
itemelement = buildpacket->elementslist->first;
while (itemelement != NULL) {
struct capwap_message_element* elementitem = (struct capwap_message_element*)itemelement->item;
if (ntohs(elementitem->type) == reasoninfo->element) {
struct capwap_returnedmessage_element* returnedelement = capwap_array_get_item_pointer(returnedmessagearray, i);
unsigned short length = sizeof(struct capwap_message_element) + ntohs(elementitem->length);
returnedelement->reason = reasoninfo->reason;
returnedelement->length = min(length, CAPWAP_RETURNED_MESSAGE_MAX_LENGTH);
memcpy(&returnedelement->message[0], elementitem, returnedelement->length);
break;
}
/* Next */
itemelement = itemelement->next;
}
}
}
}
/* */
capwap_array_free(unrecognizedarray);
/* */
capwap_init_element_join_request(&joinrequest, binding);
if (resultcode.code == CAPWAP_RESULTCODE_SUCCESS) {
/* Parsing elements list */
if (capwap_parsing_element_join_request(&joinrequest, buildpacket->elementslist->first)) {
/* TODO: gestione richiesta */
/* Get sessionid */
memcpy(&session->sessionid, joinrequest.sessionid, sizeof(struct capwap_sessionid_element));
/* Get binding */
session->binding = binding;
resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
}
}
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Prepare join response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_JOIN_RESPONSE, buildpacket->ctrlmsg.seq);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode));
/* Check is valid packet after parsing request */
validpacket = (((resultcode.code == CAPWAP_RESULTCODE_SUCCESS) || (resultcode.code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) ? 1 : 0);
if (validpacket) {
struct capwap_list* controllist;
struct capwap_list_item* item;
/* Update statistics */
ac_update_statistics();
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname));
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
for (i = 0; i < joinrequest.binding.ieee80211.wtpradioinformation->count; i++) {
struct capwap_80211_wtpradioinformation_element* radio;
radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(joinrequest.binding.ieee80211.wtpradioinformation, i);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio));
}
} else {
capwap_logging_debug("Unknown capwap binding");
}
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ECNSUPPORT_ELEMENT(&session->dfa.ecn));
/* Get information from any local address */
controllist = capwap_list_create();
ac_get_control_information(controllist);
for (item = controllist->first; item != NULL; item = item->next) {
struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
if (sessioncontrol->localaddress.ss_family == AF_INET) {
struct capwap_controlipv4_element element;
memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr));
element.wtpcount = sessioncontrol->count;
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element));
} else if (sessioncontrol->localaddress.ss_family == AF_INET6) {
struct capwap_controlipv6_element element;
memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr));
element.wtpcount = sessioncontrol->count;
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element));
}
}
capwap_list_free(controllist);
if (session->acctrladdress.ss_family == AF_INET) {
struct capwap_localipv4_element addr;
memcpy(&addr.address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV4_ELEMENT(&addr));
} else if (session->acctrladdress.ss_family == AF_INET6) {
struct capwap_localipv6_element addr;
memcpy(&addr.address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV6_ELEMENT(&addr));
}
/* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */ /* TODO */
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TRANSPORT_ELEMENT(&session->dfa.transport));
/* CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
} else if (resultcode.code == CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT) {
ASSERT(returnedmessagearray != NULL);
for (i = 0; i < returnedmessagearray->count; i++) {
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(capwap_array_get_item_pointer(returnedmessagearray, i)));
}
capwap_array_free(returnedmessagearray);
}
/* Validate packet */
if (!validpacket || !capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Send join response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send join response packet");
break;
}
}
}
} else {
capwap_logging_debug("Warning: build invalid join response packet");
}
/* Free memory */
capwap_build_packet_free(responsepacket);
capwap_free_element_join_request(&joinrequest, binding);
capwap_build_packet_free(buildpacket);
/* Change state */
if (validpacket) {
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
} else {
ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
}
} else {
/* Join timeout */
ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
return status;
}
/* */
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
unsigned short lengthpayload;
lengthpayload = packet->packetsize - GET_HLEN_HEADER(packet->header) * 4;
if (lengthpayload >= sizeof(struct capwap_control_message)) {
struct capwap_control_message* ctrlmsg = (struct capwap_control_message*)packet->payload;
unsigned long type = ntohl(ctrlmsg->type);
if (type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
status = ac_dfa_state_configure(session, packet);
} else if (type == CAPWAP_IMAGE_DATA_REQUEST) {
ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE);
status = ac_dfa_state_imagedata(session, packet);
}
}
} else {
/* Join timeout */
ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
return status;
}
/* */
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

81
src/ac/ac_dfa_reset.c Normal file
View File

@ -0,0 +1,81 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
if (!capwap_compare_ip(&session->wtpctrladdress, &packet->remoteaddr)) {
struct capwap_build_packet* buildpacket;
/* Parsing packet */
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
unsigned short binding;
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if ((binding == session->binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) {
struct capwap_element_reset_response resetresponse;
/* Valid packet, free request packet */
ac_free_reference_last_request(session);
/* Configuration status response info */
capwap_init_element_reset_response(&resetresponse, binding);
/* Parsing elements list */
if (capwap_parsing_element_reset_response(&resetresponse, buildpacket->elementslist->first)) {
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
/* Free join response */
capwap_free_element_reset_response(&resetresponse, binding);
}
}
/* Free */
capwap_build_packet_free(buildpacket);
}
}
} else {
int i;
/* No Configuration status response received */
session->dfa.rfcRetransmitCount++;
if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
/* Timeout join state */
ac_free_reference_last_request(session);
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
} else {
/* Retransmit configuration request */
for (i = 0; i < session->requestfragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
capwap_logging_debug("Warning: error to send configuration status request packet");
break;
}
}
/* Update timeout */
capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
}
return status;
}
/* */
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

263
src/ac/ac_dfa_run.c Normal file
View File

@ -0,0 +1,263 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
static int receive_echo_request(struct ac_session_t* session, struct capwap_build_packet* buildpacket, struct capwap_packet* packet) {
unsigned long i;
unsigned short binding;
ASSERT(session != NULL);
ASSERT(buildpacket != NULL);
ASSERT(packet != NULL);
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if (ac_valid_binding(binding) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
struct capwap_element_echo_request echorequest;
/* Echo request info*/
capwap_init_element_echo_request(&echorequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_echo_request(&echorequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* responsepacket;
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Prepare echo response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_ECHO_RESPONSE, buildpacket->ctrlmsg.seq);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Send echo response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send echo response packet");
break;
}
}
}
}
/* Free memory */
capwap_build_packet_free(responsepacket);
}
/* Free */
capwap_free_element_echo_request(&echorequest, binding);
}
return 0;
}
/* */
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
if (packet->socket.isctrlsocket) {
unsigned long typemsg = ntohl(buildpacket->ctrlmsg.type);
if (capwap_is_request_type(typemsg) || ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) {
switch (typemsg) {
case CAPWAP_CONFIGURATION_UPDATE_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_ECHO_REQUEST: {
if (!receive_echo_request(session, buildpacket, packet)) {
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_WTP_EVENT_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
}
}
} else {
if (IS_FLAG_K_HEADER(&buildpacket->header)) {
struct capwap_sessionid_element sessionid;
if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
int result;
capwap_fragment_packet_array* txfragpacket;
/* Receive data packet keepalive, response with same packet */
txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0);
if (!result) {
struct capwap_packet* txpacket;
ASSERT(txfragpacket->count == 1);
txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) {
capwap_logging_debug("Warning: error to send data channel keepalive packet");
result = -1;
}
}
/* */
capwap_fragment_free(txfragpacket);
capwap_array_free(txfragpacket);
if (result) {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
}
}
} else {
/* TODO */
}
}
}
/* Free */
capwap_build_packet_free(buildpacket);
}
} else {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
return status;
}
/* */
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet) {
int status = AC_DFA_NO_PACKET;
struct capwap_build_packet* buildpacket;
ASSERT(session != NULL);
ASSERT(packet == NULL);
/* Build packet */
buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, session->binding);
buildpacket->isctrlmsg = 1;
/* Prepare reset request */
capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_RESET_REQUEST, session->localseqnumber++);
capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(&session->startupimage));
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(buildpacket, NULL)) {
int i;
int result;
/* Free old reference for this request */
ac_free_reference_last_request(session);
/* Send reset request to WTP */
result = capwap_fragment_build_packet(buildpacket, session->requestfragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Send */
for (i = 0; i < session->requestfragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
capwap_logging_debug("Warning: error to send reset request packet");
result = -1;
break;
}
}
}
if (result == -1) {
/* Error to send packets */
ac_free_reference_last_request(session);
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
} else {
session->dfa.rfcRetransmitCount = 0;
capwap_killall_timeout(&session->timeout);
capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
ac_dfa_change_state(session, CAPWAP_RESET_STATE);
status = AC_DFA_ACCEPT_PACKET;
}
}
/* Free memory */
capwap_build_packet_free(buildpacket);
return status;
}
/* */
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
return ac_session_teardown_connection(session);
}

22
src/ac/ac_dfa_teardown.c Normal file
View File

@ -0,0 +1,22 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet == NULL);
/* Defered free resource */
ac_dfa_change_state(session, CAPWAP_DEAD_STATE);
return AC_DFA_DROP_PACKET;
}
/* */
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet == NULL);
return AC_DFA_DEAD;
}

276
src/ac/ac_discovery.c Normal file
View File

@ -0,0 +1,276 @@
#include "ac.h"
#include "capwap_protocol.h"
#include "ac_discovery.h"
#include "ac_session.h"
#define AC_DISCOVERY_CLEANUP_TIMEOUT 1000
struct ac_discovery_t {
pthread_t threadid;
int endthread;
unsigned short fragmentid;
unsigned char txseqnumber;
capwap_event_t waitpacket;
capwap_lock_t packetslock;
struct capwap_list* packets;
};
struct ac_discovery_packet {
int sendsock;
struct sockaddr_storage sender;
char data[0];
};
static struct ac_discovery_t g_ac_discovery;
/* */
int ac_discovery_start(void) {
int result;
memset(&g_ac_discovery, 0, sizeof(struct ac_discovery_t));
/* Init */
capwap_event_init(&g_ac_discovery.waitpacket);
capwap_lock_init(&g_ac_discovery.packetslock);
g_ac_discovery.packets = capwap_list_create();
/* Create thread */
result = pthread_create(&g_ac_discovery.threadid, NULL, ac_discovery_thread, NULL);
if (result) {
capwap_logging_debug("Unable create discovery thread");
return 0;
}
return 1;
}
/* */
void ac_discovery_stop(void) {
void* dummy;
g_ac_discovery.endthread = 1;
capwap_event_signal(&g_ac_discovery.waitpacket);
pthread_join(g_ac_discovery.threadid, &dummy);
/* Free memory */
capwap_event_destroy(&g_ac_discovery.waitpacket);
capwap_lock_exit(&g_ac_discovery.packetslock);
capwap_list_free(g_ac_discovery.packets);
}
/* */
void ac_discovery_add_packet(void* buffer, int buffersize, int sock, struct sockaddr_storage* sender) {
struct capwap_list_item* item;
struct ac_discovery_packet* packet;
ASSERT(buffer != NULL);
ASSERT(buffersize > 0);
ASSERT(sock >= 0);
ASSERT(sender != NULL);
/* TODO: mettere un history delle discovery request gi<67> processate per non eseguirle di nuovo */
/* L'elemento deve rimanere per la durata minima di una discovery request */
/* Copy packet */
item = capwap_itemlist_create(sizeof(struct ac_discovery_packet) + buffersize);
packet = (struct ac_discovery_packet*)item->item;
packet->sendsock = sock;
memcpy(&packet->sender, sender, sizeof(struct sockaddr_storage));
memcpy(packet->data, buffer, buffersize);
/* Append to packets list */
capwap_lock_enter(&g_ac_discovery.packetslock);
capwap_itemlist_insert_after(g_ac_discovery.packets, NULL, item);
capwap_event_signal(&g_ac_discovery.waitpacket);
capwap_lock_exit(&g_ac_discovery.packetslock);
}
/* */
static struct capwap_build_packet* ac_create_discovery_response(struct capwap_build_packet* packet, struct capwap_element_discovery_request* discoveryrequest, struct sockaddr_storage* sender) {
int i;
unsigned short binding;
struct capwap_list* controllist;
struct capwap_list_item* item;
struct capwap_build_packet* responsepacket;
ASSERT(packet != NULL);
ASSERT(discoveryrequest != NULL);
ASSERT(sender != NULL);
/* Check is valid binding */
binding = GET_WBID_HEADER(&packet->header);
if (!ac_valid_binding(binding)) {
return NULL;
}
/* Build packet */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Update statistics */
ac_update_statistics();
/* Prepare discovery response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_DISCOVERY_RESPONSE, packet->ctrlmsg.seq);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname));
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
for (i = 0; i < discoveryrequest->binding.ieee80211.wtpradioinformation->count; i++) {
struct capwap_80211_wtpradioinformation_element* radio;
radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(discoveryrequest->binding.ieee80211.wtpradioinformation, i);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio));
}
} else {
capwap_logging_debug("Unknown capwap binding");
}
/* Get information from any local address */
controllist = capwap_list_create();
ac_get_control_information(controllist);
for (item = controllist->first; item != NULL; item = item->next) {
struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
if (sessioncontrol->localaddress.ss_family == AF_INET) {
struct capwap_controlipv4_element element;
memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr));
element.wtpcount = sessioncontrol->count;
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element));
} else if (sessioncontrol->localaddress.ss_family == AF_INET6) {
struct capwap_controlipv6_element element;
memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr));
element.wtpcount = sessioncontrol->count;
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element));
}
}
capwap_list_free(controllist);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
return responsepacket;
}
/* Cleanup info discovery */
static void ac_discovery_cleanup(void) {
/* Clean history discovery request */
/* TODO */
}
/* */
static void ac_discovery_run(void) {
int sizedata;
struct capwap_list_item* itempacket;
struct capwap_build_packet* buildpacket;
struct ac_discovery_packet* packet;
unsigned short binding;
while (!g_ac_discovery.endthread) {
/* Get packet */
capwap_lock_enter(&g_ac_discovery.packetslock);
itempacket = NULL;
if (g_ac_discovery.packets->count > 0) {
itempacket = capwap_itemlist_remove_head(g_ac_discovery.packets);
}
capwap_lock_exit(&g_ac_discovery.packetslock);
if (!itempacket) {
/* Wait packet with timeout*/
if (!capwap_event_wait_timeout(&g_ac_discovery.waitpacket, AC_DISCOVERY_CLEANUP_TIMEOUT)) {
ac_discovery_cleanup();
}
continue;
}
/* */
packet = (struct ac_discovery_packet*)itempacket->item;
sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet);
/* Parsing packet */
buildpacket = capwap_rx_packet_create(packet->data, sizedata, 1);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
struct capwap_element_discovery_request discoveryrequest;
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
capwap_init_element_discovery_request(&discoveryrequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_discovery_request(&discoveryrequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* txpacket;
capwap_fragment_packet_array* responsefragmentpacket = NULL;
/* Creare discovery response */
txpacket = ac_create_discovery_response(buildpacket, &discoveryrequest, &packet->sender);
if (txpacket) {
int result = -1;
if (!capwap_build_packet_validate(txpacket, NULL)) {
responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
result = capwap_fragment_build_packet(txpacket, responsefragmentpacket, g_ac.mtu, g_ac_discovery.fragmentid);
if (result == 1) {
g_ac_discovery.fragmentid++;
}
} else {
capwap_logging_debug("Warning: build invalid discovery response packet");
}
capwap_build_packet_free(txpacket);
/* Send discovery response to WTP */
if (result >= 0) {
int i;
for (i = 0; i < responsefragmentpacket->count; i++) {
struct capwap_packet* sendpacket = (struct capwap_packet*)capwap_array_get_item_pointer(responsefragmentpacket, i);
ASSERT(sendpacket != NULL);
if (!capwap_sendto(packet->sendsock, sendpacket->header, sendpacket->packetsize, NULL, &packet->sender)) {
capwap_logging_debug("Warning: error to send discovery response packet");
break;
}
}
}
}
/* Don't buffering a packets sent */
if (responsefragmentpacket) {
capwap_fragment_free(responsefragmentpacket);
capwap_array_free(responsefragmentpacket);
}
}
/* Free discovery request */
capwap_free_element_discovery_request(&discoveryrequest, binding);
}
/* */
capwap_build_packet_free(buildpacket);
}
/* Free packet */
capwap_itemlist_free(itempacket);
}
}
/* */
void* ac_discovery_thread(void* param) {
capwap_logging_debug("Discovery start");
ac_discovery_run();
capwap_logging_debug("Discovery stop");
/* Thread exit */
pthread_exit(NULL);
return NULL;
}

10
src/ac/ac_discovery.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __AC_DISCOVERY_HEADER__
#define __AC_DISCOVERY_HEADER__
void* ac_discovery_thread(void* param);
int ac_discovery_start(void);
void ac_discovery_stop(void);
void ac_discovery_add_packet(void* buffer, int buffersize, int sock, struct sockaddr_storage* sender);
#endif /* __AC_DISCOVERY_HEADER__ */

532
src/ac/ac_execute.c Normal file
View File

@ -0,0 +1,532 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_event.h"
#include "ac_session.h"
#include "ac_discovery.h"
#include <signal.h>
/* Add packet to session */
static void ac_session_add_packet(struct ac_session_t* session, char* buffer, int size, int isctrlsocket, int plainbuffer) {
struct capwap_list_item* item;
struct ac_packet* packet;
ASSERT(session != NULL);
ASSERT(buffer != NULL);
ASSERT(size > 0);
/* Copy packet */
item = capwap_itemlist_create(sizeof(struct ac_packet) + size);
packet = (struct ac_packet*)item->item;
packet->plainbuffer = plainbuffer;
memcpy(packet->buffer, buffer, size);
/* Append to packets list */
capwap_lock_enter(&session->packetslock);
capwap_itemlist_insert_after((isctrlsocket ? session->controlpackets : session->datapackets), NULL, item);
capwap_event_signal(&session->waitpacket);
capwap_lock_exit(&session->packetslock);
}
/* Find AC sessions */
static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_storage* address, int isctrlsocket) {
struct ac_session_t* result = NULL;
struct capwap_list_item* search;
ASSERT(address != NULL);
capwap_lock_enter(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
if (!capwap_compare_ip(address, (isctrlsocket ? &session->wtpctrladdress : &session->wtpdataaddress))) {
session->count++;
result = session;
break;
}
search = search->next;
}
capwap_lock_exit(&g_ac.sessionslock);
return result;
}
/* */
static struct ac_session_t* ac_get_session_from_keepalive(void* buffer, int buffersize) {
struct ac_session_t* result = NULL;
struct capwap_build_packet* buildpacket;
ASSERT(buffer != NULL);
ASSERT(buffersize > 0);
buildpacket = capwap_rx_packet_create(buffer, buffersize, 0);
if (buildpacket) {
struct capwap_sessionid_element sessionid;
if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
struct capwap_list_item* search;
capwap_lock_enter(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
session->count++;
result = session;
break;
}
search = search->next;
}
capwap_lock_exit(&g_ac.sessionslock);
}
/* Free */
capwap_build_packet_free(buildpacket);
}
return result;
}
/* Close session */
static void ac_close_session(struct ac_session_t* session) {
session->closesession = 1;
capwap_event_signal(&session->waitpacket);
}
/* Close sessions */
static void ac_close_sessions() {
struct capwap_list_item* search;
capwap_lock_enter(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
ac_close_session(session);
search = search->next;
}
capwap_lock_exit(&g_ac.sessionslock);
}
/* DTLS Handshake BIO send */
static int ac_bio_handshake_send(struct capwap_dtls* dtls, char* buffer, int length, void* param) {
struct ac_data_session_handshake* handshake = (struct ac_data_session_handshake*)param;
return capwap_sendto(handshake->socket.socket[handshake->socket.type], buffer, length, &handshake->acaddress, &handshake->wtpaddress);
}
/* Find AC sessions */
static void ac_update_session_from_datapacket(struct capwap_socket* socket, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, void* buffer, int buffersize) {
struct ac_session_t* session = NULL;
struct capwap_preamble* preamble = (struct capwap_preamble*)buffer;
ASSERT(buffer != NULL);
ASSERT(buffersize > sizeof(struct capwap_preamble));
ASSERT(socket != NULL);
ASSERT(recvfromaddr != NULL);
ASSERT(recvtoaddr != NULL);
/* */
if (preamble->type == CAPWAP_PREAMBLE_HEADER) {
if ((g_ac.descriptor.dtlspolicy & CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED) != 0) {
session = ac_get_session_from_keepalive(buffer, buffersize);
if (session) {
/* Update data session */
memcpy(&session->datasocket, socket, sizeof(struct capwap_socket));
memcpy(&session->acdataaddress, recvtoaddr, sizeof(struct sockaddr_storage));
memcpy(&session->wtpdataaddress, recvfromaddr, sizeof(struct sockaddr_storage));
/* Add packet*/
ac_session_add_packet(session, buffer, buffersize, 0, 1);
ac_session_release_reference(session);
}
}
} else if (preamble->type == CAPWAP_PREAMBLE_DTLS_HEADER) {
if ((g_ac.descriptor.dtlspolicy & CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED) != 0) {
struct capwap_list_item* itemlist;
struct ac_data_session_handshake* handshake;
/* Search active data dtls handshake */
itemlist = g_ac.datasessionshandshake->first;
while (itemlist != NULL) {
handshake = (struct ac_data_session_handshake*)itemlist->item;
if (!capwap_compare_ip(recvfromaddr, &handshake->wtpaddress) && !capwap_compare_ip(recvtoaddr, &handshake->acaddress)) {
break;
}
/* Next */
itemlist = itemlist->next;
}
/* Create new DTLS handshake */
if (!itemlist) {
itemlist = capwap_itemlist_create(sizeof(struct ac_data_session_handshake));
handshake = (struct ac_data_session_handshake*)itemlist->item;
memset(handshake, 0, sizeof(struct ac_data_session_handshake));
/* */
memcpy(&handshake->socket, socket, sizeof(struct capwap_socket));
memcpy(&handshake->acaddress, recvtoaddr, sizeof(struct sockaddr_storage));
memcpy(&handshake->wtpaddress, recvfromaddr, sizeof(struct sockaddr_storage));
/* Create DTLS session */
if (!capwap_crypt_createsession(&handshake->dtls, CAPWAP_DTLS_DATA_SESSION, &g_ac.dtlscontext, ac_bio_handshake_send, handshake)) {
capwap_itemlist_free(itemlist);
itemlist = NULL;
} else {
if (capwap_crypt_open(&handshake->dtls, recvfromaddr) == CAPWAP_HANDSHAKE_ERROR) {
capwap_crypt_freesession(&handshake->dtls);
capwap_itemlist_free(itemlist);
itemlist = NULL;
} else {
/* Add item to list */
capwap_itemlist_insert_after(g_ac.datasessionshandshake, NULL, itemlist);
}
}
}
/* Decrypt packet */
if (itemlist) {
char temp[CAPWAP_MAX_PACKET_SIZE];
/* */
handshake = (struct ac_data_session_handshake*)itemlist->item;
buffersize = capwap_decrypt_packet(&handshake->dtls, buffer, buffersize, temp, CAPWAP_MAX_PACKET_SIZE);
if (buffersize > 0) {
session = ac_get_session_from_keepalive(temp, buffersize);
if (!session) {
capwap_itemlist_remove(g_ac.datasessionshandshake, itemlist);
capwap_crypt_close(&handshake->dtls);
capwap_crypt_freesession(&handshake->dtls);
capwap_itemlist_free(itemlist);
} else {
/* Update DTLS session */
capwap_crypt_change_dtls(&handshake->dtls, &session->datadtls);
memcpy(&session->datasocket, &handshake->socket, sizeof(struct capwap_socket));
memcpy(&session->acdataaddress, &handshake->acaddress, sizeof(struct sockaddr_storage));
memcpy(&session->wtpdataaddress, &handshake->wtpaddress, sizeof(struct sockaddr_storage));
capwap_crypt_change_bio_send(&session->datadtls, ac_bio_send, session);
/* Remove temp element */
capwap_itemlist_remove(g_ac.datasessionshandshake, itemlist);
capwap_itemlist_free(itemlist);
/* Add packet*/
ac_session_add_packet(session, temp, buffersize, 0, 1); /* Packet already decrypt */
ac_session_release_reference(session);
}
} else if ((buffersize == CAPWAP_ERROR_SHUTDOWN) || (buffersize == CAPWAP_ERROR_CLOSE)) {
capwap_itemlist_remove(g_ac.datasessionshandshake, itemlist);
capwap_crypt_close(&handshake->dtls);
capwap_crypt_freesession(&handshake->dtls);
capwap_itemlist_free(itemlist);
}
}
}
}
}
/* Create new session */
static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddress, struct sockaddr_storage* acaddress, struct capwap_socket* ctrlsock) {
int result;
struct capwap_list_item* itemlist;
struct ac_session_t* session;
ASSERT(acaddress != NULL);
ASSERT(wtpaddress != NULL);
ASSERT(ctrlsock != NULL);
/* Create new session */
itemlist = capwap_itemlist_create(sizeof(struct ac_session_t));
session = (struct ac_session_t*)itemlist->item;
memset(session, 0, sizeof(struct ac_session_t));
session->count = 2;
memcpy(&session->acctrladdress, acaddress, sizeof(struct sockaddr_storage));
memcpy(&session->wtpctrladdress, wtpaddress, sizeof(struct sockaddr_storage));
memcpy(&session->ctrlsocket, ctrlsock, sizeof(struct capwap_socket));
/* Duplicate state for DFA */
memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
session->dfa.acipv4list = capwap_array_clone(g_ac.dfa.acipv4list);
session->dfa.acipv6list = capwap_array_clone(g_ac.dfa.acipv6list);
session->dfa.rfcRetransmitInterval = AC_DEFAULT_RETRANSMIT_INTERVAL;
session->dfa.rfcMaxRetransmit = AC_MAX_RETRANSMIT;
session->dfa.rfcDTLSSessionDelete = AC_DEFAULT_DTLS_SESSION_DELETE;
/* Add default AC list if empty*/
if ((session->dfa.acipv4list->count == 0) && (session->dfa.acipv6list->count == 0)) {
if (session->acctrladdress.ss_family == AF_INET) {
struct capwap_acipv4list_element* acip = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(session->dfa.acipv4list, 0);
memcpy(&acip->address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
} else if (session->acctrladdress.ss_family == AF_INET6) {
struct capwap_acipv6list_element* acip = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(session->dfa.acipv6list, 0);
memcpy(&acip->address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
}
}
/* Init */
capwap_event_init(&session->waitpacket);
capwap_lock_init(&session->packetslock);
session->controlpackets = capwap_list_create();
session->datapackets = capwap_list_create();
session->requestfragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
session->responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
session->rxfragmentpacket = capwap_defragment_init_list();
session->mtu = g_ac.mtu;
session->state = CAPWAP_IDLE_STATE;
/* Update session list */
capwap_lock_enter(&g_ac.sessionslock);
capwap_itemlist_insert_after(g_ac.sessions, NULL, itemlist);
capwap_lock_exit(&g_ac.sessionslock);
/* Create thread */
result = pthread_create(&session->threadid, NULL, ac_session_thread, (void*)session);
if (!result) {
pthread_detach(session->threadid);
/* Notify change session list */
capwap_event_signal(&g_ac.changesessionlist);
} else {
capwap_logging_debug("Unable create session thread, error code %d", result);
/* Destroy element */
capwap_lock_enter(&g_ac.sessionslock);
capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessions, itemlist));
capwap_lock_exit(&g_ac.sessionslock);
session = NULL;
}
return session;
}
/* Update statistics */
void ac_update_statistics(void) {
g_ac.descriptor.station = 0; /* TODO */
capwap_lock_enter(&g_ac.sessionslock);
g_ac.descriptor.wtp = g_ac.sessions->count;
capwap_lock_exit(&g_ac.sessionslock);
}
/* Handler signal */
static void ac_signal_handler(int signum) {
if ((signum == SIGINT) || (signum == SIGTERM)) {
g_ac.running = 0;
}
}
/* AC running */
int ac_execute(void) {
int fdscount = CAPWAP_MAX_SOCKETS * 2;
struct pollfd* fds;
int result = CAPWAP_SUCCESSFUL;
int index;
int check;
int isctrlsocket = 0;
struct sockaddr_storage recvfromaddr;
struct sockaddr_storage recvtoaddr;
int isrecvpacket = 0;
struct ac_session_t* session;
struct capwap_socket ctrlsock;
char buffer[CAPWAP_MAX_PACKET_SIZE];
int buffersize;
/* Configure poll struct */
fds = (struct pollfd*)capwap_alloc(sizeof(struct pollfd) * fdscount);
if (!fds) {
capwap_outofmemory();
}
/* Retrive all socket for polling */
fdscount = capwap_network_set_pollfd(&g_ac.net, fds, fdscount);
ASSERT(fdscount > 0);
/* Handler signal */
g_ac.running = 1;
signal(SIGINT, ac_signal_handler);
signal(SIGTERM, ac_signal_handler);
/* Start discovery thread */
if (!ac_discovery_start()) {
capwap_free(fds);
capwap_logging_debug("Unable to start discovery thread");
return AC_ERROR_SYSTEM_FAILER;
}
/* */
for (;;) {
/* Receive packet */
isrecvpacket = 0;
buffersize = sizeof(buffer);
index = capwap_recvfrom(fds, fdscount, buffer, &buffersize, &recvfromaddr, &recvtoaddr, NULL);
if (!g_ac.running) {
break;
}
/* */
if (index >= 0) {
/* Detect local address */
if (recvtoaddr.ss_family == AF_UNSPEC) {
if (capwap_get_localaddress_by_remoteaddress(&recvtoaddr, &recvfromaddr, g_ac.net.bind_interface, (!(g_ac.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) {
struct sockaddr_storage sockinfo;
socklen_t sockinfolen = sizeof(struct sockaddr_storage);
memset(&sockinfo, 0, sizeof(struct sockaddr_storage));
if (getsockname(fds[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) {
break;
}
CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo));
}
}
/* Search the AC session */
isctrlsocket = ((index < (fdscount / 2)) ? 1 : 0);
session = ac_search_session_from_wtpaddress(&recvfromaddr, isctrlsocket);
if (session) {
/* Add packet*/
ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 0);
/* Release reference */
ac_session_release_reference(session);
} else {
if (isctrlsocket) {
unsigned short sessioncount;
/* Get current session number */
capwap_lock_enter(&g_ac.sessionslock);
sessioncount = g_ac.sessions->count;
capwap_lock_exit(&g_ac.sessionslock);
/* PreParsing packet for reduce a DoS attack */
check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls, 0);
if (check == CAPWAP_PLAIN_PACKET) {
struct capwap_header* header = (struct capwap_header*)buffer;
/* Accepted only packet without fragmentation */
if (!IS_FLAG_F_HEADER(header)) {
int headersize = GET_HLEN_HEADER(header) * 4;
if (buffersize >= (headersize + sizeof(struct capwap_control_message))) {
struct capwap_control_message* control = (struct capwap_control_message*)((char*)buffer + headersize);
unsigned long type = ntohl(control->type);
if (type == CAPWAP_DISCOVERY_REQUEST) {
if (sessioncount < g_ac.descriptor.wtplimit) {
ac_discovery_add_packet(buffer, buffersize, fds[index].fd, &recvfromaddr);
}
} else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) {
if (sessioncount < g_ac.descriptor.wtplimit) {
/* Retrive socket info */
capwap_get_network_socket(&g_ac.net, &ctrlsock, fds[index].fd);
/* Create a new session */
session = ac_create_session(&recvfromaddr, &recvtoaddr, &ctrlsock);
if (session) {
ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 1);
/* Release reference */
ac_session_release_reference(session);
}
}
}
}
}
} else if (check == CAPWAP_DTLS_PACKET) {
/* Need create a new sessione for check if it is a valid DTLS handshake */
if (sessioncount < g_ac.descriptor.wtplimit) {
/* TODO prevent dos attack add filtering ip for multiple error */
/* Retrive socket info */
capwap_get_network_socket(&g_ac.net, &ctrlsock, fds[index].fd);
/* Create a new session */
session = ac_create_session(&recvfromaddr, &recvtoaddr, &ctrlsock);
if (session) {
ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 0);
/* Release reference */
ac_session_release_reference(session);
}
}
}
} else {
struct capwap_socket datasocket;
/* Retrieve session by sessionid of data packet */
capwap_get_network_socket(&g_ac.net, &datasocket, fds[index].fd);
ac_update_session_from_datapacket(&datasocket, &recvfromaddr, &recvtoaddr, buffer, buffersize);
}
}
} else if (index == CAPWAP_RECV_ERROR_INTR) {
/* Ignore recv */
continue;
} else if (index == CAPWAP_RECV_ERROR_SOCKET) {
/* Socket close */
break;
}
}
/* Terminate discovery thread */
ac_discovery_stop();
/* Close all sessions */
ac_close_sessions();
/* Wait to terminate all sessions */
for (;;) {
int count;
capwap_lock_enter(&g_ac.sessionslock);
count = g_ac.sessions->count;
capwap_lock_exit(&g_ac.sessionslock);
if (!count) {
break;
}
/* Wait that list is changed */
capwap_logging_debug("Waiting for %d session terminate", count);
capwap_event_wait(&g_ac.changesessionlist);
}
/* Free handshark session */
while (g_ac.datasessionshandshake->first != NULL) {
struct ac_data_session_handshake* handshake = (struct ac_data_session_handshake*)g_ac.datasessionshandshake->first->item;
if (handshake->dtls.enable) {
capwap_crypt_freesession(&handshake->dtls);
}
capwap_itemlist_free(capwap_itemlist_remove(g_ac.datasessionshandshake, g_ac.datasessionshandshake->first));
}
/* Free memory */
capwap_free(fds);
return result;
}

617
src/ac/ac_session.c Normal file
View File

@ -0,0 +1,617 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "ac_session.h"
#define PACKET_TIMEOUT -1
#define DTLS_SHUTDOWN -2
static int ac_network_read(struct ac_session_t* session, void* buffer, int length, int* isctrlpacket, struct timeout_control* timeout) {
long indextimer;
long waittimeout;
ASSERT(session != NULL);
ASSERT(buffer != NULL);
ASSERT(length > 0);
ASSERT(isctrlpacket != NULL);
for (;;) {
if (session->closesession) {
session->closesession = 0;
return DTLS_SHUTDOWN;
}
capwap_lock_enter(&session->packetslock);
if ((session->controlpackets->count > 0) || (session->datapackets->count > 0)) {
int result = 0;
struct capwap_list_item* itempacket;
*isctrlpacket = ((session->controlpackets->count > 0) ? 1 : 0);
/* Get packet */
itempacket = capwap_itemlist_remove_head((*isctrlpacket ? session->controlpackets : session->datapackets));
capwap_lock_exit(&session->packetslock);
if (itempacket) {
struct ac_packet* packet = (struct ac_packet*)itempacket->item;
long packetlength = itempacket->itemsize - sizeof(struct ac_packet);
struct capwap_dtls* dtls = (*isctrlpacket ? &session->ctrldtls : &session->datadtls);
if (!packet->plainbuffer && dtls->enable) {
int oldaction = dtls->action;
/* Decrypt packet */
result = capwap_decrypt_packet(dtls, packet->buffer, packetlength, buffer, length);
if (result == CAPWAP_ERROR_AGAIN) {
/* Check is handshake complete */
if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (dtls->action == CAPWAP_DTLS_ACTION_DATA)) {
if (*isctrlpacket) {
if (session->state == CAPWAP_DTLS_CONNECT_STATE) {
ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
capwap_set_timeout(session->dfa.rfcWaitJoin, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
}
}
} else if (result == CAPWAP_ERROR_SHUTDOWN) {
if ((oldaction == CAPWAP_DTLS_ACTION_DATA) && (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) {
result = DTLS_SHUTDOWN;
}
}
} else {
if (packetlength <= length) {
memcpy(buffer, packet->buffer, packetlength);
result = packetlength;
}
}
/* Free packet */
capwap_itemlist_free(itempacket);
}
return result;
}
capwap_lock_exit(&session->packetslock);
/* Update timeout */
capwap_update_timeout(timeout);
waittimeout = capwap_get_timeout(timeout, &indextimer);
if ((waittimeout <= 0) && (indextimer != CAPWAP_TIMER_UNDEF)) {
return PACKET_TIMEOUT;
}
/* Wait packet */
capwap_event_wait_timeout(&session->waitpacket, waittimeout);
}
return 0;
}
/* */
static int ac_dfa_execute(struct ac_session_t* session, struct capwap_packet* packet) {
int action = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
/* Execute state */
switch (session->state) {
case CAPWAP_START_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_START_TO_IDLE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_IDLE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_IDLE_TO_DISCOVERY_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_IDLE_TO_DTLS_SETUP_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DISCOVERY_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DISCOVERY_TO_IDLE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DISCOVERY_TO_SULKING_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_SULKING_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_SULKING_TO_IDLE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_SETUP_STATE: {
action = ac_dfa_state_dtlssetup(session, packet);
break;
}
case CAPWAP_DTLS_SETUP_TO_IDLE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_SETUP_TO_SULKING_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_AUTHORIZE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_CONNECT_STATE: {
action = ac_dfa_state_dtlsconnect(session, packet);
break;
}
case CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_dtlsconnect_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_DTLS_CONNECT_TO_JOIN_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_teardown(session, packet);
break;
}
case CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_DTLS_TEARDOWN_TO_DEAD_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_JOIN_STATE: {
action = ac_dfa_state_join(session, packet);
break;
}
case CAPWAP_POSTJOIN_STATE: {
action = ac_dfa_state_postjoin(session, packet);
break;
}
case CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_join_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_JOIN_TO_IMAGE_DATA_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_JOIN_TO_CONFIGURE_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_IMAGE_DATA_STATE: {
action = ac_dfa_state_imagedata(session, packet);
break;
}
case CAPWAP_IMAGE_DATA_TO_RESET_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_imagedata_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_CONFIGURE_STATE: {
action = ac_dfa_state_configure(session, packet);
break;
}
case CAPWAP_CONFIGURE_TO_RESET_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_configure_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE: {
/* Never called with this state */
ASSERT(0);
break;
}
case CAPWAP_RESET_STATE: {
action = ac_dfa_state_reset(session, packet);
break;
}
case CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_reset_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_DATA_CHECK_STATE: {
action = ac_dfa_state_datacheck(session, packet);
break;
}
case CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_datacheck_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_DATA_CHECK_TO_RUN_STATE: {
action = ac_dfa_state_datacheck_to_run(session, packet);
break;
}
case CAPWAP_RUN_STATE: {
action = ac_dfa_state_run(session, packet);
break;
}
case CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE: {
action = ac_dfa_state_run_to_dtlsteardown(session, packet);
break;
}
case CAPWAP_RUN_TO_RESET_STATE: {
action = ac_dfa_state_run_to_reset(session, packet);
break;
}
case CAPWAP_DEAD_STATE: {
action = ac_dfa_state_dead(session, packet);
break;
}
default: {
capwap_logging_debug("Unknown action event: %lu", session->state);
break;
}
}
return action;
}
static void ac_session_run(struct ac_session_t* session) {
int check;
int length;
int isctrlsocket;
int action = AC_DFA_ACCEPT_PACKET;
char buffer[CAPWAP_MAX_PACKET_SIZE];
ASSERT(session != NULL);
/* Configure DFA */
if (g_ac.enabledtls) {
action = AC_DFA_NO_PACKET;
ac_dfa_change_state(session, CAPWAP_DTLS_SETUP_STATE);
capwap_set_timeout(session->dfa.rfcWaitDTLS, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
/* Wait Join request */
ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
capwap_set_timeout(session->dfa.rfcWaitJoin, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
while (action != AC_DFA_DEAD) {
/* Get packet */
if ((action == AC_DFA_ACCEPT_PACKET) || (action == AC_DFA_DROP_PACKET)) {
length = ac_network_read(session, buffer, sizeof(buffer), &isctrlsocket, &session->timeout);
if (length < 0) {
if (length == PACKET_TIMEOUT) {
action = ac_dfa_execute(session, NULL); /* Timeout */
} else if (length == DTLS_SHUTDOWN) {
action = ac_session_teardown_connection(session);
}
} else if (length > 0) {
/* Accept data packet only in running state */
if (isctrlsocket || (session->state == CAPWAP_DATA_CHECK_TO_RUN_STATE) || (session->state == CAPWAP_RUN_STATE)) {
/* Check generic capwap packet */
check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, length, 0, 0);
if (check == CAPWAP_PLAIN_PACKET) {
struct capwap_packet packet;
check = capwap_defragment_packets(&session->wtpctrladdress, buffer, length, session->rxfragmentpacket, &packet);
if (check == CAPWAP_RECEIVE_COMPLETE_PACKET) {
int ignorepacket = 0;
if (isctrlsocket) {
/* Check for already response to packet */
if (capwap_recv_retrasmitted_request(&session->ctrldtls, &packet, session->remoteseqnumber, session->lastrecvpackethash, &session->ctrlsocket, session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
ignorepacket = 1;
}
/* Check message type */
if (!capwap_check_message_type(&session->ctrldtls, &packet, session->mtu)) {
ignorepacket = 1;
}
}
/* */
if (!ignorepacket && (action == AC_DFA_ACCEPT_PACKET)) {
memcpy(&packet.socket, (isctrlsocket ? &session->ctrlsocket : &session->datasocket), sizeof(struct capwap_socket));
action = ac_dfa_execute(session, &packet);
}
/* Free packet */
capwap_free_packet(&packet);
} else if (check != CAPWAP_REQUEST_MORE_FRAGMENT) {
/* Discard fragments */
capwap_defragment_remove_sender(session->rxfragmentpacket, &session->wtpctrladdress);
}
}
}
}
} else {
action = ac_dfa_execute(session, NULL);
}
}
/* Release reference session */
if (!ac_session_release_reference(session)) {
capwap_logging_debug("Reference session is > 0 to exit thread");
}
}
/* Change WTP state machine */
void ac_dfa_change_state(struct ac_session_t* session, int state) {
ASSERT(session != NULL);
if (state != session->state) {
#ifdef DEBUG
char sessionname[33];
capwap_sessionid_printf(&session->sessionid, sessionname);
capwap_logging_debug("Session AC %s change state from %s to %s", sessionname, capwap_dfa_getname(session->state), capwap_dfa_getname(state));
#endif
session->state = state;
}
}
/* Teardown connection */
int ac_session_teardown_connection(struct ac_session_t* session) {
ASSERT(session != NULL);
/* Close DTSL Control */
if (session->ctrldtls.enable) {
capwap_crypt_close(&session->ctrldtls);
}
/* Close DTLS Data */
if (session->datadtls.enable) {
capwap_crypt_close(&session->datadtls);
}
/* */
capwap_killall_timeout(&session->timeout);
capwap_set_timeout(session->dfa.rfcDTLSSessionDelete, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
return AC_DFA_DROP_PACKET;
}
/* Release reference of session */
int ac_session_release_reference(struct ac_session_t* session) {
int remove = 0;
struct capwap_list_item* search;
ASSERT(session != NULL);
capwap_lock_enter(&g_ac.sessionslock);
session->count--;
if (!session->count) {
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* item = (struct ac_session_t*)search->item;
if (session == item) {
/* Free DTSL Control */
capwap_crypt_freesession(&session->ctrldtls);
/* Free DTLS Data */
capwap_crypt_freesession(&session->datadtls);
/* Free resource */
capwap_event_destroy(&session->waitpacket);
capwap_lock_exit(&session->packetslock);
capwap_list_free(session->controlpackets);
capwap_list_free(session->datapackets);
capwap_defragment_free_list(session->rxfragmentpacket);
/* Free fragments packet */
capwap_fragment_free(session->requestfragmentpacket);
capwap_fragment_free(session->responsefragmentpacket);
capwap_array_free(session->requestfragmentpacket);
capwap_array_free(session->responsefragmentpacket);
/* Free DFA resource */
capwap_array_free(session->dfa.acipv4list);
capwap_array_free(session->dfa.acipv6list);
/* Remove item from list */
remove = 1;
capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessions, search));
capwap_event_signal(&g_ac.changesessionlist);
break;
}
search = search->next;
}
}
capwap_lock_exit(&g_ac.sessionslock);
return remove;
}
/* */
void* ac_session_thread(void* param) {
ASSERT(param != NULL);
capwap_logging_debug("Session start");
ac_session_run((struct ac_session_t*)param);
capwap_logging_debug("Session end");
/* Thread exit */
pthread_exit(NULL);
return NULL;
}
/* */
void ac_get_control_information(struct capwap_list* controllist) {
struct capwap_list* addrlist;
struct capwap_list_item* item;
ASSERT(controllist != NULL);
/* Detect local address */
addrlist = capwap_list_create();
capwap_interface_list(&g_ac.net, addrlist);
/* Prepare control list */
for (item = addrlist->first; item != NULL; item = item->next) {
struct capwap_list_item* itemcontrol;
struct ac_session_control* sessioncontrol;
struct sockaddr_storage* address = (struct sockaddr_storage*)item->item;
/* */
itemcontrol = capwap_itemlist_create(sizeof(struct ac_session_control));
sessioncontrol = (struct ac_session_control*)itemcontrol->item;
memcpy(&sessioncontrol->localaddress, address, sizeof(struct sockaddr_storage));
sessioncontrol->count = 0;
/* Add */
capwap_itemlist_insert_after(controllist, NULL, itemcontrol);
}
/* Free local address list */
capwap_list_free(addrlist);
/* */
capwap_lock_enter(&g_ac.sessionslock);
/* Get wtp count from any local address */
for (item = controllist->first; item != NULL; item = item->next) {
struct capwap_list_item* search;
struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
for (search = g_ac.sessions->first; search != NULL; search = search->next) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
if (!capwap_compare_ip(&session->acctrladdress, &sessioncontrol->localaddress)) {
sessioncontrol->count++;
}
}
}
/* */
capwap_lock_exit(&g_ac.sessionslock);
}
/* */
void ac_free_reference_last_request(struct ac_session_t* session) {
ASSERT(session);
capwap_fragment_free(session->requestfragmentpacket);
}
/* */
void ac_free_reference_last_response(struct ac_session_t* session) {
ASSERT(session);
capwap_fragment_free(session->responsefragmentpacket);
memset(&session->lastrecvpackethash[0], 0, sizeof(session->lastrecvpackethash));
}

112
src/ac/ac_session.h Normal file
View File

@ -0,0 +1,112 @@
#ifndef __AC_SESSION_HEADER__
#define __AC_SESSION_HEADER__
#include "capwap_dtls.h"
#define AC_DFA_NO_PACKET 0
#define AC_DFA_ACCEPT_PACKET 1
#define AC_DFA_DROP_PACKET 2
#define AC_DFA_DEAD 3
/* AC packet */
struct ac_packet {
int plainbuffer;
char buffer[0];
};
/* */
struct ac_session_control {
struct sockaddr_storage localaddress;
unsigned short count;
};
/* AC sessions */
struct ac_session_t {
struct ac_state dfa;
unsigned long count;
struct sockaddr_storage acctrladdress;
struct sockaddr_storage acdataaddress;
struct sockaddr_storage wtpctrladdress;
struct sockaddr_storage wtpdataaddress;
struct capwap_socket ctrlsocket;
struct capwap_socket datasocket;
struct timeout_control timeout;
struct capwap_sessionid_element sessionid;
unsigned short binding;
struct capwap_dtls ctrldtls;
struct capwap_dtls datadtls;
int closesession;
pthread_t threadid;
capwap_event_t waitpacket;
capwap_lock_t packetslock;
struct capwap_list* controlpackets;
struct capwap_list* datapackets;
unsigned char localseqnumber;
unsigned char remoteseqnumber;
unsigned short mtu;
unsigned short fragmentid;
capwap_fragment_list* rxfragmentpacket;
capwap_fragment_packet_array* requestfragmentpacket;
capwap_fragment_packet_array* responsefragmentpacket;
unsigned char lastrecvpackethash[16];
unsigned long state;
struct capwap_imageidentifier_element startupimage;
};
void* ac_session_thread(void* param);
int ac_session_teardown_connection(struct ac_session_t* session);
int ac_session_release_reference(struct ac_session_t* session);
void ac_dfa_change_state(struct ac_session_t* session, int state);
void ac_get_control_information(struct capwap_list* controllist);
void ac_free_reference_last_request(struct ac_session_t* session);
void ac_free_reference_last_response(struct ac_session_t* session);
/* */
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param);
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
/* */
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet);
#endif /* __AC_SESSION_HEADER__ */

151
src/common/capwap.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

288
src/common/capwap_element.h Normal file
View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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;
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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__ */

View 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);
}

View 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
View 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
View 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
View 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__ */

Some files were not shown because too many files have changed in this diff Show More