fork SmartCAWPAP as FreeWTP

This commit is contained in:
Andreas Schultz
2016-08-22 16:59:55 +02:00
parent 8cc6559f08
commit 0101ea6e56
341 changed files with 724 additions and 17737 deletions

67
src/Makefile.am Executable file
View File

@ -0,0 +1,67 @@
# FreeWTP -- An Open Source CAPWAP WTP
#
# Copyright SmartCAPWAP (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
# Copyright FreeCAPWAP (C) 2016 Travelping GmbH <info@travelping.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING included with this
# distribution); if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
bin_PROGRAMS = wtp
AM_CFLAGS = -std=gnu99 -D_GNU_SOURCE \
-fno-strict-aliasing \
${LIBNL_CFLAGS}
if DTLS_ENABLED
AM_CFLAGS += $(WOLFSSL_CFLAGS)
endif
AM_CFLAGS += \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/kmod \
-I$(top_srcdir)/lib/binding/ieee80211 \
-I$(top_srcdir)/src/binding/ieee80211
wtp_SOURCES = \
wtp.c \
kmod.c \
element_helper.c \
dfa.c \
dfa_idle.c \
dfa_discovery.c \
dfa_sulking.c \
dfa_dtls.c \
dfa_join.c \
dfa_configure.c \
dfa_datacheck.c \
dfa_run.c \
dfa_reset.c \
dfa_imagedata.c \
radio.c \
binding/ieee80211/netlink_link.c \
binding/ieee80211/wifi_drivers.c
if BUILD_WTP_WIFI_DRIVERS_NL80211
wtp_SOURCES += binding/ieee80211/wifi_nl80211.c
endif
wtp_LDADD = $(CONFIG_LIBS) \
$(LIBNL_LIBS) \
$(top_builddir)/lib/libcapwap.la
if DTLS_ENABLED
wtp_LDADD += $(WOLFSSL_LIBS)
endif

View File

@ -1,904 +0,0 @@
#include "ac.h"
#include "ac_soap.h"
#include "ac_session.h"
#include "capwap_dtls.h"
#include "capwap_socket.h"
#include "ac_wlans.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"
#define AC_STATIONS_HASH_SIZE 65536
#define AC_IFDATACHANNEL_HASH_SIZE 16
/* Local param */
static char g_configurationfile[260] = AC_DEFAULT_CONFIGURATION_FILE;
/* */
static unsigned long ac_stations_item_gethash(const void* key, unsigned long hashsize) {
uint8_t* macaddress = (uint8_t*)key;
return (((((unsigned long)macaddress[4] << 8) | (unsigned long)macaddress[5]) ^ ((unsigned long)macaddress[3] << 4)) % AC_STATIONS_HASH_SIZE);
}
/* */
static const void* ac_stations_item_getkey(const void* data) {
return (const void*)((struct ac_station*)data)->address;
}
/* */
static int ac_stations_item_cmp(const void* key1, const void* key2) {
return memcmp(key1, key2, MACADDRESS_EUI48_LENGTH);
}
/* */
static unsigned long ac_ifdatachannel_item_gethash(const void* key, unsigned long hashsize) {
return ((*(unsigned long*)key) % AC_IFDATACHANNEL_HASH_SIZE);
}
/* */
static const void* ac_ifdatachannel_item_getkey(const void* data) {
return (const void*)&((struct ac_if_datachannel*)data)->index;
}
/* */
static int ac_ifdatachannel_item_cmp(const void* key1, const void* key2) {
unsigned long value1 = *(unsigned long*)key1;
unsigned long value2 = *(unsigned long*)key2;
return ((value1 == value2) ? 0 : ((value1 < value2) ? -1 : 1));
}
/* */
static void ac_ifdatachannel_item_free(void* data) {
struct ac_if_datachannel* datachannel = (struct ac_if_datachannel*)data;
/* */
if (datachannel->ifindex >= 0) {
ac_kmod_delete_iface(datachannel->ifindex);
}
capwap_free(data);
}
/* Alloc AC */
static int ac_init(void) {
g_ac.standalone = 1;
/* Sessions message queue */
if (!ac_msgqueue_init()) {
return 0;
}
/* Network */
capwap_network_init(&g_ac.net);
g_ac.addrlist = capwap_list_create();
g_ac.mtu = CAPWAP_MTU_DEFAULT;
g_ac.binding = capwap_array_create(sizeof(uint16_t), 0, 0);
/* Try to use IPv6 */
g_ac.net.localaddr.ss.ss_family = AF_INET6;
CAPWAP_SET_NETWORK_PORT(&g_ac.net.localaddr, CAPWAP_CONTROL_PORT);
/* Standard name */
g_ac.acname.name = (uint8_t*)capwap_duplicate_string(AC_STANDARD_NAME);
/* Descriptor */
g_ac.descriptor.stationlimit = AC_DEFAULT_MAXSTATION;
g_ac.descriptor.maxwtp = 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, 1);
/* */
g_ac.dfa.ecn.flag = CAPWAP_LIMITED_ECN_SUPPORT;
g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
/* */
g_ac.dfa.timers.discovery = AC_DISCOVERY_INTERVAL / 1000;
g_ac.dfa.timers.echorequest = AC_ECHO_INTERVAL / 1000;
g_ac.dfa.decrypterrorreport_interval = AC_DECRYPT_ERROR_PERIOD_INTERVAL / 1000;
g_ac.dfa.idletimeout.timeout = AC_IDLE_TIMEOUT_INTERVAL / 1000;
g_ac.dfa.wtpfallback.mode = AC_WTP_FALLBACK_MODE;
/* */
g_ac.dfa.acipv4list.addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
g_ac.dfa.acipv6list.addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
/* Sessions */
g_ac.sessions = capwap_list_create();
g_ac.sessionsthread = capwap_list_create();
capwap_rwlock_init(&g_ac.sessionslock);
/* Stations */
g_ac.authstations = capwap_hash_create(AC_STATIONS_HASH_SIZE);
g_ac.authstations->item_gethash = ac_stations_item_gethash;
g_ac.authstations->item_getkey = ac_stations_item_getkey;
g_ac.authstations->item_cmp = ac_stations_item_cmp;
capwap_rwlock_init(&g_ac.authstationslock);
/* Data Channel Interfaces */
g_ac.ifdatachannel = capwap_hash_create(AC_IFDATACHANNEL_HASH_SIZE);
g_ac.ifdatachannel->item_gethash = ac_ifdatachannel_item_gethash;
g_ac.ifdatachannel->item_getkey = ac_ifdatachannel_item_getkey;
g_ac.ifdatachannel->item_cmp = ac_ifdatachannel_item_cmp;
g_ac.ifdatachannel->item_free = ac_ifdatachannel_item_free;
capwap_rwlock_init(&g_ac.ifdatachannellock);
/* Backend */
g_ac.availablebackends = capwap_array_create(sizeof(struct ac_http_soap_server*), 0, 0);
return 1;
}
/* Destroy AC */
static void ac_destroy(void) {
int i;
/* Dtls */
capwap_crypt_freecontext(&g_ac.dtlscontext);
/* */
for (i = 0; i < g_ac.descriptor.descsubelement->count; i++) {
struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(g_ac.descriptor.descsubelement, i);
if (desc->data) {
capwap_free(desc->data);
}
}
/* */
capwap_array_free(g_ac.descriptor.descsubelement);
capwap_array_free(g_ac.binding);
capwap_free(g_ac.acname.name);
/* */
capwap_array_free(g_ac.dfa.acipv4list.addresses);
capwap_array_free(g_ac.dfa.acipv6list.addresses);
/* Sessions */
capwap_list_free(g_ac.sessions);
capwap_list_free(g_ac.sessionsthread);
capwap_rwlock_destroy(&g_ac.sessionslock);
ac_msgqueue_free();
/* Data Channel Interfaces */
ASSERT(g_ac.ifdatachannel->count == 0);
capwap_hash_free(g_ac.ifdatachannel);
capwap_rwlock_destroy(&g_ac.ifdatachannellock);
/* Stations */
ASSERT(g_ac.authstations->count == 0);
capwap_hash_free(g_ac.authstations);
capwap_rwlock_destroy(&g_ac.authstationslock);
/* Backend */
if (g_ac.backendacid) {
capwap_free(g_ac.backendacid);
}
if (g_ac.backendversion) {
capwap_free(g_ac.backendversion);
}
for (i = 0; i < g_ac.availablebackends->count; i++) {
ac_soapclient_free_server(*(struct ac_http_soap_server**)capwap_array_get_item_pointer(g_ac.availablebackends, i));
}
capwap_array_free(g_ac.availablebackends);
capwap_list_free(g_ac.addrlist);
}
/* Help */
static void ac_print_usage(void) {
}
/* Parsing configuration */
static int ac_parsing_configuration_1_0(config_t* config) {
int i;
int configBool;
LIBCONFIG_LOOKUP_INT_ARG configInt;
const char* configString;
config_setting_t* configSetting;
/* Logging configuration */
if (config_lookup_bool(config, "logging.enable", &configBool) == CONFIG_TRUE) {
if (!configBool) {
capwap_logging_verboselevel(LOG_NONE);
capwap_logging_disable_allinterface();
} else {
if (config_lookup_string(config, "logging.level", &configString) == CONFIG_TRUE) {
if (!strcmp(configString, "fatal")) {
capwap_logging_verboselevel(LOG_EMERG);
} else if (!strcmp(configString, "error")) {
capwap_logging_verboselevel(LOG_ERR);
} else if (!strcmp(configString, "warning")) {
capwap_logging_verboselevel(LOG_WARNING);
} else if (!strcmp(configString, "info")) {
capwap_logging_verboselevel(LOG_INFO);
} else if (!strcmp(configString, "debug")) {
capwap_logging_verboselevel(LOG_DEBUG);
} else {
log_printf(LOG_ERR, "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 {
log_printf(LOG_ERR, "Invalid configuration file, unknown logging.output value");
return 0;
}
}
}
}
}
}
/* Set running mode */
if (config_lookup_bool(config, "application.standalone", &configBool) == CONFIG_TRUE) {
g_ac.standalone = ((configBool != 0) ? 1 : 0);
}
/* Set name of AC */
if (config_lookup_string(config, "application.name", &configString) == CONFIG_TRUE) {
if (strlen(configString) > CAPWAP_ACNAME_MAXLENGTH) {
log_printf(LOG_ERR, "Invalid configuration file, application.name string length exceeded");
return 0;
}
capwap_free(g_ac.acname.name);
g_ac.acname.name = (uint8_t*)capwap_duplicate_string(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 {
log_printf(LOG_ERR, "Invalid configuration file, unknown application.binding value");
return 0;
}
}
}
}
/* Set max stations of AC */
if (config_lookup_int(config, "application.descriptor.maxstations", &configInt) == CONFIG_TRUE) {
if ((configInt > 0) && (configInt < 65536)) {
g_ac.descriptor.stationlimit = (unsigned short)configInt;
} else {
log_printf(LOG_ERR, "Invalid configuration file, unknown application.descriptor.maxstations value");
return 0;
}
}
/* Set max wtp of AC */
if (config_lookup_int(config, "application.descriptor.maxwtp", &configInt) == CONFIG_TRUE) {
if ((configInt > 0) && (configInt < 65536)) {
g_ac.descriptor.maxwtp = (unsigned short)configInt;
} else {
log_printf(LOG_ERR, "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", &configBool) == CONFIG_TRUE) {
if (configBool != 0) {
g_ac.descriptor.security |= CAPWAP_ACDESC_SECURITY_PRESHARED_KEY;
}
}
if (config_lookup_bool(config, "application.descriptor.security.x509", &configBool) == CONFIG_TRUE) {
if (configBool != 0) {
g_ac.descriptor.security |= CAPWAP_ACDESC_SECURITY_X509_CERT;
}
}
}
/* Set rmacfiled of AC */
if (config_lookup_bool(config, "application.descriptor.rmacfiled.supported", &configBool) == CONFIG_TRUE) {
g_ac.descriptor.rmacfield = ((configBool != 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", &configBool) == CONFIG_TRUE) {
if (configBool != 0) {
g_ac.descriptor.dtlspolicy |= CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
}
}
if (config_lookup_bool(config, "application.descriptor.dtlspolicy.dtlsdatachannel", &configBool) == CONFIG_TRUE) {
if (configBool != 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) {
LIBCONFIG_LOOKUP_INT_ARG 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 {
log_printf(LOG_ERR, "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;
desc->data = (uint8_t*)capwap_alloc(desc->length + 1);
strcpy((char*)desc->data, configValue);
desc->data[desc->length] = 0;
} else {
log_printf(LOG_ERR, "Invalid configuration file, application.descriptor.info.value string length exceeded");
return 0;
}
} else {
log_printf(LOG_ERR, "Invalid configuration file, element application.descriptor.info.value not found");
return 0;
}
} else {
log_printf(LOG_ERR, "Invalid configuration file, element application.descriptor.info.type not found");
return 0;
}
} else {
log_printf(LOG_ERR, "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 {
log_printf(LOG_ERR, "Invalid configuration file, unknown application.ecn value");
return 0;
}
}
/* Set Timer of AC */
if (config_lookup_int(config, "application.timer.discovery", &configInt) == CONFIG_TRUE) {
configInt *= 1000; /* Set timeout in ms */
if ((configInt >= AC_MIN_DISCOVERY_INTERVAL) && (configInt <= AC_MAX_DISCOVERY_INTERVAL)) {
g_ac.dfa.timers.discovery = (unsigned char)(configInt / 1000);
} else {
log_printf(LOG_ERR, "Invalid configuration file, invalid application.timer.discovery value");
return 0;
}
}
if (config_lookup_int(config, "application.timer.echorequest", &configInt) == CONFIG_TRUE) {
configInt *= 1000;
if ((configInt >= AC_MIN_ECHO_INTERVAL) && (configInt <= AC_MAX_ECHO_INTERVAL)) {
g_ac.dfa.timers.echorequest = (unsigned char)(configInt / 1000);
} else {
log_printf(LOG_ERR, "Invalid configuration file, invalid application.timer.echorequest value");
return 0;
}
}
if (config_lookup_int(config, "application.timer.decrypterrorreport", &configInt) == CONFIG_TRUE) {
if ((configInt > 0) && (configInt < 65536)) {
g_ac.dfa.decrypterrorreport_interval = (unsigned short)configInt;
} else {
log_printf(LOG_ERR, "Invalid configuration file, invalid application.timer.decrypterrorreport value");
return 0;
}
}
if (config_lookup_int(config, "application.timer.idletimeout", &configInt) == CONFIG_TRUE) {
if (configInt > 0) {
g_ac.dfa.idletimeout.timeout = (unsigned long)configInt;
} else {
log_printf(LOG_ERR, "Invalid configuration file, invalid application.timer.idletimeout value");
return 0;
}
}
/* Set wtpfallback of AC */
if (config_lookup_bool(config, "application.wtpfallback", &configBool) == CONFIG_TRUE) {
g_ac.dfa.wtpfallback.mode = ((configBool != 0) ? CAPWAP_WTP_FALLBACK_ENABLED : CAPWAP_WTP_FALLBACK_DISABLED);
}
/* Set DTLS of WTP */
if (config_lookup_bool(config, "application.dtls.enable", &configBool) == CONFIG_TRUE) {
if (configBool != 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 {
log_printf(LOG_ERR, "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 (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);
}
} else if (dtlsparam.mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
if (config_lookup_string(config, "application.dtls.presharedkey.hint", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
dtlsparam.presharedkey.hint = capwap_duplicate_string(configString);
}
}
if (config_lookup_string(config, "application.dtls.presharedkey.identity", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
dtlsparam.presharedkey.identity = capwap_duplicate_string(configString);
}
}
if (config_lookup_string(config, "application.dtls.presharedkey.pskkey", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
/* TODO controllare se <20> un valore hex */
dtlsparam.presharedkey.pskkey = capwap_duplicate_string(configString);
}
}
/* */
if (dtlsparam.presharedkey.identity && dtlsparam.presharedkey.pskkey) {
if (capwap_crypt_createcontext(&g_ac.dtlscontext, &dtlsparam)) {
g_ac.enabledtls = 1;
}
}
/* Free dtls param */
if (dtlsparam.presharedkey.hint) {
capwap_free(dtlsparam.presharedkey.hint);
}
if (dtlsparam.presharedkey.identity) {
capwap_free(dtlsparam.presharedkey.identity);
}
if (dtlsparam.presharedkey.pskkey) {
capwap_free(dtlsparam.presharedkey.pskkey);
}
}
if (!g_ac.enabledtls) {
return 0;
}
}
}
/* Set interface binding of AC */
if (config_lookup_string(config, "application.network.binding", &configString) == CONFIG_TRUE) {
if (strlen(configString) > (IFNAMSIZ - 1)) {
log_printf(LOG_ERR, "Invalid configuration file, application.network.binding string length exceeded");
return 0;
}
strcpy(g_ac.net.bindiface, configString);
}
/* Set mtu of AC */
if (config_lookup_int(config, "application.network.mtu", &configInt) == CONFIG_TRUE) {
if ((configInt > 0) && (configInt < 65536)) {
g_ac.mtu = (unsigned short)configInt;
} else {
log_printf(LOG_ERR, "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 {
log_printf(LOG_ERR, "Invalid configuration file, unknown application.network.transport value");
return 0;
}
}
/* Backend */
if (config_lookup_string(config, "backend.id", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
g_ac.backendacid = capwap_duplicate_string(configString);
}
}
if (config_lookup_string(config, "backend.version", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
g_ac.backendversion = capwap_duplicate_string(configString);
}
}
configSetting = config_lookup(config, "backend.server");
if (configSetting) {
int count = config_setting_length(configSetting);
/* Retrieve server */
for (i = 0; i < count; i++) {
config_setting_t* configServer = config_setting_get_elem(configSetting, i);
if (configServer != NULL) {
if (config_setting_lookup_string(configServer, "url", &configString) == CONFIG_TRUE) {
struct ac_http_soap_server* server;
struct ac_http_soap_server** itemserver;
/* */
server = ac_soapclient_create_server(configString);
if (!server) {
log_printf(LOG_ERR, "Invalid configuration file, invalid backend.server value");
return 0;
}
/* HTTPS params */
if (server->protocol == SOAP_HTTPS_PROTOCOL) {
char* calist = NULL;
char* certificate = NULL;
char* privatekey = NULL;
config_setting_t* configSSL;
/* */
configSSL = config_setting_get_member(configServer, "x509");
if (!configSSL) {
log_printf(LOG_ERR, "Invalid configuration file, invalid backend.server.x509 value");
return 0;
}
if (config_setting_lookup_string(configSSL, "calist", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
calist = capwap_duplicate_string(configString);
}
}
if (config_setting_lookup_string(configSSL, "certificate", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
certificate = capwap_duplicate_string(configString);
}
}
if (config_setting_lookup_string(configSSL, "privatekey", &configString) == CONFIG_TRUE) {
if (strlen(configString) > 0) {
privatekey = capwap_duplicate_string(configString);
}
}
/* */
if (calist && certificate && privatekey) {
server->sslcontext = capwap_socket_crypto_createcontext(calist, certificate, privatekey);
if (!server->sslcontext) {
log_printf(LOG_ERR, "Invalid configuration file, unable to initialize crypto library");
return 0;
}
} else {
log_printf(LOG_ERR, "Invalid configuration file, invalid backend.server.x509 value");
return 0;
}
/* Free SSL param */
capwap_free(calist);
capwap_free(certificate);
capwap_free(privatekey);
}
/* Add item */
itemserver = (struct ac_http_soap_server**)capwap_array_get_item_pointer(g_ac.availablebackends, g_ac.availablebackends->count);
*itemserver= server;
}
}
}
}
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);
}
log_printf(LOG_ERR, "Invalid configuration file, '%s' is not supported", configString);
} else {
log_printf(LOG_ERR, "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 {
log_printf(LOG_ERR, "Invalid -%c argument", optopt);
return -1;
}
break;
}
case '?': {
if (optopt == 'c') {
log_printf(LOG_ERR, "Option -%c requires an argument", optopt);
} else {
log_printf(LOG_ERR, "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;
log_printf(LOG_ERR, "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 control channel to any address */
if (capwap_bind_sockets(&g_ac.net)) {
log_printf(LOG_EMERG, "Cannot bind address");
return AC_ERROR_NETWORK;
}
/* Detect local address */
capwap_interface_list(&g_ac.net, g_ac.addrlist);
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) {
log_printf(LOG_EMERG, "Request root privileges");
return CAPWAP_REQUEST_ROOT;
}
/* Init random generator */
capwap_init_rand();
/* Init crypt */
if (capwap_crypt_init()) {
log_printf(LOG_EMERG, "Error to init crypt engine");
return CAPWAP_CRYPT_ERROR;
}
/* Init soap module */
ac_soapclient_init();
/* 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) {
if (!g_ac.standalone) {
capwap_daemon();
/* Console logging is disabled in daemon mode */
capwap_logging_disable_console();
log_printf(LOG_INFO, "Running AC in daemon mode");
}
/* Complete configuration AC */
result = ac_configure();
if (result == CAPWAP_SUCCESSFUL) {
/* Connect AC to kernel module */
if (!ac_kmod_init()) {
/* Bind data channel */
if (!ac_kmod_createdatachannel(g_ac.net.localaddr.ss.ss_family, CAPWAP_GET_NETWORK_PORT(&g_ac.net.localaddr) + 1)) {
log_printf(LOG_INFO, "SmartCAPWAP kernel module connected");
/* Running AC */
result = ac_execute();
} else {
log_printf(LOG_EMERG, "Unable to create kernel data channel");
}
/* Disconnect kernel module */
ac_kmod_free();
} else {
log_printf(LOG_EMERG, "Unable to connect to kernel module");
}
/* Close connection */
ac_close();
}
}
/* Free memory */
ac_destroy();
/* Free soap */
ac_soapclient_free();
/* 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;
}

View File

@ -1,189 +0,0 @@
#ifndef __CAPWAP_AC_HEADER__
#define __CAPWAP_AC_HEADER__
/* standard include */
#include "capwap.h"
#include "capwap_network.h"
#include "capwap_protocol.h"
#include "capwap_event.h"
#include "capwap_lock.h"
#include "capwap_rwlock.h"
#include "capwap_list.h"
#include "capwap_hash.h"
#include "capwap_element.h"
#include <pthread.h>
#include <linux/if_ether.h>
#include <json-c/json.h>
#include <ac_kmod.h>
/* AC Configuration */
#define AC_DEFAULT_CONFIGURATION_FILE "/etc/capwap/ac.conf"
#define AC_DEFAULT_MAXSTATION 128
#define AC_DEFAULT_MAXSESSIONS 128
#define VLAN_MAX 4096
/* 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_DTLS_INTERVAL 60000
#define AC_JOIN_INTERVAL 60000
#define AC_CHANGE_STATE_PENDING_INTERVAL 25000
#define AC_DATA_CHECK_INTERVAL 30000
#define AC_RETRANSMIT_INTERVAL 3000
#define AC_MAX_RETRANSMIT 5
#define AC_DTLS_SESSION_DELETE_INTERVAL 5000
#define AC_MIN_ECHO_INTERVAL 1000
#define AC_ECHO_INTERVAL 30000
#define AC_MAX_ECHO_INTERVAL 256000
#define AC_MAX_DATA_KEEPALIVE_INTERVAL 256000
#define AC_MIN_DISCOVERY_INTERVAL 2000
#define AC_DISCOVERY_INTERVAL 20000
#define AC_MAX_DISCOVERY_INTERVAL 180000
#define AC_DECRYPT_ERROR_PERIOD_INTERVAL 120000
#define AC_IDLE_TIMEOUT_INTERVAL 300000
#define AC_WTP_FALLBACK_MODE CAPWAP_WTP_FALLBACK_ENABLED
/* */
#define compat_json_object_object_get(obj, key) ({ \
json_bool error; struct json_object* result = NULL; \
error = json_object_object_get_ex(obj, key, &result); \
(error ? result : NULL); \
})
/* */
struct ac_if_datachannel {
unsigned long index;
int ifindex;
char ifname[IFNAMSIZ];
int mtu;
char bridge[IFNAMSIZ];
};
/* */
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;
/* */
struct capwap_acipv4list_element acipv4list;
struct capwap_acipv6list_element acipv6list;
};
/* */
struct ac_fds {
int fdstotalcount;
struct pollfd* fdspoll;
int fdsnetworkcount;
int msgqueuecount;
int msgqueuestartpos;
struct ac_kmod_event* kmodevents;
int kmodeventscount;
int kmodeventsstartpos;
};
/* AC */
struct ac_t {
int standalone;
int running;
/* */
struct ac_state dfa;
struct capwap_network net;
struct capwap_list* addrlist;
unsigned short mtu;
struct capwap_array* binding;
struct capwap_acname_element acname;
struct capwap_acdescriptor_element descriptor;
/* Sessions message queue */
int fdmsgsessions[2];
/* Kernel module */
struct ac_kmod_handle kmodhandle;
/* Sessions */
struct capwap_list* sessions;
struct capwap_list* sessionsthread;
capwap_rwlock_t sessionslock;
/* Authorative Stations */
struct capwap_hash* authstations;
capwap_rwlock_t authstationslock;
/* Data Channel Interfaces */
struct capwap_hash* ifdatachannel;
capwap_rwlock_t ifdatachannellock;
/* Dtls */
int enabledtls;
struct capwap_dtls_context dtlscontext;
/* Backend Management */
char* backendacid;
char* backendversion;
struct capwap_array* availablebackends;
};
/* AC session thread */
struct ac_session_thread_t {
pthread_t threadid;
};
/* AC session message queue item */
#define AC_MESSAGE_QUEUE_CLOSE_THREAD 1
#define AC_MESSAGE_QUEUE_CLOSE_ALLSESSIONS 2
#define AC_MESSAGE_QUEUE_UPDATE_CONFIGURATION 3
struct ac_session_msgqueue_item_t {
unsigned long message;
union {
struct {
pthread_t threadid;
} message_close_thread;
struct {
struct json_object* jsonroot;
} message_configuration;
};
};
extern struct ac_t g_ac;
/* Primary thread */
int ac_execute(void);
int ac_execute_update_fdspool(struct ac_fds* fds);
int ac_valid_binding(unsigned short binding);
void ac_update_statistics(void);
#endif /* __CAPWAP_AC_HEADER__ */

View File

@ -1,481 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static struct ac_json_ieee80211_ops* ac_json_80211_message_elements[] = {
/* CAPWAP_ELEMENT_80211_ADD_WLAN */ &ac_json_80211_addwlan_ops,
/* CAPWAP_ELEMENT_80211_ANTENNA */ &ac_json_80211_antenna_ops,
/* CAPWAP_ELEMENT_80211_ASSIGN_BSSID */ &ac_json_80211_assignbssid_ops,
/* CAPWAP_ELEMENT_80211_DELETE_WLAN */ &ac_json_80211_deletewlan_ops,
/* CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL */ &ac_json_80211_directsequencecontrol_ops,
/* CAPWAP_ELEMENT_80211_IE */ &ac_json_80211_ie_ops,
/* CAPWAP_ELEMENT_80211_MACOPERATION */ &ac_json_80211_macoperation_ops,
/* CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES */ &ac_json_80211_miccountermeasures_ops,
/* CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY */ &ac_json_80211_multidomaincapability_ops,
/* CAPWAP_ELEMENT_80211_OFDMCONTROL */ &ac_json_80211_ofdmcontrol_ops,
/* CAPWAP_ELEMENT_80211_RATESET */ &ac_json_80211_rateset_ops,
/* CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT */ &ac_json_80211_rsnaerrorreport_ops,
/* CAPWAP_ELEMENT_80211_STATION */ NULL,
/* CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE */ NULL,
/* CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE */ NULL,
/* CAPWAP_ELEMENT_80211_STATISTICS */ &ac_json_80211_statistics_ops,
/* CAPWAP_ELEMENT_80211_SUPPORTEDRATES */ &ac_json_80211_supportedrates_ops,
/* CAPWAP_ELEMENT_80211_TXPOWER */ &ac_json_80211_txpower_ops,
/* CAPWAP_ELEMENT_80211_TXPOWERLEVEL */ &ac_json_80211_txpowerlevel_ops,
/* CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS */ NULL,
/* CAPWAP_ELEMENT_80211_UPDATE_WLAN */ &ac_json_80211_updatewlan_ops,
/* CAPWAP_ELEMENT_80211_WTP_QOS */ &ac_json_80211_wtpqos_ops,
/* CAPWAP_ELEMENT_80211_WTP_RADIO_CONF */ &ac_json_80211_wtpradioconf_ops,
/* CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM */ &ac_json_80211_wtpradiofailalarm_ops,
/* CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION */ &ac_json_80211_wtpradioinformation_ops
};
/* */
static struct ac_json_ieee80211_ops *
ac_json_80211_getops_by_capwaptype(const struct capwap_message_element_id type)
{
int i;
for (i = 0; i < CAPWAP_80211_MESSAGE_ELEMENTS_COUNT; i++) {
if (ac_json_80211_message_elements[i] &&
memcmp(&ac_json_80211_message_elements[i]->type, &type, sizeof(type)) == 0)
return ac_json_80211_message_elements[i];
}
return NULL;
}
/* */
static struct ac_json_ieee80211_ops* ac_json_80211_getops_by_jsontype(char* type)
{
int i;
for (i = 0; i < CAPWAP_80211_MESSAGE_ELEMENTS_COUNT; i++) {
if (ac_json_80211_message_elements[i] &&
strcmp(ac_json_80211_message_elements[i]->json_type, type) == 0)
return ac_json_80211_message_elements[i];
}
return NULL;
}
/* */
void ac_json_ieee80211_init(struct ac_json_ieee80211_wtpradio* wtpradio) {
ASSERT(wtpradio != NULL);
memset(wtpradio, 0, sizeof(struct ac_json_ieee80211_wtpradio));
}
/* */
void ac_json_ieee80211_free(struct ac_json_ieee80211_wtpradio* wtpradio) {
int i, j;
ASSERT(wtpradio != NULL);
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
struct ac_json_ieee80211_item* item = &wtpradio->items[i];
if (item->valid) {
if (item->addwlan) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_ADD_WLAN)->free(item->addwlan);
}
if (item->antenna) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_ANTENNA)->free(item->antenna);
}
if (item->assignbssid) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_ASSIGN_BSSID)->free(item->assignbssid);
}
if (item->deletewlan) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_DELETE_WLAN)->free(item->deletewlan);
}
if (item->directsequencecontrol) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL)->free(item->directsequencecontrol);
}
if (item->iearray) {
const struct capwap_message_elements_ops* ieops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_IE);
for (j = 0; j < item->iearray->count; j++) {
ieops->free(*(struct capwap_80211_ie_element**)capwap_array_get_item_pointer(item->iearray, j));
}
capwap_array_free(item->iearray);
}
if (item->macoperation) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_MACOPERATION)->free(item->macoperation);
}
if (item->miccountermeasures) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES)->free(item->miccountermeasures);
}
if (item->multidomaincapability) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY)->free(item->multidomaincapability);
}
if (item->ofdmcontrol) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_OFDMCONTROL)->free(item->ofdmcontrol);
}
if (item->rateset) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_RATESET)->free(item->rateset);
}
if (item->rsnaerrorreport) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT)->free(item->rsnaerrorreport);
}
if (item->statistics) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_STATISTICS)->free(item->statistics);
}
if (item->supportedrates) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_SUPPORTEDRATES)->free(item->supportedrates);
}
if (item->txpower) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_TXPOWER)->free(item->txpower);
}
if (item->txpowerlevel) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_TXPOWERLEVEL)->free(item->txpowerlevel);
}
if (item->updatewlan) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_UPDATE_WLAN)->free(item->updatewlan);
}
if (item->wtpqos) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTP_QOS)->free(item->wtpqos);
}
if (item->wtpradioconf) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTP_RADIO_CONF)->free(item->wtpradioconf);
}
if (item->wtpradiofailalarm) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM)->free(item->wtpradiofailalarm);
}
if (item->wtpradioinformation) {
capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)->free(item->wtpradioinformation);
}
}
}
}
/* */
int ac_json_ieee80211_addmessageelement(struct ac_json_ieee80211_wtpradio *wtpradio,
const struct capwap_message_element_id id,
void *data, int overwrite)
{
struct ac_json_ieee80211_ops* ops;
ASSERT(wtpradio != NULL);
ASSERT(IS_80211_MESSAGE_ELEMENTS(id));
ASSERT(data != NULL);
/* */
ops = ac_json_80211_getops_by_capwaptype(id);
if (!ops)
return 0;
return ops->add_message_element(wtpradio, data, overwrite);
}
/* */
int ac_json_ieee80211_parsingmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, struct capwap_message_element_itemlist* messageelement) {
int i;
ASSERT(wtpradio != NULL);
ASSERT(messageelement != NULL);
ASSERT(IS_80211_MESSAGE_ELEMENTS(messageelement->id));
switch (messageelement->category) {
case CAPWAP_MESSAGE_ELEMENT_SINGLE:
if (!ac_json_ieee80211_addmessageelement(wtpradio, messageelement->id,
messageelement->data, 0))
return 0;
break;
case CAPWAP_MESSAGE_ELEMENT_ARRAY: {
struct capwap_array* items =
(struct capwap_array*)messageelement->data;
for (i = 0; i < items->count; i++)
if (!ac_json_ieee80211_addmessageelement(wtpradio, messageelement->id,
*(void**)capwap_array_get_item_pointer(items, i), 0))
return 0;
break;
}
default:
return 0;
}
return 1;
}
/* */
int ac_json_ieee80211_parsingjson(struct ac_json_ieee80211_wtpradio* wtpradio, struct json_object* jsonroot) {
int i;
int length;
ASSERT(wtpradio != NULL);
ASSERT(jsonroot != NULL);
if (json_object_get_type(jsonroot) != json_type_array) {
return 0;
}
/* */
length = json_object_array_length(jsonroot);
for (i = 0; i < length; i++) {
struct json_object* jsonitem;
struct json_object* jsonradio = json_object_array_get_idx(jsonroot, i);
/* Get RadioID */
jsonitem = compat_json_object_object_get(jsonradio, "RadioID");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int radioid = json_object_get_int(jsonitem);
if (IS_VALID_RADIOID(radioid)) {
struct lh_entry* entry;
/* Parsing every entry */
for(entry = json_object_get_object(jsonradio)->head; entry != NULL; entry = entry->next) {
struct ac_json_ieee80211_ops* ops = ac_json_80211_getops_by_jsontype((char*)entry->k); /* Retrieve JSON handler */
if (ops) {
void* data = ops->create((struct json_object*)entry->v, radioid);
if (data) {
/* Message element complete */
ac_json_ieee80211_addmessageelement(wtpradio, ops->type, data, 1);
/* Free resource */
capwap_get_message_element_ops(ops->type)->free(data);
}
}
}
}
}
}
return 1;
}
/* */
struct json_object* ac_json_ieee80211_getjson(struct ac_json_ieee80211_wtpradio* wtpradio) {
int i;
struct json_object* jsonarray;
struct json_object* jsonitems;
ASSERT(wtpradio != NULL);
jsonarray = json_object_new_array();
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
struct ac_json_ieee80211_item* item = &wtpradio->items[i];
if (!item->valid) {
continue;
}
/* */
jsonitems = json_object_new_object();
/* Radio Id */
json_object_object_add(jsonitems, "RadioID", json_object_new_int(i + 1));
if (item->addwlan) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_ADD_WLAN)->create_json(jsonitems, item->addwlan);
}
if (item->antenna) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_ANTENNA)->create_json(jsonitems, item->antenna);
}
if (item->assignbssid) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_ASSIGN_BSSID)->create_json(jsonitems, item->assignbssid);
}
if (item->deletewlan) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_DELETE_WLAN)->create_json(jsonitems, item->deletewlan);
}
if (item->directsequencecontrol) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL)->create_json(jsonitems, item->directsequencecontrol);
}
if (item->iearray) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_IE)->create_json(jsonitems, item->iearray);
}
if (item->macoperation) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_MACOPERATION)->create_json(jsonitems, item->macoperation);
}
if (item->miccountermeasures) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES)->create_json(jsonitems, item->miccountermeasures);
}
if (item->multidomaincapability) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY)->create_json(jsonitems, item->multidomaincapability);
}
if (item->ofdmcontrol) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_OFDMCONTROL)->create_json(jsonitems, item->ofdmcontrol);
}
if (item->rateset) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_RATESET)->create_json(jsonitems, item->rateset);
}
if (item->rsnaerrorreport) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT)->create_json(jsonitems, item->rsnaerrorreport);
}
if (item->statistics) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_STATISTICS)->create_json(jsonitems, item->statistics);
}
if (item->supportedrates) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_SUPPORTEDRATES)->create_json(jsonitems, item->supportedrates);
}
if (item->txpower) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_TXPOWER)->create_json(jsonitems, item->txpower);
}
if (item->txpowerlevel) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_TXPOWERLEVEL)->create_json(jsonitems, item->txpowerlevel);
}
if (item->updatewlan) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_UPDATE_WLAN)->create_json(jsonitems, item->updatewlan);
}
if (item->wtpqos) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_WTP_QOS)->create_json(jsonitems, item->wtpqos);
}
if (item->wtpradioconf) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_WTP_RADIO_CONF)->create_json(jsonitems, item->wtpradioconf);
}
if (item->wtpradiofailalarm) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM)->create_json(jsonitems, item->wtpradiofailalarm);
}
if (item->wtpradioinformation) {
ac_json_80211_getops_by_capwaptype(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)->create_json(jsonitems, item->wtpradioinformation);
}
/* */
json_object_array_add(jsonarray, jsonitems);
}
return jsonarray;
}
/* */
void ac_json_ieee80211_buildpacket(struct ac_json_ieee80211_wtpradio* wtpradio, struct capwap_packet_txmng* txmngpacket) {
int i, j;
ASSERT(wtpradio != NULL);
ASSERT(txmngpacket != NULL);
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
struct ac_json_ieee80211_item* item = &wtpradio->items[i];
if (item->valid) {
if (item->addwlan) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ADD_WLAN, item->addwlan);
}
if (item->antenna) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ANTENNA, item->antenna);
}
if (item->assignbssid) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ASSIGN_BSSID, item->assignbssid);
}
if (item->deletewlan) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN, item->deletewlan);
}
if (item->directsequencecontrol) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL, item->directsequencecontrol);
}
if (item->iearray) {
for (j = 0; j < item->iearray->count; j++) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_IE, *(struct capwap_80211_ie_element**)capwap_array_get_item_pointer(item->iearray, j));
}
}
if (item->macoperation) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MACOPERATION, item->macoperation);
}
if (item->miccountermeasures) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES, item->miccountermeasures);
}
if (item->multidomaincapability) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY, item->multidomaincapability);
}
if (item->ofdmcontrol) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_OFDMCONTROL, item->ofdmcontrol);
}
if (item->rateset) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_RATESET, item->rateset);
}
if (item->rsnaerrorreport) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT, item->rsnaerrorreport);
}
if (item->statistics) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_STATISTICS, item->statistics);
}
if (item->supportedrates) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_SUPPORTEDRATES, item->supportedrates);
}
if (item->txpower) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWER, item->txpower);
}
if (item->txpowerlevel) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWERLEVEL, item->txpowerlevel);
}
if (item->updatewlan) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN, item->updatewlan);
}
if (item->wtpqos) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_QOS, item->wtpqos);
}
if (item->wtpradioconf) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_RADIO_CONF, item->wtpradioconf);
}
if (item->wtpradiofailalarm) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM, item->wtpradiofailalarm);
}
if (item->wtpradioinformation) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, item->wtpradioinformation);
}
}
}
}

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_addwlan_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_addwlan_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_addwlan_element* addwlan = (struct capwap_80211_addwlan_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[addwlan->radioid - 1];
const struct capwap_message_elements_ops* ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_ADD_WLAN);
if (item->addwlan) {
if (!overwrite) {
return 0;
}
ops->free(item->addwlan);
}
item->valid = 1;
item->addwlan = (struct capwap_80211_addwlan_element*)ops->clone(addwlan);
return 1;
}
/* */
static void ac_json_80211_addwlan_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_addwlan_ops = {
.type = CAPWAP_ELEMENT_80211_ADD_WLAN,
.json_type = "IEEE80211AddWLAN",
.create = ac_json_80211_addwlan_createmessageelement,
.add_message_element = ac_json_80211_addwlan_addmessageelement,
.create_json = ac_json_80211_addwlan_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_ADDWLAN_HEADER__
#define __AC_JSON_80211_ADDWLAN_HEADER__
#include "capwap_element_80211_addwlan.h"
extern struct ac_json_ieee80211_ops ac_json_80211_addwlan_ops;
#endif /* __AC_JSON_80211_ADDWLAN_HEADER__ */

View File

@ -1,109 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211Antenna: {
Diversity: [bool],
Combiner: [int],
AntennaSelection: [
[int]
]
}
*/
/* */
static void* ac_json_80211_antenna_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_antenna_element* antenna;
antenna = (struct capwap_80211_antenna_element*)capwap_alloc(sizeof(struct capwap_80211_antenna_element));
memset(antenna, 0, sizeof(struct capwap_80211_antenna_element));
antenna->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "Diversity");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_boolean)) {
antenna->diversity = (json_object_get_boolean(jsonitem) ? CAPWAP_ANTENNA_DIVERSITY_ENABLE : CAPWAP_ANTENNA_DIVERSITY_DISABLE);
} else {
capwap_free(antenna);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "Combiner");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
antenna->combiner = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(antenna);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "AntennaSelection");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_array)) {
int i;
int length;
antenna->selections = capwap_array_create(sizeof(uint8_t), 0, 1);
length = json_object_array_length(jsonitem);
for (i = 0; i < length; i++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonitem, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_int)) {
uint8_t* value = (uint8_t*)capwap_array_get_item_pointer(antenna->selections, antenna->selections->count);
*value = (uint8_t)json_object_get_int(jsonvalue);
}
}
} else {
capwap_free(antenna);
return NULL;
}
return antenna;
}
/* */
static int ac_json_80211_antenna_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_antenna_element* antenna = (struct capwap_80211_antenna_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[antenna->radioid - 1];
const struct capwap_message_elements_ops* ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_ANTENNA);
if (item->antenna) {
if (!overwrite) {
return 0;
}
ops->free(item->antenna);
}
item->valid = 1;
item->antenna = (struct capwap_80211_antenna_element*)ops->clone(antenna);
return 1;
}
/* */
static void ac_json_80211_antenna_createjson(struct json_object* jsonparent, void* data) {
int i;
struct json_object* jsonantenna;
struct json_object* jsonitem;
struct capwap_80211_antenna_element* antenna = (struct capwap_80211_antenna_element*)data;
jsonantenna = json_object_new_array();
for (i = 0; i < antenna->selections->count; i++) {
json_object_array_add(jsonantenna, json_object_new_int((int)*(uint8_t*)capwap_array_get_item_pointer(antenna->selections, i)));
}
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "Diversity", json_object_new_boolean((antenna->diversity == CAPWAP_ANTENNA_DIVERSITY_ENABLE) ? 1 : 0));
json_object_object_add(jsonitem, "Combiner", json_object_new_int((int)antenna->combiner));
json_object_object_add(jsonitem, "AntennaSelection", jsonantenna);
json_object_object_add(jsonparent, "IEEE80211Antenna", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_antenna_ops = {
.type = CAPWAP_ELEMENT_80211_ANTENNA,
.json_type = "IEEE80211Antenna",
.create = ac_json_80211_antenna_createmessageelement,
.add_message_element = ac_json_80211_antenna_addmessageelement,
.create_json = ac_json_80211_antenna_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_ANTENNA_HEADER__
#define __AC_JSON_80211_ANTENNA_HEADER__
#include "capwap_element_80211_antenna.h"
extern struct ac_json_ieee80211_ops ac_json_80211_antenna_ops;
#endif /* __AC_JSON_80211_ANTENNA_HEADER__ */

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_assignbssid_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_assignbssid_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_assignbssid_element* assignbssid = (struct capwap_80211_assignbssid_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[assignbssid->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_ASSIGN_BSSID);
if (item->assignbssid) {
if (!overwrite) {
return 0;
}
ops->free(item->assignbssid);
}
item->valid = 1;
item->assignbssid = (struct capwap_80211_assignbssid_element*)ops->clone(assignbssid);
return 1;
}
/* */
static void ac_json_80211_assignbssid_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_assignbssid_ops = {
.type = CAPWAP_ELEMENT_80211_ASSIGN_BSSID,
.json_type = "IEEE80211AssignBSSID",
.create = ac_json_80211_assignbssid_createmessageelement,
.add_message_element = ac_json_80211_assignbssid_addmessageelement,
.create_json = ac_json_80211_assignbssid_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_ASSIGNBSSID_HEADER__
#define __AC_JSON_80211_ASSIGNBSSID_HEADER__
#include "capwap_element_80211_assignbssid.h"
extern struct ac_json_ieee80211_ops ac_json_80211_assignbssid_ops;
#endif /* __AC_JSON_80211_ASSIGNBSSID_HEADER__ */

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_deletewlan_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_deletewlan_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_deletewlan_element* deletewlan = (struct capwap_80211_deletewlan_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[deletewlan->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_DELETE_WLAN);
if (item->deletewlan) {
if (!overwrite) {
return 0;
}
ops->free(item->deletewlan);
}
item->valid = 1;
item->deletewlan = (struct capwap_80211_deletewlan_element*)ops->clone(deletewlan);
return 1;
}
/* */
static void ac_json_80211_deletewlan_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_deletewlan_ops = {
.type = CAPWAP_ELEMENT_80211_DELETE_WLAN,
.json_type = "IEEE80211DeleteWLAN",
.create = ac_json_80211_deletewlan_createmessageelement,
.add_message_element = ac_json_80211_deletewlan_addmessageelement,
.create_json = ac_json_80211_deletewlan_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_DELETEWLAN_HEADER__
#define __AC_JSON_80211_DELETEWLAN_HEADER__
#include "capwap_element_80211_deletewlan.h"
extern struct ac_json_ieee80211_ops ac_json_80211_deletewlan_ops;
#endif /* __AC_JSON_80211_DELETEWLAN_HEADER__ */

View File

@ -1,88 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211DirectSequenceControl: {
CurrentChan: [int],
CurrentCCA: [int],
EnergyDetectThreshold: [int]
}
*/
/* */
static void* ac_json_80211_directsequencecontrol_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_directsequencecontrol_element* directsequencecontrol;
directsequencecontrol = (struct capwap_80211_directsequencecontrol_element*)capwap_alloc(sizeof(struct capwap_80211_directsequencecontrol_element));
memset(directsequencecontrol, 0, sizeof(struct capwap_80211_directsequencecontrol_element));
directsequencecontrol->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "CurrentChan");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
directsequencecontrol->currentchannel = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(directsequencecontrol);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "CurrentCCA");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
directsequencecontrol->currentcca = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(directsequencecontrol);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "EnergyDetectThreshold");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
directsequencecontrol->enerydetectthreshold = (uint32_t)json_object_get_int(jsonitem);
} else {
capwap_free(directsequencecontrol);
return NULL;
}
return directsequencecontrol;
}
/* */
static int ac_json_80211_directsequencecontrol_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_directsequencecontrol_element* directsequencecontrol = (struct capwap_80211_directsequencecontrol_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[directsequencecontrol->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL);
if (item->directsequencecontrol) {
if (!overwrite) {
return 0;
}
ops->free(item->directsequencecontrol);
}
item->valid = 1;
item->directsequencecontrol = (struct capwap_80211_directsequencecontrol_element*)ops->clone(directsequencecontrol);
return 1;
}
/* */
static void ac_json_80211_directsequencecontrol_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_directsequencecontrol_element* directsequencecontrol = (struct capwap_80211_directsequencecontrol_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "CurrentChan", json_object_new_int((int)directsequencecontrol->currentchannel));
json_object_object_add(jsonitem, "CurrentCCA", json_object_new_int((int)directsequencecontrol->currentcca));
json_object_object_add(jsonitem, "EnergyDetectThreshold", json_object_new_int((int)directsequencecontrol->enerydetectthreshold));
json_object_object_add(jsonparent, "IEEE80211DirectSequenceControl", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_directsequencecontrol_ops = {
.type = CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL,
.json_type = "IEEE80211DirectSequenceControl",
.create = ac_json_80211_directsequencecontrol_createmessageelement,
.add_message_element = ac_json_80211_directsequencecontrol_addmessageelement,
.create_json = ac_json_80211_directsequencecontrol_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_DIRECTSEQUENCECONTROL_HEADER__
#define __AC_JSON_80211_DIRECTSEQUENCECONTROL_HEADER__
#include "capwap_element_80211_directsequencecontrol.h"
extern struct ac_json_ieee80211_ops ac_json_80211_directsequencecontrol_ops;
#endif /* __AC_JSON_80211_DIRECTSEQUENCECONTROL_HEADER__ */

View File

@ -1,39 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_ie_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_ie_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_ie_element** ieclone;
struct capwap_80211_ie_element* ie = (struct capwap_80211_ie_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[ie->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_IE);
if (!item->iearray) {
item->iearray = capwap_array_create(sizeof(struct capwap_80211_ie_element*), 0, 0);
}
item->valid = 1;
ieclone = (struct capwap_80211_ie_element**)capwap_array_get_item_pointer(item->iearray, item->iearray->count);
*ieclone = (struct capwap_80211_ie_element*)ops->clone(ie);
return 1;
}
/* */
static void ac_json_80211_ie_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_ie_ops = {
.type = CAPWAP_ELEMENT_80211_IE,
.json_type = "IEEE80211IE",
.create = ac_json_80211_ie_createmessageelement,
.add_message_element = ac_json_80211_ie_addmessageelement,
.create_json = ac_json_80211_ie_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_IE_HEADER__
#define __AC_JSON_80211_IE_HEADER__
#include "capwap_element_80211_ie.h"
extern struct ac_json_ieee80211_ops ac_json_80211_ie_ops;
#endif /* __AC_JSON_80211_IE_HEADER__ */

View File

@ -1,118 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211MACOperation: {
RTSThreshold: [int],
ShortRetry: [int],
LongRetry: [int],
FragmentationThreshold: [int],
TxMSDULifetime: [int],
RxMSDULifetime: [int]
}
*/
/* */
static void* ac_json_80211_macoperation_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_macoperation_element* macoperation;
macoperation = (struct capwap_80211_macoperation_element*)capwap_alloc(sizeof(struct capwap_80211_macoperation_element));
memset(macoperation, 0, sizeof(struct capwap_80211_macoperation_element));
macoperation->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "RTSThreshold");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
macoperation->rtsthreshold = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(macoperation);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "ShortRetry");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
macoperation->shortretry = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(macoperation);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "LongRetry");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
macoperation->longretry = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(macoperation);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "FragmentationThreshold");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
macoperation->fragthreshold = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(macoperation);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "TxMSDULifetime");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
macoperation->txmsdulifetime = (uint32_t)json_object_get_int(jsonitem);
} else {
capwap_free(macoperation);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "RxMSDULifetime");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
macoperation->rxmsdulifetime = (uint32_t)json_object_get_int(jsonitem);
} else {
capwap_free(macoperation);
return NULL;
}
return macoperation;
}
/* */
static int ac_json_80211_macoperation_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_macoperation_element* macoperation = (struct capwap_80211_macoperation_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[macoperation->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_MACOPERATION);
if (item->macoperation) {
if (!overwrite) {
return 0;
}
ops->free(item->macoperation);
}
item->valid = 1;
item->macoperation = (struct capwap_80211_macoperation_element*)ops->clone(macoperation);
return 1;
}
/* */
static void ac_json_80211_macoperation_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_macoperation_element* macoperation = (struct capwap_80211_macoperation_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "RTSThreshold", json_object_new_int((int)macoperation->rtsthreshold));
json_object_object_add(jsonitem, "ShortRetry", json_object_new_int((int)macoperation->shortretry));
json_object_object_add(jsonitem, "LongRetry", json_object_new_int((int)macoperation->longretry));
json_object_object_add(jsonitem, "FragmentationThreshold", json_object_new_int((int)macoperation->fragthreshold));
json_object_object_add(jsonitem, "TxMSDULifetime", json_object_new_int((int)macoperation->txmsdulifetime));
json_object_object_add(jsonitem, "RxMSDULifetime", json_object_new_int((int)macoperation->rxmsdulifetime));
json_object_object_add(jsonparent, "IEEE80211MACOperation", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_macoperation_ops = {
.type = CAPWAP_ELEMENT_80211_MACOPERATION,
.json_type = "IEEE80211MACOperation",
.create = ac_json_80211_macoperation_createmessageelement,
.add_message_element = ac_json_80211_macoperation_addmessageelement,
.create_json = ac_json_80211_macoperation_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_MACOPERATION_HEADER__
#define __AC_JSON_80211_MACOPERATION_HEADER__
#include "capwap_element_80211_macoperation.h"
extern struct ac_json_ieee80211_ops ac_json_80211_macoperation_ops;
#endif /* __AC_JSON_80211_MACOPERATION_HEADER__ */

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_miccountermeasures_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_miccountermeasures_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_miccountermeasures_element* miccountermeasures = (struct capwap_80211_miccountermeasures_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[miccountermeasures->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES);
if (item->miccountermeasures) {
if (!overwrite) {
return 0;
}
ops->free(item->miccountermeasures);
}
item->valid = 1;
item->miccountermeasures = (struct capwap_80211_miccountermeasures_element*)ops->clone(miccountermeasures);
return 1;
}
/* */
static void ac_json_80211_miccountermeasures_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_miccountermeasures_ops = {
.type = CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES,
.json_type = "IEEE80211MicCounterMeasures",
.create = ac_json_80211_miccountermeasures_createmessageelement,
.add_message_element = ac_json_80211_miccountermeasures_addmessageelement,
.create_json = ac_json_80211_miccountermeasures_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_MICCOUNTERMEASURES_HEADER__
#define __AC_JSON_80211_MICCOUNTERMEASURES_HEADER__
#include "capwap_element_80211_miccountermeasures.h"
extern struct ac_json_ieee80211_ops ac_json_80211_miccountermeasures_ops;
#endif /* __AC_JSON_80211_MICCOUNTERMEASURES_HEADER__ */

View File

@ -1,88 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211MultiDomainCapability: {
FirstChannel: [int],
NumberChannels: [int],
MaxTxPowerLevel: [int]
}
*/
/* */
static void* ac_json_80211_multidomaincapability_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_multidomaincapability_element* multidomaincapability;
multidomaincapability = (struct capwap_80211_multidomaincapability_element*)capwap_alloc(sizeof(struct capwap_80211_multidomaincapability_element));
memset(multidomaincapability, 0, sizeof(struct capwap_80211_multidomaincapability_element));
multidomaincapability->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "FirstChannel");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
multidomaincapability->firstchannel = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(multidomaincapability);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "NumberChannels");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
multidomaincapability->numberchannels = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(multidomaincapability);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "MaxTxPowerLevel");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
multidomaincapability->maxtxpowerlevel = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(multidomaincapability);
return NULL;
}
return multidomaincapability;
}
/* */
static int ac_json_80211_multidomaincapability_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_multidomaincapability_element* multidomaincapability = (struct capwap_80211_multidomaincapability_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[multidomaincapability->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY);
if (item->multidomaincapability) {
if (!overwrite) {
return 0;
}
ops->free(item->multidomaincapability);
}
item->valid = 1;
item->multidomaincapability = (struct capwap_80211_multidomaincapability_element*)ops->clone(multidomaincapability);
return 1;
}
/* */
static void ac_json_80211_multidomaincapability_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_multidomaincapability_element* multidomaincapability = (struct capwap_80211_multidomaincapability_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "FirstChannel", json_object_new_int((int)multidomaincapability->firstchannel));
json_object_object_add(jsonitem, "NumberChannels", json_object_new_int((int)multidomaincapability->numberchannels));
json_object_object_add(jsonitem, "MaxTxPowerLevel", json_object_new_int((int)multidomaincapability->maxtxpowerlevel));
json_object_object_add(jsonparent, "IEEE80211MultiDomainCapability", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_multidomaincapability_ops = {
.type = CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY,
.json_type = "IEEE80211MultiDomainCapability",
.create = ac_json_80211_multidomaincapability_createmessageelement,
.add_message_element = ac_json_80211_multidomaincapability_addmessageelement,
.create_json = ac_json_80211_multidomaincapability_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_MULTIDOMAINCAPABILITY_HEADER__
#define __AC_JSON_80211_MULTIDOMAINCAPABILITY_HEADER__
#include "capwap_element_80211_multidomaincapability.h"
extern struct ac_json_ieee80211_ops ac_json_80211_multidomaincapability_ops;
#endif /* __AC_JSON_80211_MULTIDOMAINCAPABILITY_HEADER__ */

View File

@ -1,88 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211OFDMControl: {
CurrentChan: [int],
BandSupport: [int],
TIThreshold: [int]
}
*/
/* */
static void* ac_json_80211_ofdmcontrol_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_ofdmcontrol_element* ofdmcontrol;
ofdmcontrol = (struct capwap_80211_ofdmcontrol_element*)capwap_alloc(sizeof(struct capwap_80211_ofdmcontrol_element));
memset(ofdmcontrol, 0, sizeof(struct capwap_80211_ofdmcontrol_element));
ofdmcontrol->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "CurrentChan");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
ofdmcontrol->currentchannel = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(ofdmcontrol);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "BandSupport");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
ofdmcontrol->bandsupport = (uint8_t)json_object_get_int(jsonitem) & CAPWAP_OFDMCONTROL_BAND_MASK;
} else {
capwap_free(ofdmcontrol);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "TIThreshold");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
ofdmcontrol->tithreshold = (uint32_t)json_object_get_int(jsonitem);
} else {
capwap_free(ofdmcontrol);
return NULL;
}
return ofdmcontrol;
}
/* */
static int ac_json_80211_ofdmcontrol_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_ofdmcontrol_element* ofdmcontrol = (struct capwap_80211_ofdmcontrol_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[ofdmcontrol->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_OFDMCONTROL);
if (item->ofdmcontrol) {
if (!overwrite) {
return 0;
}
ops->free(item->ofdmcontrol);
}
item->valid = 1;
item->ofdmcontrol = (struct capwap_80211_ofdmcontrol_element*)ops->clone(ofdmcontrol);
return 1;
}
/* */
static void ac_json_80211_ofdmcontrol_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_ofdmcontrol_element* ofdmcontrol = (struct capwap_80211_ofdmcontrol_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "CurrentChan", json_object_new_int((int)ofdmcontrol->currentchannel));
json_object_object_add(jsonitem, "BandSupport", json_object_new_int((int)ofdmcontrol->bandsupport));
json_object_object_add(jsonitem, "TIThreshold", json_object_new_int((int)ofdmcontrol->tithreshold));
json_object_object_add(jsonparent, "IEEE80211OFDMControl", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_ofdmcontrol_ops = {
.type = CAPWAP_ELEMENT_80211_OFDMCONTROL,
.json_type = "IEEE80211OFDMControl",
.create = ac_json_80211_ofdmcontrol_createmessageelement,
.add_message_element = ac_json_80211_ofdmcontrol_addmessageelement,
.create_json = ac_json_80211_ofdmcontrol_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_OFDMCONTROL_HEADER__
#define __AC_JSON_80211_OFDMCONTROL_HEADER__
#include "capwap_element_80211_ofdmcontrol.h"
extern struct ac_json_ieee80211_ops ac_json_80211_ofdmcontrol_ops;
#endif /* __AC_JSON_80211_OFDMCONTROL_HEADER__ */

View File

@ -1,81 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211Rateset: [
[int]
]
*/
/* */
static void* ac_json_80211_rateset_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
int i;
int length;
struct capwap_80211_rateset_element* rateset;
if (json_object_get_type(jsonparent) != json_type_array) {
return NULL;
}
length = json_object_array_length(jsonparent);
if ((length < CAPWAP_RATESET_MINLENGTH) || (length > CAPWAP_RATESET_MAXLENGTH)) {
return NULL;
}
rateset = (struct capwap_80211_rateset_element*)capwap_alloc(sizeof(struct capwap_80211_rateset_element));
memset(rateset, 0, sizeof(struct capwap_80211_rateset_element));
rateset->radioid = radioid;
for (i = 0; i < length; i++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonparent, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_int)) {
rateset->ratesetcount++;
rateset->rateset[i] = (uint8_t)json_object_get_int(jsonvalue);
}
}
return rateset;
}
/* */
static int ac_json_80211_rateset_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_rateset_element* rateset = (struct capwap_80211_rateset_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[rateset->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_RATESET);
if (item->rateset) {
if (!overwrite) {
return 0;
}
ops->free(item->rateset);
}
item->valid = 1;
item->rateset = (struct capwap_80211_rateset_element*)ops->clone(rateset);
return 1;
}
/* */
static void ac_json_80211_rateset_createjson(struct json_object* jsonparent, void* data) {
int i;
struct json_object* jsonrates;
struct capwap_80211_rateset_element* rateset = (struct capwap_80211_rateset_element*)data;
jsonrates = json_object_new_array();
for (i = 0; i < rateset->ratesetcount; i++) {
json_object_array_add(jsonrates, json_object_new_int((int)rateset->rateset[i]));
}
json_object_object_add(jsonparent, "IEEE80211Rateset", jsonrates);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_rateset_ops = {
.type = CAPWAP_ELEMENT_80211_RATESET,
.json_type = "IEEE80211Rateset",
.create = ac_json_80211_rateset_createmessageelement,
.add_message_element = ac_json_80211_rateset_addmessageelement,
.create_json = ac_json_80211_rateset_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_RATESET_HEADER__
#define __AC_JSON_80211_RATESET_HEADER__
#include "capwap_element_80211_rateset.h"
extern struct ac_json_ieee80211_ops ac_json_80211_rateset_ops;
#endif /* __AC_JSON_80211_RATESET_HEADER__ */

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_rsnaerrorreport_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_rsnaerrorreport_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_rsnaerrorreport_element* rsnaerrorreport = (struct capwap_80211_rsnaerrorreport_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[rsnaerrorreport->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT);
if (item->rsnaerrorreport) {
if (!overwrite) {
return 0;
}
ops->free(item->rsnaerrorreport);
}
item->valid = 1;
item->rsnaerrorreport = (struct capwap_80211_rsnaerrorreport_element*)ops->clone(rsnaerrorreport);
return 1;
}
/* */
static void ac_json_80211_rsnaerrorreport_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_rsnaerrorreport_ops = {
.type = CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT,
.json_type = "IEEE80211RSNAErrorReport",
.create = ac_json_80211_rsnaerrorreport_createmessageelement,
.add_message_element = ac_json_80211_rsnaerrorreport_addmessageelement,
.create_json = ac_json_80211_rsnaerrorreport_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_RSNAERRORREPORT_HEADER__
#define __AC_JSON_80211_RSNAERRORREPORT_HEADER__
#include "capwap_element_80211_rsnaerrorreport.h"
extern struct ac_json_ieee80211_ops ac_json_80211_rsnaerrorreport_ops;
#endif /* __AC_JSON_80211_RSNAERRORREPORT_HEADER__ */

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_statistics_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_statistics_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_statistics_element* statistics = (struct capwap_80211_statistics_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[statistics->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_STATISTICS);
if (item->statistics) {
if (!overwrite) {
return 0;
}
ops->free(item->statistics);
}
item->valid = 1;
item->statistics = (struct capwap_80211_statistics_element*)ops->clone(statistics);
return 1;
}
/* */
static void ac_json_80211_statistics_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_statistics_ops = {
.type = CAPWAP_ELEMENT_80211_STATISTICS,
.json_type = "IEEE80211Statistics",
.create = ac_json_80211_statistics_createmessageelement,
.add_message_element = ac_json_80211_statistics_addmessageelement,
.create_json = ac_json_80211_statistics_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_STATISTICS_HEADER__
#define __AC_JSON_80211_STATISTICS_HEADER__
#include "capwap_element_80211_statistics.h"
extern struct ac_json_ieee80211_ops ac_json_80211_statistics_ops;
#endif /* __AC_JSON_80211_STATISTICS_HEADER__ */

View File

@ -1,81 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211SupportedRates: [
[int]
]
*/
/* */
static void* ac_json_80211_supportedrates_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
int i;
int length;
struct capwap_80211_supportedrates_element* supportedrates;
if (json_object_get_type(jsonparent) != json_type_array) {
return NULL;
}
length = json_object_array_length(jsonparent);
if ((length < CAPWAP_SUPPORTEDRATES_MINLENGTH) || (length > CAPWAP_SUPPORTEDRATES_MAXLENGTH)) {
return NULL;
}
supportedrates = (struct capwap_80211_supportedrates_element*)capwap_alloc(sizeof(struct capwap_80211_supportedrates_element));
memset(supportedrates, 0, sizeof(struct capwap_80211_supportedrates_element));
supportedrates->radioid = radioid;
for (i = 0; i < length; i++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonparent, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_int)) {
supportedrates->supportedratescount++;
supportedrates->supportedrates[i] = (uint8_t)json_object_get_int(jsonvalue);
}
}
return supportedrates;
}
/* */
static int ac_json_80211_supportedrates_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_supportedrates_element* supportedrates = (struct capwap_80211_supportedrates_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[supportedrates->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_SUPPORTEDRATES);
if (item->supportedrates) {
if (!overwrite) {
return 0;
}
ops->free(item->supportedrates);
}
item->valid = 1;
item->supportedrates = (struct capwap_80211_supportedrates_element*)ops->clone(supportedrates);
return 1;
}
/* */
static void ac_json_80211_supportedrates_createjson(struct json_object* jsonparent, void* data) {
int i;
struct json_object* jsonrates;
struct capwap_80211_supportedrates_element* supportedrates = (struct capwap_80211_supportedrates_element*)data;
jsonrates = json_object_new_array();
for (i = 0; i < supportedrates->supportedratescount; i++) {
json_object_array_add(jsonrates, json_object_new_int((int)supportedrates->supportedrates[i]));
}
json_object_object_add(jsonparent, "IEEE80211SupportedRates", jsonrates);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_supportedrates_ops = {
.type = CAPWAP_ELEMENT_80211_SUPPORTEDRATES,
.json_type = "IEEE80211SupportedRates",
.create = ac_json_80211_supportedrates_createmessageelement,
.add_message_element = ac_json_80211_supportedrates_addmessageelement,
.create_json = ac_json_80211_supportedrates_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_SUPPORTEDRATES_HEADER__
#define __AC_JSON_80211_SUPPORTEDRATES_HEADER__
#include "capwap_element_80211_supportedrates.h"
extern struct ac_json_ieee80211_ops ac_json_80211_supportedrates_ops;
#endif /* __AC_JSON_80211_SUPPORTEDRATES_HEADER__ */

View File

@ -1,68 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211TxPower: {
CurrentTxPower: [int]
}
*/
/* */
static void* ac_json_80211_txpower_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_txpower_element* txpower;
txpower = (struct capwap_80211_txpower_element*)capwap_alloc(sizeof(struct capwap_80211_txpower_element));
memset(txpower, 0, sizeof(struct capwap_80211_txpower_element));
txpower->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "CurrentTxPower");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
txpower->currenttxpower = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(txpower);
return NULL;
}
return txpower;
}
/* */
static int ac_json_80211_txpower_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_txpower_element* txpower = (struct capwap_80211_txpower_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[txpower->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_TXPOWER);
if (item->txpower) {
if (!overwrite) {
return 0;
}
ops->free(item->txpower);
}
item->valid = 1;
item->txpower = (struct capwap_80211_txpower_element*)ops->clone(txpower);
return 1;
}
/* */
static void ac_json_80211_txpower_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_txpower_element* txpower = (struct capwap_80211_txpower_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "CurrentTxPower", json_object_new_int((int)txpower->currenttxpower));
json_object_object_add(jsonparent, "IEEE80211TxPower", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_txpower_ops = {
.type = CAPWAP_ELEMENT_80211_TXPOWER,
.json_type = "IEEE80211TxPower",
.create = ac_json_80211_txpower_createmessageelement,
.add_message_element = ac_json_80211_txpower_addmessageelement,
.create_json = ac_json_80211_txpower_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_TXPOWER_HEADER__
#define __AC_JSON_80211_TXPOWER_HEADER__
#include "capwap_element_80211_txpower.h"
extern struct ac_json_ieee80211_ops ac_json_80211_txpower_ops;
#endif /* __AC_JSON_80211_TXPOWER_HEADER__ */

View File

@ -1,81 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211TXPowerLevel: [
[int]
]
*/
/* */
static void* ac_json_80211_txpowerlevel_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
int i;
int length;
struct capwap_80211_txpowerlevel_element* txpowerlevel;
if (json_object_get_type(jsonparent) != json_type_array) {
return NULL;
}
length = json_object_array_length(jsonparent);
if (length > CAPWAP_TXPOWERLEVEL_MAXLENGTH) {
return NULL;
}
txpowerlevel = (struct capwap_80211_txpowerlevel_element*)capwap_alloc(sizeof(struct capwap_80211_txpowerlevel_element));
memset(txpowerlevel, 0, sizeof(struct capwap_80211_txpowerlevel_element));
txpowerlevel->radioid = radioid;
for (i = 0; i < length; i++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonparent, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_int)) {
txpowerlevel->numlevels++;
txpowerlevel->powerlevel[i] = (uint16_t)json_object_get_int(jsonvalue);
}
}
return txpowerlevel;
}
/* */
static int ac_json_80211_txpowerlevel_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_txpowerlevel_element* txpowerlevel = (struct capwap_80211_txpowerlevel_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[txpowerlevel->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_TXPOWERLEVEL);
if (item->txpowerlevel) {
if (!overwrite) {
return 0;
}
ops->free(item->txpowerlevel);
}
item->valid = 1;
item->txpowerlevel = (struct capwap_80211_txpowerlevel_element*)ops->clone(txpowerlevel);
return 1;
}
/* */
static void ac_json_80211_txpowerlevel_createjson(struct json_object* jsonparent, void* data) {
int i;
struct json_object* jsontxpower;
struct capwap_80211_txpowerlevel_element* txpowerlevel = (struct capwap_80211_txpowerlevel_element*)data;
jsontxpower = json_object_new_array();
for (i = 0; i < txpowerlevel->numlevels; i++) {
json_object_array_add(jsontxpower, json_object_new_int((int)txpowerlevel->powerlevel[i]));
}
json_object_object_add(jsonparent, "IEEE80211TXPowerLevel", jsontxpower);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_txpowerlevel_ops = {
.type = CAPWAP_ELEMENT_80211_TXPOWERLEVEL,
.json_type = "IEEE80211TXPowerLevel",
.create = ac_json_80211_txpowerlevel_createmessageelement,
.add_message_element = ac_json_80211_txpowerlevel_addmessageelement,
.create_json = ac_json_80211_txpowerlevel_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_TXPOWERLEVEL_HEADER__
#define __AC_JSON_80211_TXPOWERLEVEL_HEADER__
#include "capwap_element_80211_txpowerlevel.h"
extern struct ac_json_ieee80211_ops ac_json_80211_txpowerlevel_ops;
#endif /* __AC_JSON_80211_TXPOWERLEVEL_HEADER__ */

View File

@ -1,41 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/* */
static void* ac_json_80211_updatewlan_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_updatewlan_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_updatewlan_element* updatewlan = (struct capwap_80211_updatewlan_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[updatewlan->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_UPDATE_WLAN);
if (item->updatewlan) {
if (!overwrite) {
return 0;
}
ops->free(item->updatewlan);
}
item->valid = 1;
item->updatewlan = (struct capwap_80211_updatewlan_element*)ops->clone(updatewlan);
return 1;
}
/* */
static void ac_json_80211_updatewlan_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_updatewlan_ops = {
.type = CAPWAP_ELEMENT_80211_UPDATE_WLAN,
.json_type = "IEEE80211UpdateWLAN",
.create = ac_json_80211_updatewlan_createmessageelement,
.add_message_element = ac_json_80211_updatewlan_addmessageelement,
.create_json = ac_json_80211_updatewlan_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_UPDATEWLAN_HEADER__
#define __AC_JSON_80211_UPDATEWLAN_HEADER__
#include "capwap_element_80211_updatewlan.h"
extern struct ac_json_ieee80211_ops ac_json_80211_updatewlan_ops;
#endif /* __AC_JSON_80211_UPDATEWLAN_HEADER__ */

View File

@ -1,79 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211WTPQoS: {
TaggingPolicy: [int],
Voice: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
Video: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
BestEffort: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
Background: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
}
*/
/* */
static void* ac_json_80211_wtpqos_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
return NULL; /* TODO */
}
/* */
static int ac_json_80211_wtpqos_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_wtpqos_element* wtpqos = (struct capwap_80211_wtpqos_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[wtpqos->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTP_QOS);
if (item->wtpqos) {
if (!overwrite) {
return 0;
}
ops->free(item->wtpqos);
}
item->valid = 1;
item->wtpqos = (struct capwap_80211_wtpqos_element*)ops->clone(wtpqos);
return 1;
}
/* */
static void ac_json_80211_wtpqos_createjson(struct json_object* jsonparent, void* data) {
/* TODO */
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_wtpqos_ops = {
.type = CAPWAP_ELEMENT_80211_WTP_QOS,
.json_type = "IEEE80211WTPQoS",
.create = ac_json_80211_wtpqos_createmessageelement,
.add_message_element = ac_json_80211_wtpqos_addmessageelement,
.create_json = ac_json_80211_wtpqos_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_WTPQOS_HEADER__
#define __AC_JSON_80211_WTPQOS_HEADER__
#include "capwap_element_80211_wtpqos.h"
extern struct ac_json_ieee80211_ops ac_json_80211_wtpqos_ops;
#endif /* __AC_JSON_80211_WTPQOS_HEADER__ */

View File

@ -1,128 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211WTPRadioConfiguration: {
ShortPreamble: [int],
NumBSSIDs: [int],
DTIMPeriod: [int],
BSSID: [string],
BeaconPeriod: [int],
CountryString: [string]
}
*/
/* */
static void* ac_json_80211_wtpradioconf_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_wtpradioconf_element* wtpradioconf;
wtpradioconf = (struct capwap_80211_wtpradioconf_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioconf_element));
memset(wtpradioconf, 0, sizeof(struct capwap_80211_wtpradioconf_element));
wtpradioconf->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "ShortPreamble");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradioconf->shortpreamble = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(wtpradioconf);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "NumBSSIDs");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradioconf->maxbssid = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(wtpradioconf);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "DTIMPeriod");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradioconf->dtimperiod = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(wtpradioconf);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "BSSID");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
if (!capwap_scanf_macaddress((unsigned char*)wtpradioconf->bssid, json_object_get_string(jsonitem), MACADDRESS_EUI48_LENGTH)) {
capwap_free(wtpradioconf);
return NULL;
}
} else {
capwap_free(wtpradioconf);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "BeaconPeriod");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradioconf->beaconperiod = (uint16_t)json_object_get_int(jsonitem);
} else {
capwap_free(wtpradioconf);
return NULL;
}
jsonitem = compat_json_object_object_get(jsonparent, "CountryString");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
const char* country = json_object_get_string(jsonitem);
if (strlen(country) == (CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH - 1)) {
strcpy((char*)wtpradioconf->country, country);
} else {
capwap_free(wtpradioconf);
return NULL;
}
} else {
capwap_free(wtpradioconf);
return NULL;
}
return wtpradioconf;
}
/* */
static int ac_json_80211_wtpradioconf_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_wtpradioconf_element* wtpradioconf = (struct capwap_80211_wtpradioconf_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[wtpradioconf->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTP_RADIO_CONF);
if (item->wtpradioconf) {
if (!overwrite) {
return 0;
}
ops->free(item->wtpradioconf);
}
item->valid = 1;
item->wtpradioconf = (struct capwap_80211_wtpradioconf_element*)ops->clone(wtpradioconf);
return 1;
}
/* */
static void ac_json_80211_wtpradioconf_createjson(struct json_object* jsonparent, void* data) {
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
struct json_object* jsonitem;
struct capwap_80211_wtpradioconf_element* wtpradioconf = (struct capwap_80211_wtpradioconf_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "ShortPreamble", json_object_new_int((int)wtpradioconf->shortpreamble));
json_object_object_add(jsonitem, "NumBSSIDs", json_object_new_int((int)wtpradioconf->maxbssid));
json_object_object_add(jsonitem, "DTIMPeriod", json_object_new_int((int)wtpradioconf->dtimperiod));
json_object_object_add(jsonitem, "BSSID", json_object_new_string(capwap_printf_macaddress(buffer, wtpradioconf->bssid, MACADDRESS_EUI48_LENGTH)));
json_object_object_add(jsonitem, "BeaconPeriod", json_object_new_int((int)wtpradioconf->beaconperiod));
json_object_object_add(jsonitem, "CountryString", json_object_new_string((char*)wtpradioconf->country));
json_object_object_add(jsonparent, "IEEE80211WTPRadioConfiguration", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_wtpradioconf_ops = {
.type = CAPWAP_ELEMENT_80211_WTP_RADIO_CONF,
.json_type = "IEEE80211WTPRadioConfiguration",
.create = ac_json_80211_wtpradioconf_createmessageelement,
.add_message_element = ac_json_80211_wtpradioconf_addmessageelement,
.create_json = ac_json_80211_wtpradioconf_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_WTPRADIOCONF_HEADER__
#define __AC_JSON_80211_WTPRADIOCONF_HEADER__
#include "capwap_element_80211_wtpradioconf.h"
extern struct ac_json_ieee80211_ops ac_json_80211_wtpradioconf_ops;
#endif /* __AC_JSON_80211_WTPRADIOCONF_HEADER__ */

View File

@ -1,79 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211WTPRadioFailAlarm: {
Type: [int],
Status: [int]
}
*/
/* */
static void* ac_json_80211_wtpradiofailalarm_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_wtpradiofailalarm_element* wtpradiofailalarm;
wtpradiofailalarm = (struct capwap_80211_wtpradiofailalarm_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradiofailalarm_element));
memset(wtpradiofailalarm, 0, sizeof(struct capwap_80211_wtpradiofailalarm_element));
wtpradiofailalarm->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "Type");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradiofailalarm->type = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(wtpradiofailalarm);
return NULL;
}
/* */
jsonitem = compat_json_object_object_get(jsonparent, "Status");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradiofailalarm->status = (uint8_t)json_object_get_int(jsonitem);
} else {
capwap_free(wtpradiofailalarm);
return NULL;
}
return wtpradiofailalarm;
}
/* */
static int ac_json_80211_wtpradiofailalarm_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_wtpradiofailalarm_element* wtpradiofailalarm = (struct capwap_80211_wtpradiofailalarm_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[wtpradiofailalarm->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM);
if (item->wtpradiofailalarm) {
if (!overwrite) {
return 0;
}
ops->free(item->wtpradiofailalarm);
}
item->valid = 1;
item->wtpradiofailalarm = (struct capwap_80211_wtpradiofailalarm_element*)ops->clone(wtpradiofailalarm);
return 1;
}
/* */
static void ac_json_80211_wtpradiofailalarm_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_wtpradiofailalarm_element* wtpradiofailalarm = (struct capwap_80211_wtpradiofailalarm_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "Type", json_object_new_int((int)wtpradiofailalarm->type));
json_object_object_add(jsonitem, "Status", json_object_new_int((int)wtpradiofailalarm->status));
json_object_object_add(jsonparent, "IEEE80211WTPRadioFailAlarm", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_wtpradiofailalarm_ops = {
.type = CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM,
.json_type = "IEEE80211WTPRadioFailAlarm",
.create = ac_json_80211_wtpradiofailalarm_createmessageelement,
.add_message_element = ac_json_80211_wtpradiofailalarm_addmessageelement,
.create_json = ac_json_80211_wtpradiofailalarm_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_WTPRADIOFAILALARM_HEADER__
#define __AC_JSON_80211_WTPRADIOFAILALARM_HEADER__
#include "capwap_element_80211_wtpradiofailalarm.h"
extern struct ac_json_ieee80211_ops ac_json_80211_wtpradiofailalarm_ops;
#endif /* __AC_JSON_80211_WTPRADIOFAILALARM_HEADER__ */

View File

@ -1,68 +0,0 @@
#include "ac.h"
#include "ac_json.h"
/*
IEEE80211WTPRadioInformation: {
Mode: [int]
}
*/
/* */
static void* ac_json_80211_wtpradioinformation_createmessageelement(struct json_object* jsonparent, uint16_t radioid) {
struct json_object* jsonitem;
struct capwap_80211_wtpradioinformation_element* wtpradioinformation;
wtpradioinformation = (struct capwap_80211_wtpradioinformation_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioinformation_element));
memset(wtpradioinformation, 0, sizeof(struct capwap_80211_wtpradioinformation_element));
wtpradioinformation->radioid = radioid;
/* */
jsonitem = compat_json_object_object_get(jsonparent, "Mode");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
wtpradioinformation->radiotype = (uint32_t)json_object_get_int(jsonitem) & CAPWAP_RADIO_TYPE_MASK;
} else {
capwap_free(wtpradioinformation);
return NULL;
}
return wtpradioinformation;
}
/* */
static int ac_json_80211_wtpradioinformation_addmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite) {
struct capwap_80211_wtpradioinformation_element* wtpradioinformation = (struct capwap_80211_wtpradioinformation_element*)data;
struct ac_json_ieee80211_item* item = &wtpradio->items[wtpradioinformation->radioid - 1];
const struct capwap_message_elements_ops *ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
if (item->wtpradioinformation) {
if (!overwrite) {
return 0;
}
ops->free(item->wtpradioinformation);
}
item->valid = 1;
item->wtpradioinformation = (struct capwap_80211_wtpradioinformation_element*)ops->clone(wtpradioinformation);
return 1;
}
/* */
static void ac_json_80211_wtpradioinformation_createjson(struct json_object* jsonparent, void* data) {
struct json_object* jsonitem;
struct capwap_80211_wtpradioinformation_element* wtpradioinformation = (struct capwap_80211_wtpradioinformation_element*)data;
jsonitem = json_object_new_object();
json_object_object_add(jsonitem, "Mode", json_object_new_int((int)wtpradioinformation->radiotype));
json_object_object_add(jsonparent, "IEEE80211WTPRadioInformation", jsonitem);
}
/* */
struct ac_json_ieee80211_ops ac_json_80211_wtpradioinformation_ops = {
.type = CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION,
.json_type = "IEEE80211WTPRadioInformation",
.create = ac_json_80211_wtpradioinformation_createmessageelement,
.add_message_element = ac_json_80211_wtpradioinformation_addmessageelement,
.create_json = ac_json_80211_wtpradioinformation_createjson
};

View File

@ -1,8 +0,0 @@
#ifndef __AC_JSON_80211_WTPRADIOINFORMATION_HEADER__
#define __AC_JSON_80211_WTPRADIOINFORMATION_HEADER__
#include "capwap_element_80211_wtpradioinformation.h"
extern struct ac_json_ieee80211_ops ac_json_80211_wtpradioinformation_ops;
#endif /* __AC_JSON_80211_WTPRADIOINFORMATION_HEADER__ */

View File

@ -1,897 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "ac_backend.h"
#include "ac_soap.h"
#include "ac_session.h"
/* */
#define AC_BACKEND_WAIT_TIMEOUT 10000
#define SOAP_PROTOCOL_RESPONSE_WAIT_EVENT_TIMEOUT 70000
/* */
struct ac_backend_t {
pthread_t threadid;
int endthread;
capwap_event_t wait;
capwap_lock_t lock;
capwap_lock_t backendlock;
/* Backend Soap */
int activebackend;
int backendstatus;
int errorjoinbackend;
/* Session */
char* backendsessionid;
/* Soap Request */
struct ac_http_soap_request* soaprequest;
};
static struct ac_backend_t g_ac_backend;
/* */
static struct ac_http_soap_server* ac_backend_get_server(void) {
return *(struct ac_http_soap_server**)capwap_array_get_item_pointer(g_ac.availablebackends, g_ac_backend.activebackend);
}
/* */
static int ac_backend_parsing_closewtpsession_event(const char* idevent, struct json_object* jsonparams) {
int result = -1;
struct ac_session_t* session;
struct json_object* jsonwtpid;
/* Params CloseWTPSession Action
{
WTPId: [string]
}
*/
/* WTPId */
jsonwtpid = compat_json_object_object_get(jsonparams, "WTPId");
if (!jsonwtpid || (json_object_get_type(jsonwtpid) != json_type_string)) {
return -1;
}
/* Get session */
session = ac_search_session_from_wtpid(json_object_get_string(jsonwtpid));
if (session) {
struct ac_session_notify_event_t notify;
/* Notify Request to Complete Event */
strcpy(notify.idevent, idevent);
notify.action = NOTIFY_ACTION_CHANGE_STATE;
notify.session_state = CAPWAP_DEAD_STATE;
ac_session_send_action(session, AC_SESSION_ACTION_NOTIFY_EVENT, 0, (void*)&notify, sizeof(struct ac_session_notify_event_t));
/* Async close session */
log_printf(LOG_DEBUG, "Receive close wtp session for WTP %s", session->wtpid);
ac_session_send_action(session, AC_SESSION_ACTION_CLOSE, 0, NULL, 0);
/* */
ac_session_release_reference(session);
result = 0;
}
return result;
}
/* */
static int ac_backend_parsing_resetwtp_event(const char* idevent, struct json_object* jsonparams) {
int result = -1;
struct ac_session_t* session;
struct json_object* jsonwtpid;
struct json_object* jsonimage;
struct json_object* jsonvendor;
struct json_object* jsondata;
/* Params ResetWTP Action
{
WTPId: [string],
ImageIdentifier: {
Vendor: [int],
Data: [string]
}
}
*/
/* WTPId */
jsonwtpid = compat_json_object_object_get(jsonparams, "WTPId");
if (!jsonwtpid || (json_object_get_type(jsonwtpid) != json_type_string)) {
return -1;
}
/* ImageIdentifier */
jsonimage = compat_json_object_object_get(jsonparams, "ImageIdentifier");
if (!jsonimage || (json_object_get_type(jsonimage) != json_type_object)) {
return -1;
}
jsonvendor = compat_json_object_object_get(jsonimage, "Vendor");
jsondata = compat_json_object_object_get(jsonimage, "Data");
if (!jsonvendor || !jsondata || (json_object_get_type(jsonvendor) != json_type_int) || (json_object_get_type(jsondata) != json_type_string)) {
return -1;
}
/* Get session */
session = ac_search_session_from_wtpid(json_object_get_string(jsonwtpid));
if (session) {
const char* name = json_object_get_string(jsondata);
if (name && *name) {
int length;
struct ac_notify_reset_t* reset;
struct ac_session_notify_event_t notify;
/* Notification data */
length = sizeof(struct ac_notify_reset_t) + strlen(name) + 1;
reset = (struct ac_notify_reset_t*)capwap_alloc(length);
/* */
reset->vendor = (uint32_t)json_object_get_int(jsonvendor);
strcpy((char*)reset->name, name);
/* Notify Request to Complete Event */
strcpy(notify.idevent, idevent);
notify.action = NOTIFY_ACTION_CHANGE_STATE;
notify.session_state = CAPWAP_DEAD_STATE;
ac_session_send_action(session, AC_SESSION_ACTION_NOTIFY_EVENT, 0, (void*)&notify, sizeof(struct ac_session_notify_event_t));
/* Notify Action */
log_printf(LOG_DEBUG, "Receive reset request for WTP %s", session->wtpid);
ac_session_send_action(session, AC_SESSION_ACTION_RESET_WTP, 0, (void*)reset, length);
result = 0;
/* */
capwap_free(reset);
}
ac_session_release_reference(session);
}
return result;
}
/* */
static int ac_backend_parsing_addwlan_event(const char* idevent, struct json_object* jsonparams) {
int result = -1;
struct ac_session_t* session;
struct json_object* jsonwtpid;
struct json_object* jsonradioid;
struct json_object* jsonwlanid;
struct json_object* jsoncapability;
struct json_object* jsonqos;
struct json_object* jsonauthtype;
struct json_object* jsonmacmode;
struct json_object* jsontunnelmode;
struct json_object* jsonhidessid;
struct json_object* jsonssid;
const char* ssid;
/* Params AddWLAN Action
{
WTPID: [string],
RadioID: [int],
WLANID: [int],
Capability: [int],
Key: {
TODO
},
DefaultQoS: [int],
AuthType: [int],
MACMode: [int],
TunnelMode: [int],
SuppressSSID: [bool],
SSID: [string],
IE: {
TODO
}
}
*/
/* WTPID */
jsonwtpid = compat_json_object_object_get(jsonparams, "WTPID");
if (!jsonwtpid || (json_object_get_type(jsonwtpid) != json_type_string)) {
return -1;
}
/* RadioID */
jsonradioid = compat_json_object_object_get(jsonparams, "RadioID");
if (!jsonradioid || (json_object_get_type(jsonradioid) != json_type_int)) {
return -1;
}
/* WLANID */
jsonwlanid = compat_json_object_object_get(jsonparams, "WLANID");
if (!jsonwlanid || (json_object_get_type(jsonwlanid) != json_type_int)) {
return -1;
}
/* Capability */
jsoncapability = compat_json_object_object_get(jsonparams, "Capability");
if (!jsoncapability || (json_object_get_type(jsoncapability) != json_type_int)) {
return -1;
}
/* Key */
/* TODO */
/* DefaultQoS */
jsonqos = compat_json_object_object_get(jsonparams, "DefaultQoS");
if (!jsonqos || (json_object_get_type(jsonqos) != json_type_int)) {
return -1;
}
/* AuthType */
jsonauthtype = compat_json_object_object_get(jsonparams, "AuthType");
if (!jsonauthtype || (json_object_get_type(jsonauthtype) != json_type_int)) {
return -1;
}
/* MACMode */
jsonmacmode = compat_json_object_object_get(jsonparams, "MACMode");
if (!jsonmacmode || (json_object_get_type(jsonmacmode) != json_type_int)) {
return -1;
}
/* TunnelMode */
jsontunnelmode = compat_json_object_object_get(jsonparams, "TunnelMode");
if (!jsontunnelmode || (json_object_get_type(jsontunnelmode) != json_type_int)) {
return -1;
}
/* SuppressSSID */
jsonhidessid = compat_json_object_object_get(jsonparams, "SuppressSSID");
if (!jsonhidessid || (json_object_get_type(jsonhidessid) != json_type_boolean)) {
return -1;
}
/* SSID */
jsonssid = compat_json_object_object_get(jsonparams, "SSID");
if (jsonssid && (json_object_get_type(jsonssid) == json_type_string)) {
ssid = json_object_get_string(jsonssid);
if (strlen(ssid) > CAPWAP_ADD_WLAN_SSID_LENGTH) {
return -1;
}
} else {
return -1;
}
/* IE */
/* TODO */
/* Get session */
session = ac_search_session_from_wtpid(json_object_get_string(jsonwtpid));
if (session) {
int length;
struct ac_notify_addwlan_t* addwlan;
struct ac_session_notify_event_t notify;
/* Notification data */
length = sizeof(struct ac_notify_addwlan_t);
addwlan = (struct ac_notify_addwlan_t*)capwap_alloc(length);
/* */
addwlan->radioid = (uint8_t)json_object_get_int(jsonradioid);
addwlan->wlanid = (uint8_t)json_object_get_int(jsonwlanid);
addwlan->capability = (uint16_t)json_object_get_int(jsoncapability);
addwlan->qos = (uint8_t)json_object_get_int(jsonqos);
addwlan->authmode = (uint8_t)json_object_get_int(jsonauthtype);
addwlan->macmode = (uint8_t)json_object_get_int(jsonmacmode);
addwlan->tunnelmode = (uint8_t)json_object_get_int(jsontunnelmode);
addwlan->suppressssid = (uint8_t)(json_object_get_boolean(jsonhidessid) ? 1 : 0);
strcpy(addwlan->ssid, ssid);
/* Notify Request to Complete Event */
strcpy(notify.idevent, idevent);
notify.action = NOTIFY_ACTION_RECEIVE_RESPONSE_CONTROLMESSAGE;
notify.ctrlmsg_type = CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE;
ac_session_send_action(session, AC_SESSION_ACTION_NOTIFY_EVENT, 0, (void*)&notify, sizeof(struct ac_session_notify_event_t));
/* Notify Action */
log_printf(LOG_DEBUG, "Receive AddWLAN request for WTP %s with SSID: %s", session->wtpid, addwlan->ssid);
ac_session_send_action(session, AC_SESSION_ACTION_ADDWLAN, 0, (void*)addwlan, length);
/* */
ac_session_release_reference(session);
capwap_free(addwlan);
result = 0;
}
return result;
}
/* */
static int ac_backend_parsing_updatewlan_event(const char* idevent, struct json_object* jsonparams) {
int result = -1;
return result;
}
/* */
static int ac_backend_parsing_deletewlan_event(const char* idevent, struct json_object* jsonparams) {
int result = -1;
return result;
}
/* */
static int ac_backend_soap_update_event(const char* idevent, int status) {
int result = 0;
char buffer[256];
struct ac_soap_request* request = NULL;
struct ac_http_soap_server* server;
ASSERT(g_ac_backend.soaprequest == NULL);
ASSERT(g_ac_backend.backendsessionid != NULL);
/* Get HTTP Soap Server */
server = ac_backend_get_server();
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Build Soap Request */
if (!g_ac_backend.endthread) {
request = ac_soapclient_create_request("updateBackendEvent", SOAP_NAMESPACE_URI);
if (request) {
ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
ac_soapclient_add_param(request, "xs:string", "idevent", idevent);
ac_soapclient_add_param(request, "xs:int", "status", capwap_itoa(status, buffer));
g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
}
}
capwap_lock_exit(&g_ac_backend.lock);
/* */
if (!g_ac_backend.soaprequest) {
if (request) {
ac_soapclient_free_request(request);
}
return 0;
}
/* Send Request & Recv Response */
if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
if (response) {
ac_soapclient_free_response(response);
}
}
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Free resource */
ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
g_ac_backend.soaprequest = NULL;
capwap_lock_exit(&g_ac_backend.lock);
return result;
}
/* */
static int ac_backend_soap_getconfiguration(void) {
int result = -1;
struct ac_soap_request* request = NULL;
struct ac_http_soap_server* server;
struct json_object* jsonroot = NULL;
ASSERT(g_ac_backend.soaprequest == NULL);
ASSERT(g_ac_backend.backendsessionid != NULL);
/* Get HTTP Soap Server */
server = ac_backend_get_server();
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Build Soap Request */
if (!g_ac_backend.endthread) {
request = ac_soapclient_create_request("getConfiguration", SOAP_NAMESPACE_URI);
if (request) {
ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
}
}
capwap_lock_exit(&g_ac_backend.lock);
/* */
if (!g_ac_backend.soaprequest) {
if (request) {
ac_soapclient_free_request(request);
}
return -1;
}
/* Send Request & Recv Response */
if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
if (response) {
/* Get Configuration result */
jsonroot = ac_soapclient_parse_json_response(response);
ac_soapclient_free_response(response);
}
}
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Free resource */
ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
g_ac_backend.soaprequest = NULL;
capwap_lock_exit(&g_ac_backend.lock);
/* Send JSON command to primary thread */
if (jsonroot) {
result = ac_msgqueue_update_configuration(jsonroot);
if (result) {
json_object_put(jsonroot);
}
}
return result;
}
/* */
static int ac_backend_soap_join(int forcereset) {
struct ac_soap_request* request = NULL;
struct ac_http_soap_server* server;
ASSERT(g_ac_backend.soaprequest == NULL);
ASSERT(g_ac_backend.backendsessionid == NULL);
/* Get HTTP Soap Server */
server = ac_backend_get_server();
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Build Soap Request */
if (!g_ac_backend.endthread) {
request = ac_soapclient_create_request("joinBackend", SOAP_NAMESPACE_URI);
if (request) {
ac_soapclient_add_param(request, "xs:string", "idac", g_ac.backendacid);
ac_soapclient_add_param(request, "xs:string", "version", g_ac.backendversion);
ac_soapclient_add_param(request, "xs:boolean", "forcereset", (forcereset ? "true" : "false"));
g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
}
}
capwap_lock_exit(&g_ac_backend.lock);
/* */
if (!g_ac_backend.soaprequest) {
if (request) {
ac_soapclient_free_request(request);
}
return -1;
}
/* Send Request & Recv Response */
if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
if (response) {
/* Get join result */
if ((response->responsecode == HTTP_RESULT_OK) && response->xmlResponseReturn) {
xmlChar* xmlResult = xmlNodeGetContent(response->xmlResponseReturn);
if (xmlStrlen(xmlResult)) {
g_ac_backend.backendsessionid = capwap_duplicate_string((const char*)xmlResult);
}
xmlFree(xmlResult);
}
/* */
ac_soapclient_free_response(response);
}
}
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Free resource */
ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
g_ac_backend.soaprequest = NULL;
capwap_lock_exit(&g_ac_backend.lock);
/* Retrieve AC configuration */
if (g_ac_backend.backendsessionid && forcereset) {
if (ac_backend_soap_getconfiguration()) {
log_printf(LOG_ERR, "Unable to get AC configuration from Backend Server");
capwap_free(g_ac_backend.backendsessionid);
g_ac_backend.backendsessionid = NULL;
}
}
return (g_ac_backend.backendsessionid ? 0 : -1);
}
/* */
static int ac_backend_parsing_event(struct json_object* jsonitem) {
int result = -1;
struct json_object* jsonvalue;
ASSERT(jsonitem != NULL);
/* Receive event into JSON result
{
EventID: [int],
Action: [string],
Params: {
<Depends on the Action>
}
}
*/
/* Get EventID */
jsonvalue = compat_json_object_object_get(jsonitem, "EventID");
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_string)) {
const char* idevent = json_object_get_string(jsonvalue);
/* Get Action */
jsonvalue = compat_json_object_object_get(jsonitem, "Action");
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_string)) {
const char* action = json_object_get_string(jsonvalue);
if (action) {
jsonvalue = compat_json_object_object_get(jsonitem, "Params");
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
/* Parsing params according to the action */
if (!strcmp(action, "CloseWTPSession")) {
result = ac_backend_parsing_closewtpsession_event(idevent, jsonvalue);
} else if (!strcmp(action, "ResetWTP")) {
result = ac_backend_parsing_resetwtp_event(idevent, jsonvalue);
} else if (!strcmp(action, "AddWLAN")) {
result = ac_backend_parsing_addwlan_event(idevent, jsonvalue);
} else if (!strcmp(action, "UpdateWLAN")) {
result = ac_backend_parsing_updatewlan_event(idevent, jsonvalue);
} else if (!strcmp(action, "DeleteWLAN")) {
result = ac_backend_parsing_deletewlan_event(idevent, jsonvalue);
}
/* Notify result action */
ac_backend_soap_update_event(idevent, (!result ? SOAP_EVENT_STATUS_RUNNING : SOAP_EVENT_STATUS_GENERIC_ERROR));
}
}
}
}
return result;
}
/* */
static int ac_backend_soap_waitevent(void) {
int result = -1;
struct ac_soap_request* request = NULL;
struct ac_http_soap_server* server;
struct json_object* jsonroot = NULL;
ASSERT(g_ac_backend.soaprequest == NULL);
ASSERT(g_ac_backend.backendsessionid != NULL);
/* Get HTTP Soap Server */
server = ac_backend_get_server();
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Build Soap Request */
if (!g_ac_backend.endthread) {
request = ac_soapclient_create_request("waitBackendEvent", SOAP_NAMESPACE_URI);
if (request) {
ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
/* Change result timeout */
g_ac_backend.soaprequest->responsetimeout = SOAP_PROTOCOL_RESPONSE_WAIT_EVENT_TIMEOUT;
}
}
capwap_lock_exit(&g_ac_backend.lock);
/* */
if (!g_ac_backend.soaprequest) {
if (request) {
ac_soapclient_free_request(request);
}
return -1;
}
/* Send Request & Recv Response */
if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
if (response) {
/* Wait event result */
jsonroot = ac_soapclient_parse_json_response(response);
ac_soapclient_free_response(response);
}
}
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Free resource */
ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
g_ac_backend.soaprequest = NULL;
capwap_lock_exit(&g_ac_backend.lock);
/* Parsing JSON command after close event request */
if (jsonroot) {
if (json_object_get_type(jsonroot) == json_type_array) {
int i;
int length;
/* Parsing every message into JSON result */
length = json_object_array_length(jsonroot);
if (!length) {
result = 0;
} else {
for (i = 0; i < length; i++) {
struct json_object* jsonitem = json_object_array_get_idx(jsonroot, i);
if (jsonitem && (json_object_get_type(jsonitem) == json_type_object)) {
result = ac_backend_parsing_event(jsonitem);
if (result) {
break;
}
}
}
}
}
/* Free JSON */
json_object_put(jsonroot);
}
return result;
}
/* */
static void ac_backend_soap_leave(void) {
struct ac_soap_request* request;
struct ac_http_soap_server* server;
ASSERT(g_ac_backend.soaprequest == NULL);
/* */
if (!g_ac_backend.backendstatus || !g_ac_backend.backendsessionid) {
return;
}
/* Get HTTP Soap Server */
server = ac_backend_get_server();
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Build Soap Request */
request = ac_soapclient_create_request("leaveBackend", SOAP_NAMESPACE_URI);
if (request) {
ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server);
}
capwap_lock_exit(&g_ac_backend.lock);
/* */
if (!g_ac_backend.soaprequest) {
if (request) {
ac_soapclient_free_request(request);
}
return;
}
/* Send Request & Recv Response */
if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) {
struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest);
if (response) {
ac_soapclient_free_response(response);
}
}
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
/* Free resource */
ac_soapclient_close_request(g_ac_backend.soaprequest, 1);
g_ac_backend.soaprequest = NULL;
capwap_lock_exit(&g_ac_backend.lock);
}
/* */
static void ac_backend_run(void) {
int connected = 0;
int forcereset = 1;
capwap_lock_enter(&g_ac_backend.backendlock);
while (!g_ac_backend.endthread) {
if (connected) {
if (ac_backend_soap_waitevent()) {
if (g_ac_backend.endthread) {
break;
}
/* Connection error, change Backend Server */
connected = 0;
log_printf(LOG_DEBUG, "Lost connection with Backend Server");
capwap_lock_enter(&g_ac_backend.backendlock);
/* Lost session id */
capwap_free(g_ac_backend.backendsessionid);
g_ac_backend.backendsessionid = NULL;
/* Change backend */
g_ac_backend.activebackend = (g_ac_backend.activebackend + 1) % g_ac.availablebackends->count;
}
} else {
/* Join with a Backend Server */
if (!ac_backend_soap_join(forcereset)) {
log_printf(LOG_DEBUG, "Joined with Backend Server");
/* Join Complete */
connected = 1;
forcereset = 0;
g_ac_backend.backendstatus = 1;
g_ac_backend.errorjoinbackend = 0;
capwap_lock_exit(&g_ac_backend.backendlock);
} else {
/* Change Backend Server */
g_ac_backend.activebackend = (g_ac_backend.activebackend + 1) % g_ac.availablebackends->count;
g_ac_backend.errorjoinbackend++;
/* Wait timeout before continue */
if (g_ac_backend.errorjoinbackend >= g_ac.availablebackends->count) {
log_printf(LOG_DEBUG, "Unable to join with Backend Server");
/* */
forcereset = 1;
g_ac_backend.backendstatus = 0;
g_ac_backend.errorjoinbackend = 0;
capwap_lock_exit(&g_ac_backend.backendlock);
/* Close all sessions */
ac_msgqueue_close_allsessions();
/* Wait before retry join to backend server */
capwap_event_wait_timeout(&g_ac_backend.wait, AC_BACKEND_WAIT_TIMEOUT);
capwap_lock_enter(&g_ac_backend.backendlock);
}
}
}
}
/* Leave Backend */
ac_backend_soap_leave();
g_ac_backend.backendstatus = 0;
/* */
if (g_ac_backend.backendsessionid) {
capwap_free(g_ac_backend.backendsessionid);
g_ac_backend.backendsessionid = NULL;
}
/* */
if (!connected) {
capwap_lock_exit(&g_ac_backend.backendlock);
}
}
/* */
static void* ac_backend_thread(void* param) {
log_printf(LOG_DEBUG, "Backend start");
ac_backend_run();
log_printf(LOG_DEBUG, "Backend stop");
/* Thread exit */
pthread_exit(NULL);
return NULL;
}
/* */
int ac_backend_isconnect(void) {
return (g_ac_backend.backendstatus ? 1 : 0);
}
/* */
struct ac_http_soap_request* ac_backend_createrequest_with_session(char* method, char* uri) {
struct ac_http_soap_server* server;
struct ac_soap_request* request;
struct ac_http_soap_request* soaprequest = NULL;
/* Get active connection only if Backend Management Thread is not trying to connect with a Backend Server */
capwap_lock_enter(&g_ac_backend.backendlock);
if (ac_backend_isconnect()) {
server = ac_backend_get_server();
/* Build Soap Request */
request = ac_soapclient_create_request(method, SOAP_NAMESPACE_URI);
if (request) {
soaprequest = ac_soapclient_prepare_request(request, server);
if (soaprequest) {
ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid);
} else {
ac_soapclient_free_request(request);
}
}
}
capwap_lock_exit(&g_ac_backend.backendlock);
return soaprequest;
}
/* */
int ac_backend_start(void) {
int result;
memset(&g_ac_backend, 0, sizeof(struct ac_backend_t));
/* */
if (!g_ac.backendacid) {
log_printf(LOG_ERR, "AC Backend ID isn't set");
return 0;
} else if (!g_ac.backendversion) {
log_printf(LOG_ERR, "Backend Protocol Version isn't set");
return 0;
} else if (!g_ac.availablebackends->count) {
log_printf(LOG_ERR, "List of available backends is empty");
return 0;
}
/* Init */
capwap_lock_init(&g_ac_backend.lock);
capwap_lock_init(&g_ac_backend.backendlock);
capwap_event_init(&g_ac_backend.wait);
/* Create thread */
result = pthread_create(&g_ac_backend.threadid, NULL, ac_backend_thread, NULL);
if (result) {
log_printf(LOG_DEBUG, "Unable create backend thread");
return 0;
}
return 1;
}
/* */
void ac_backend_stop(void) {
void* dummy;
g_ac_backend.endthread = 1;
/* Critical section */
capwap_lock_enter(&g_ac_backend.lock);
if (g_ac_backend.soaprequest) {
ac_soapclient_shutdown_request(g_ac_backend.soaprequest);
}
/* */
capwap_lock_exit(&g_ac_backend.lock);
capwap_event_signal(&g_ac_backend.wait);
/* Wait close thread */
pthread_join(g_ac_backend.threadid, &dummy);
}
/* */
void ac_backend_free(void) {
capwap_event_destroy(&g_ac_backend.wait);
capwap_lock_destroy(&g_ac_backend.lock);
capwap_lock_destroy(&g_ac_backend.backendlock);
}

View File

@ -1,22 +0,0 @@
#ifndef __AC_BACKEND_HEADER__
#define __AC_BACKEND_HEADER__
/* */
#define SOAP_NAMESPACE_URI "http://smartcapwap/namespace"
/* SOAP event status*/
#define SOAP_EVENT_STATUS_GENERIC_ERROR -1
#define SOAP_EVENT_STATUS_CANCEL -2
#define SOAP_EVENT_STATUS_RUNNING 0
#define SOAP_EVENT_STATUS_COMPLETE 1
/* */
int ac_backend_start(void);
void ac_backend_stop(void);
void ac_backend_free(void);
/* */
int ac_backend_isconnect(void);
struct ac_http_soap_request* ac_backend_createrequest_with_session(char* method, char* uri);
#endif /* __AC_BACKEND_HEADER__ */

View File

@ -1,772 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
#include "ac_json.h"
#include "ac_wlans.h"
#include <json-c/json.h>
#include <arpa/inet.h>
/* */
static void ac_dfa_state_configure_set_radio_configuration(struct ac_session_t* session, struct ac_json_ieee80211_wtpradio* wtpradio) {
int i;
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
struct ac_json_ieee80211_item* item = &wtpradio->items[i];
if (item->valid) {
struct ac_device* device = &session->wlans->devices[i];
/* Set rates */
if (item->rateset || item->supportedrates) {
if (item->rateset) {
memcpy(device->supportedrates, item->rateset->rateset, item->rateset->ratesetcount);
device->supportedratescount = item->rateset->ratesetcount;
} else if (item->supportedrates) {
memcpy(device->supportedrates, item->supportedrates->supportedrates, item->supportedrates->supportedratescount);
device->supportedratescount = item->supportedrates->supportedratescount;
}
}
}
}
}
/* */
static struct ac_soap_response* ac_dfa_state_configure_parsing_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int i;
const char* jsonmessage;
char* base64confstatus;
struct json_object* jsonarray;
struct json_object* jsonparam;
struct json_object* jsonhash;
struct capwap_array* elemarray;
struct capwap_statisticstimer_element* statisticstimer;
struct capwap_wtprebootstat_element* wtprebootstat;
struct capwap_wtpstaticipaddress_element* wtpstaticipaddress;
struct ac_soap_response* response;
unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* Create SOAP request with JSON param
{
RadioAdministrativeState: [
{
RadioID: [int],
AdminState: [int]
}
],
StatisticsTimer: {
StatisticsTimer: [int]
},
WTPRebootStatistics: {
RebootCount: [int],
ACInitiatedCount: [int],
LinkFailureCount: [int],
SWFailureCount: [int],
HWFailureCount: [int],
OtherFailureCount: [int],
UnknownFailureCount: [int],
LastFailureType: [int]
},
ACNamePriority: [
{
Priority: [int],
ACName: [string]
}
],
WTPStaticIPAddressInformation: {
IPAddress: [string],
Netmask: [string],
Gateway: [string],
Static: [int]
},
<IEEE 802.11 BINDING>
WTPRadio: [
{
RadioID: [int],
IEEE80211Antenna: {
Diversity: [bool],
Combiner: [int],
AntennaSelection: [
[int]
]
},
IEEE80211DirectSequenceControl: {
CurrentChan: [int],
CurrentCCA: [int],
EnergyDetectThreshold: [int]
},
IEEE80211MACOperation: {
RTSThreshold: [int],
ShortRetry: [int],
LongRetry: [int],
FragmentationThreshold: [int],
TxMSDULifetime: [int],
RxMSDULifetime: [int]
},
IEEE80211MultiDomainCapability: {
FirstChannel: [int],
NumberChannels: [int],
MaxTxPowerLevel: [int]
},
IEEE80211OFDMControl: {
CurrentChan: [int],
BandSupport: [int],
TIThreshold: [int]
},
IEEE80211SupportedRates: [
[int]
],
IEEE80211TxPower: {
CurrentTxPower: [int]
},
IEEE80211TXPowerLevel: [
[int]
],
IEEE80211WTPRadioConfiguration: {
ShortPreamble: [int],
NumBSSIDs: [int],
DTIMPeriod: [int],
BSSID: [string],
BeaconPeriod: [int],
CountryString: [string]
},
IEEE80211WTPRadioInformation: {
Mode: [int]
}
}
]
}
*/
/* */
jsonparam = json_object_new_object();
/* RadioAdministrativeState */
jsonarray = json_object_new_array();
elemarray = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RADIOADMSTATE);
for (i = 0; i < elemarray->count; i++) {
struct json_object* jsonradioadm;
struct capwap_radioadmstate_element* radioadm = *(struct capwap_radioadmstate_element**)capwap_array_get_item_pointer(elemarray, i);
/* */
jsonradioadm = json_object_new_object();
json_object_object_add(jsonradioadm, "RadioID", json_object_new_int((int)radioadm->radioid));
json_object_object_add(jsonradioadm, "AdminState", json_object_new_int((int)radioadm->state));
json_object_array_add(jsonarray, jsonradioadm);
}
json_object_object_add(jsonparam, "RadioAdministrativeState", jsonarray);
/* StatisticsTimer */
statisticstimer = (struct capwap_statisticstimer_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_STATISTICSTIMER);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "StatisticsTimer", json_object_new_int((int)statisticstimer->timer));
json_object_object_add(jsonparam, "StatisticsTimer", jsonhash);
/* WTPRebootStatistics */
wtprebootstat = (struct capwap_wtprebootstat_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "RebootCount", json_object_new_int((int)wtprebootstat->rebootcount));
json_object_object_add(jsonhash, "ACInitiatedCount", json_object_new_int((int)wtprebootstat->acinitiatedcount));
json_object_object_add(jsonhash, "LinkFailureCount", json_object_new_int((int)wtprebootstat->linkfailurecount));
json_object_object_add(jsonhash, "SWFailureCount", json_object_new_int((int)wtprebootstat->swfailurecount));
json_object_object_add(jsonhash, "HWFailureCount", json_object_new_int((int)wtprebootstat->hwfailurecount));
json_object_object_add(jsonhash, "OtherFailureCount", json_object_new_int((int)wtprebootstat->otherfailurecount));
json_object_object_add(jsonhash, "UnknownFailureCount", json_object_new_int((int)wtprebootstat->unknownfailurecount));
json_object_object_add(jsonhash, "LastFailureType", json_object_new_int((int)wtprebootstat->lastfailuretype));
json_object_object_add(jsonparam, "WTPRebootStatistics", jsonhash);
/* ACNamePriority */
elemarray = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ACNAMEPRIORITY);
if (elemarray && elemarray->count) {
jsonarray = json_object_new_array();
for (i = 0; i < elemarray->count; i++) {
json_object* jacname;
struct capwap_acnamepriority_element* acname = *(struct capwap_acnamepriority_element**)capwap_array_get_item_pointer(elemarray, i);
/* */
jacname = json_object_new_object();
json_object_object_add(jacname, "Priority", json_object_new_int((int)acname->priority));
json_object_object_add(jacname, "ACName", json_object_new_string((char*)acname->name));
json_object_array_add(jsonarray, jacname);
}
json_object_object_add(jsonparam, "ACNamePriority", jsonarray);
}
/* WTPStaticIPAddressInformation */
wtpstaticipaddress = (struct capwap_wtpstaticipaddress_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPSTATICIPADDRESS);
if (wtpstaticipaddress) {
char ipbuffer[INET_ADDRSTRLEN];
/* */
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "IPAddress", json_object_new_string(inet_ntop(AF_INET, (void*)&wtpstaticipaddress->address, ipbuffer, INET_ADDRSTRLEN)));
json_object_object_add(jsonhash, "Netmask", json_object_new_string(inet_ntop(AF_INET, (void*)&wtpstaticipaddress->netmask, ipbuffer, INET_ADDRSTRLEN)));
json_object_object_add(jsonhash, "Gateway", json_object_new_string(inet_ntop(AF_INET, (void*)&wtpstaticipaddress->gateway, ipbuffer, INET_ADDRSTRLEN)));
json_object_object_add(jsonhash, "Static", json_object_new_int((int)wtpstaticipaddress->staticip));
json_object_object_add(jsonparam, "WTPStaticIPAddressInformation", jsonhash);
}
/* Binding message */
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct ac_json_ieee80211_wtpradio wtpradio;
struct capwap_list_item* search = packet->messages->first;
/* Reording message by radioid and management */
ac_json_ieee80211_init(&wtpradio);
while (search) {
struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item;
/* Parsing only IEEE 802.11 message element */
if (IS_80211_MESSAGE_ELEMENTS(messageelement->id)) {
if (!ac_json_ieee80211_parsingmessageelement(&wtpradio, messageelement)) {
json_object_put(jsonparam);
return NULL;
}
}
/* Next */
search = search->next;
}
/* Generate JSON tree */
jsonarray = ac_json_ieee80211_getjson(&wtpradio);
json_object_object_add(jsonparam, IEEE80211_BINDING_JSON_ROOT, jsonarray);
/* Free resource */
ac_json_ieee80211_free(&wtpradio);
}
/* Get JSON param and convert base64 */
jsonmessage = json_object_to_json_string(jsonparam);
base64confstatus = capwap_alloc(AC_BASE64_ENCODE_LENGTH(strlen(jsonmessage)));
ac_base64_string_encode(jsonmessage, base64confstatus);
/* Send message */
response = ac_soap_configurestatuswtpsession(session, session->wtpid, base64confstatus);
/* Free JSON */
json_object_put(jsonparam);
capwap_free(base64confstatus);
return response;
}
/* */
static uint32_t ac_dfa_state_configure_create_response(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct ac_soap_response* response, struct capwap_packet_txmng* txmngpacket) {
int length;
unsigned long i;
struct json_object* jsonroot;
struct json_object* jsonelement;
struct capwap_array* radioadmstate;
struct capwap_timers_element responsetimers;
struct capwap_idletimeout_element responseidletimeout;
struct capwap_wtpfallback_element responsewtpfallback;
unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* Receive SOAP response with JSON result
{
CAPWAPTimers: {
Discovery: [int],
EchoRequest: [int]
},
DecryptionErrorReportPeriod: [
{
RadioID: [int],
ReportInterval: [int]
}
],
IdleTimeout: {
Timeout: [int]
},
WTPFallback: {
Mode: [int]
}
ACIPv4List: [
{
ACIPAddress: [string]
}
],
ACIPv6List: [
{
ACIPAddress: [string]
}
]
WTPStaticIPAddressInformation: {
IPAddress: [string],
Netmask: [string],
Gateway: [string],
Static: [int]
}
<IEEE 802.11 BINDING>
WTPRadio: [
{
RadioID: [int],
IEEE80211Antenna: {
Diversity: [bool],
Combiner: [int],
AntennaSelection: [
[int]
]
},
IEEE80211DirectSequenceControl: {
CurrentChan: [int],
CurrentCCA: [int],
EnergyDetectThreshold: [int]
},
IEEE80211MACOperation: {
RTSThreshold: [int],
ShortRetry: [int],
LongRetry: [int],
FragmentationThreshold: [int],
TxMSDULifetime: [int],
RxMSDULifetime: [int]
},
IEEE80211MultiDomainCapability: {
FirstChannel: [int],
NumberChannels: [int],
MaxTxPowerLevel: [int]
},
IEEE80211OFDMControl: {
CurrentChan: [int],
BandSupport: [int],
TIThreshold: [int]
},
IEEE80211Rateset: [
[int]
],
IEEE80211SupportedRates: [
[int]
],
IEEE80211TxPower: {
CurrentTxPower: [int]
},
IEEE80211WTPQoS: {
TaggingPolicy: [int],
Voice: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
Video: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
BestEffort: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
Background: {
QueueDepth: [int],
CWMin: [int],
CWMax: [int],
AIFS: [int],
Priority8021p: [int],
DSCP: [int]
}
}
IEEE80211WTPRadioConfiguration: {
ShortPreamble: [int],
NumBSSIDs: [int],
DTIMPeriod: [int],
BSSID: [string],
BeaconPeriod: [int],
CountryString: [string]
}
}
]
}
*/
/* Add message elements response, every local value can be overwrite from backend server */
jsonroot = ac_soapclient_parse_json_response(response);
if (!jsonroot) {
return CAPWAP_RESULTCODE_FAILURE;
}
/* CAPWAP Timers */
memcpy(&responsetimers, &session->dfa.timers, sizeof(struct capwap_timers_element));
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "CAPWAPTimers");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_object)) {
struct json_object* jsonitem;
/* Discovery */
jsonitem = compat_json_object_object_get(jsonelement, "Discovery");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int value = json_object_get_int(jsonitem);
if ((value > 0) && (value < 256)) {
responsetimers.discovery = (uint8_t)value;
}
}
/* EchoRequest */
jsonitem = compat_json_object_object_get(jsonelement, "EchoRequest");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int value = json_object_get_int(jsonitem);
if ((value > 0) && (value < 256)) {
responsetimers.echorequest = (uint8_t)value;
}
}
}
}
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TIMERS, &responsetimers);
/* Decryption Error Report Period */
jsonelement = NULL;
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "DecryptionErrorReportPeriod");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
length = json_object_array_length(jsonelement);
} else {
jsonelement = NULL;
}
}
/* Build Decryption Error Report Period List with elements of Radio Administration State */
radioadmstate = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RADIOADMSTATE);
for (i = 0; i < radioadmstate->count; i++) {
struct capwap_decrypterrorreportperiod_element report;
struct capwap_radioadmstate_element* radioadm = *(struct capwap_radioadmstate_element**)capwap_array_get_item_pointer(radioadmstate, i);
report.radioid = radioadm->radioid;
report.interval = session->dfa.decrypterrorreport_interval;
/* Search for JSON overwrite value */
if (jsonelement) {
int j;
for (j = 0; j < length; j++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonitem;
/* RadioID */
jsonitem = compat_json_object_object_get(jsonvalue, "RadioID");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int value = json_object_get_int(jsonitem);
if ((value > 0) && (value < 256) && ((uint8_t)value == report.radioid)) {
/* Get ReportInterval value */
jsonitem = compat_json_object_object_get(jsonvalue, "ReportInterval");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
value = json_object_get_int(jsonitem);
if ((value > 0) && (value < 65536)) {
report.interval = (uint16_t)value;
break;
}
}
}
}
}
}
}
/* */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD, &report);
}
/* IdleTimeout */
memcpy(&responseidletimeout, &session->dfa.idletimeout, sizeof(struct capwap_idletimeout_element));
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "IdleTimeout");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_object)) {
struct json_object* jsonitem;
/* Timeout */
jsonitem = compat_json_object_object_get(jsonelement, "Timeout");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int value = json_object_get_int(jsonitem);
if (value > 0) {
responseidletimeout.timeout = (uint32_t)value;
}
}
}
}
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IDLETIMEOUT, &responseidletimeout);
/* WTPFallback */
memcpy(&responsewtpfallback, &session->dfa.wtpfallback, sizeof(struct capwap_wtpfallback_element));
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "WTPFallback");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_object)) {
struct json_object* jsonitem;
/* Mode */
jsonitem = compat_json_object_object_get(jsonelement, "Mode");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int value = json_object_get_int(jsonitem);
if ((value > 0) && (value < 256)) {
responsewtpfallback.mode = (uint8_t)value;
}
}
}
}
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPFALLBACK, &responsewtpfallback);
/* ACIPv4List */
jsonelement = NULL;
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "ACIPv4List");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
length = json_object_array_length(jsonelement);
} else {
jsonelement = NULL;
}
}
if (jsonelement) {
int j;
struct capwap_acipv4list_element* responseacipv4list;
responseacipv4list = (struct capwap_acipv4list_element*)capwap_alloc(sizeof(struct capwap_acipv4list_element));
responseacipv4list->addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
for (j = 0; j < length; j++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonitem;
/* ACIPAddress */
jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
const char* value = json_object_get_string(jsonitem);
if (value) {
union sockaddr_capwap address;
if (capwap_address_from_string(value, &address)) {
/* Accept only IPv4 address */
if (address.ss.ss_family == AF_INET) {
struct in_addr* responseaddress_in = (struct in_addr*)capwap_array_get_item_pointer(responseacipv4list->addresses, responseacipv4list->addresses->count);
memcpy(responseaddress_in, &address.sin.sin_addr, sizeof(struct in_addr));
}
}
}
}
}
}
if (responseacipv4list->addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, responseacipv4list);
}
capwap_array_free(responseacipv4list->addresses);
capwap_free(responseacipv4list);
} else if (session->dfa.acipv4list.addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, &session->dfa.acipv4list);
}
/* ACIPv6List */
jsonelement = NULL;
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "ACIPv6List");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
length = json_object_array_length(jsonelement);
} else {
jsonelement = NULL;
}
}
if (jsonelement) {
int j;
struct capwap_acipv6list_element* responseacipv6list;
responseacipv6list = (struct capwap_acipv6list_element*)capwap_alloc(sizeof(struct capwap_acipv6list_element));
responseacipv6list->addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
for (j = 0; j < length; j++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonitem;
/* ACIPAddress */
jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
const char* value = json_object_get_string(jsonitem);
if (value) {
union sockaddr_capwap address;
if (capwap_address_from_string(value, &address)) {
/* Accept only IPv6 address */
if (address.ss.ss_family == AF_INET6) {
struct in6_addr* responseaddress_in6 = (struct in6_addr*)capwap_array_get_item_pointer(responseacipv6list->addresses, responseacipv6list->addresses->count);
memcpy(responseaddress_in6, &address.sin6.sin6_addr, sizeof(struct in6_addr));
}
}
}
}
}
}
if (responseacipv6list->addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, responseacipv6list);
}
capwap_array_free(responseacipv6list->addresses);
capwap_free(responseacipv6list);
} else if (session->dfa.acipv6list.addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, &session->dfa.acipv6list);
}
/* WTPStaticIPAddressInformation */
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "WTPStaticIPAddressInformation");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_object)) {
struct json_object* jsonitem;
/* IPAddress */
jsonitem = compat_json_object_object_get(jsonelement, "IPAddress");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
union sockaddr_capwap address;
const char* addressvalue = json_object_get_string(jsonitem);
if (capwap_address_from_string(addressvalue, &address)) {
if (address.ss.ss_family == AF_INET) {
/* Netmask */
jsonitem = compat_json_object_object_get(jsonelement, "Netmask");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
union sockaddr_capwap netmask;
const char* netmaskvalue = json_object_get_string(jsonitem);
if (capwap_address_from_string(netmaskvalue, &netmask)) {
if (netmask.ss.ss_family == AF_INET) {
/* Gateway */
jsonitem = compat_json_object_object_get(jsonelement, "Gateway");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
union sockaddr_capwap gateway;
const char* gatewayvalue = json_object_get_string(jsonitem);
if (capwap_address_from_string(gatewayvalue, &gateway)) {
if (gateway.ss.ss_family == AF_INET) {
/* Static */
jsonitem = compat_json_object_object_get(jsonelement, "Static");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) {
int value = json_object_get_int(jsonitem);
struct capwap_wtpstaticipaddress_element responsewtpstaticipaddress;
memcpy(&responsewtpstaticipaddress.address, &address.sin.sin_addr, sizeof(struct in_addr));
memcpy(&responsewtpstaticipaddress.netmask, &netmask.sin.sin_addr, sizeof(struct in_addr));
memcpy(&responsewtpstaticipaddress.gateway, &gateway.sin.sin_addr, sizeof(struct in_addr));
responsewtpstaticipaddress.staticip = (uint8_t)value;
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPSTATICIPADDRESS, &responsewtpstaticipaddress);
}
}
}
}
}
}
}
}
}
}
}
}
/* WTP Radio Information */
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct ac_json_ieee80211_wtpradio wtpradio;
/* */
ac_json_ieee80211_init(&wtpradio);
/* Parsing SOAP response */
jsonelement = compat_json_object_object_get(jsonroot, IEEE80211_BINDING_JSON_ROOT);
if (jsonelement) {
if (ac_json_ieee80211_parsingjson(&wtpradio, jsonelement)) {
/* Add IEEE802.11 message elements to packet */
ac_json_ieee80211_buildpacket(&wtpradio, txmngpacket);
/* Retrieve frequency and rates configuration */
ac_dfa_state_configure_set_radio_configuration(session, &wtpradio);
}
}
/* Free resource */
ac_json_ieee80211_free(&wtpradio);
}
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
if (jsonroot) {
json_object_put(jsonroot);
}
return CAPWAP_RESULTCODE_SUCCESS;
}
/* */
void ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
ASSERT(session != NULL);
ASSERT(packet != NULL);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Parsing request and add message element for respone message */
response = ac_dfa_state_configure_parsing_request(session, packet);
if (response) {
result = ac_dfa_state_configure_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
}
/* With error add result code message element */
if (!CAPWAP_RESULTCODE_OK(result)) {
struct capwap_resultcode_element resultcode = { .code = result };
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* */
if (result == CAPWAP_RESULTCODE_FAILURE) {
/* TODO: Add AC List Message Elements */
}
}
/* Configure response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Save remote sequence number */
session->remotetype = packet->rxmngpacket->ctrlmsg.type;
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
log_printf(LOG_DEBUG, "Warning: error to send configuration status response packet");
}
/* Change state */
if (CAPWAP_RESULTCODE_OK(result)) {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_CHANGE_STATE_PENDING_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
ac_session_teardown(session);
}
}

View File

@ -1,219 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
#include "ac_json.h"
#include <json-c/json.h>
/* */
static struct ac_soap_response* ac_dfa_state_datacheck_parsing_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int i;
const char* jsonmessage;
char* base64confstatus;
struct capwap_array* elemarray;
struct json_object* jsonarray;
struct json_object* jsonparam;
struct json_object* jsonhash;
struct ac_soap_response* response;
struct capwap_resultcode_element* resultcode;
unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* Create SOAP request with JSON param
{
RadioOperationalState: [
{
RadioID: [int],
State: [int],
Cause: [int]
}
],
ResultCode: {
Code: [int]
},
ReturnedMessageElement: [
{
}
],
<IEEE 802.11 BINDING>
WTPRadio: [
{
RadioID: [int],
IEEE80211WTPRadioFailAlarm: {
Type: [int],
Status: [int]
}
}
}
}
*/
/* */
jsonparam = json_object_new_object();
/* RadioOperationalState */
jsonarray = json_object_new_array();
elemarray = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RADIOOPRSTATE);
for (i = 0; i < elemarray->count; i++) {
json_object* jsonradioops;
struct capwap_radiooprstate_element* radioops = *(struct capwap_radiooprstate_element**)capwap_array_get_item_pointer(elemarray, i);
/* */
jsonradioops = json_object_new_object();
json_object_object_add(jsonradioops, "RadioID", json_object_new_int((int)radioops->radioid));
json_object_object_add(jsonradioops, "State", json_object_new_int((int)radioops->state));
json_object_object_add(jsonradioops, "Cause", json_object_new_int((int)radioops->cause));
json_object_array_add(jsonarray, jsonradioops);
}
json_object_object_add(jsonparam, "RadioOperationalState", jsonarray);
/* ResultCode */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Code", json_object_new_int((int)resultcode->code));
json_object_object_add(jsonparam, "ResultCode", jsonhash);
/* ReturnedMessageElement */
jsonarray = json_object_new_array();
/* TODO */
json_object_object_add(jsonparam, "ReturnedMessageElement", jsonarray);
/* Binding message */
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct ac_json_ieee80211_wtpradio wtpradio;
struct capwap_list_item* search = packet->messages->first;
/* Reording message by radioid and management */
ac_json_ieee80211_init(&wtpradio);
while (search) {
struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item;
/* Parsing only IEEE 802.11 message element */
if (IS_80211_MESSAGE_ELEMENTS(messageelement->id)) {
if (!ac_json_ieee80211_parsingmessageelement(&wtpradio, messageelement)) {
json_object_put(jsonparam);
return NULL;
}
}
/* Next */
search = search->next;
}
/* Generate JSON tree */
jsonarray = ac_json_ieee80211_getjson(&wtpradio);
json_object_object_add(jsonparam, IEEE80211_BINDING_JSON_ROOT, jsonarray);
/* Free resource */
ac_json_ieee80211_free(&wtpradio);
}
/* Get JSON param and convert base64 */
jsonmessage = json_object_to_json_string(jsonparam);
base64confstatus = capwap_alloc(AC_BASE64_ENCODE_LENGTH(strlen(jsonmessage)));
ac_base64_string_encode(jsonmessage, base64confstatus);
/* Send message */
response = ac_soap_changestatewtpsession(session, session->wtpid, base64confstatus);
/* Free JSON */
json_object_put(jsonparam);
capwap_free(base64confstatus);
return response;
}
/* */
static uint32_t ac_dfa_state_datacheck_create_response(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct ac_soap_response* response, struct capwap_packet_txmng* txmngpacket) {
struct json_object* jsonroot;
/* Receive SOAP response with JSON result
{
}
*/
/* Add message elements response, every local value can be overwrite from backend server */
jsonroot = ac_soapclient_parse_json_response(response);
if (!jsonroot) {
return CAPWAP_RESULTCODE_FAILURE;
}
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
if (jsonroot) {
json_object_put(jsonroot);
}
return CAPWAP_RESULTCODE_SUCCESS;
}
/* */
void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
ASSERT(session != NULL);
ASSERT(packet != NULL);
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Parsing request and add message element for respone message */
response = ac_dfa_state_datacheck_parsing_request(session, packet);
if (response) {
result = ac_dfa_state_datacheck_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
/* Create data session */
if (CAPWAP_RESULTCODE_OK(result)) {
if (ac_kmod_new_datasession(&session->sessionid, (uint8_t)session->binding, session->mtu)) {
result = CAPWAP_RESULTCODE_FAILURE;
}
}
}
/* With error add result code message element */
if (!CAPWAP_RESULTCODE_OK(result)) {
struct capwap_resultcode_element resultcode = { .code = result };
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* */
if (result == CAPWAP_RESULTCODE_FAILURE) {
/* TODO: Add AC List Message Elements */
}
}
/* Change event response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Save remote sequence number */
session->remotetype = packet->rxmngpacket->ctrlmsg.type;
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
/* Send Change event response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
log_printf(LOG_DEBUG, "Warning: error to send change event response packet");
}
/* Change state */
if (CAPWAP_RESULTCODE_OK(result)) {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_DATA_CHECK_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
capwap_timeout_set(session->timeout, session->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
ac_session_teardown(session);
}
}

View File

@ -1,23 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
int ac_dtls_setup(struct ac_session_t* session) {
ASSERT(session != NULL);
/* Create DTLS session */
if (!capwap_crypt_createsession(&session->dtls, &g_ac.dtlscontext)) {
return 0;
}
if (capwap_crypt_open(&session->dtls) == CAPWAP_HANDSHAKE_ERROR) {
return 0;
}
/* Wait DTLS handshake complete */
ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_DTLS_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
return 1;
}

View File

@ -1,10 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
/* TODO */
ac_session_teardown(session);
}

View File

@ -1,679 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
#include "ac_backend.h"
#include "ac_json.h"
#include <json-c/json.h>
#include <arpa/inet.h>
/* */
static int ac_dfa_state_join_check_authorizejoin(struct ac_session_t* session, struct ac_soap_response* response) {
xmlChar* xmlResult;
if ((response->responsecode != HTTP_RESULT_OK) || !response->xmlResponseReturn) {
/* TODO: check return failed code */
return CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
// Check return value
xmlResult = xmlNodeGetContent(response->xmlResponseReturn);
if (!xmlResult) {
return CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
} else if (xmlStrcmp(xmlResult, (const xmlChar *)"true")) {
xmlFree(xmlResult);
return CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
xmlFree(xmlResult);
return CAPWAP_RESULTCODE_SUCCESS;
}
/* */
static struct ac_soap_response* ac_dfa_state_join_parsing_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int i;
const char* jsonmessage;
char* base64confstatus;
struct json_object* jsonarray;
struct json_object* jsonparam;
struct json_object* jsonhash;
struct ac_soap_response* response;
struct capwap_location_element* location;
struct capwap_wtpboarddata_element* wtpboarddata;
struct capwap_wtpdescriptor_element* wtpdescriptor;
struct capwap_wtpname_element* wtpname;
struct capwap_wtpframetunnelmode_element* wtpframetunnelmode;
struct capwap_wtpmactype_element* wtpmactype;
struct capwap_ecnsupport_element* ecnsupport;
struct capwap_localipv4_element* localipv4;
struct capwap_localipv6_element* localipv6;
struct capwap_wtprebootstat_element* wtprebootstat;
unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* Create SOAP request with JSON param
{
Binding: {
Type: [int]
}
LocationData: {
Location: [string]
},
WTPBoardData: {
VendorIdentifier: [int],
BoardDataSubElement: [
{
BoardDataType: [int],
BoardDataValue: [base64]
}
]
},
WTPDescriptor: {
MaxRadios: [int],
RadiosInUse: [int],
EncryptionSubElement: [
{
WBID: [int],
EncryptionCapabilities: [int]
}
],
DescriptorSubElement: [
{
DescriptorVendorIdentifier: [int],
DescriptorType: [int],
DescriptorData: [string]
}
]
},
WTPName: {
Name: [string]
},
WTPFrameTunnelMode: {
NativeFrameTunnel: [bool]
FrameTunnelMode8023: [bool],
LocalBridge: [bool]
},
WTPMACType: {
Type: [int]
},
<IEEE 802.11 BINDING>
WTPRadio: [
{
RadioID: [int],
IEEE80211WTPRadioInformation: {
Mode: [int]
}
}
]
ECNSupport: {
Mode: [int]
}
CAPWAPLocalIPv4Address: {
Address: [string]
},
CAPWAPLocalIPv6Address: {
Address: [string]
},
WTPRebootStatistics: {
RebootCount: [int],
ACInitiatedCount: [int],
LinkFailureCount: [int],
SWFailureCount: [int],
HWFailureCount: [int],
OtherFailureCount: [int],
UnknownFailureCount: [int],
LastFailureType: [int]
}
}
*/
/* */
jsonparam = json_object_new_object();
/* Binding */
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Type", json_object_new_int((int)binding));
json_object_object_add(jsonparam, "Binding", jsonhash);
/* LocationData */
location = (struct capwap_location_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_LOCATION);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Location", json_object_new_string((char*)location->value));
json_object_object_add(jsonparam, "LocationData", jsonhash);
/* WTPBoardData */
wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "VendorIdentifier", json_object_new_int((int)wtpboarddata->vendor));
jsonarray = json_object_new_array();
for (i = 0; i < wtpboarddata->boardsubelement->count; i++) {
char* base64data;
int base64length;
struct json_object* jsonboard;
struct capwap_wtpboarddata_board_subelement* wtpboarddata_board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(wtpboarddata->boardsubelement, i);
/* Encoded base64 board data */
base64data = (char*)capwap_alloc(AC_BASE64_ENCODE_LENGTH((int)wtpboarddata_board->length));
base64length = ac_base64_binary_encode((const char*)wtpboarddata_board->data, (int)wtpboarddata_board->length, base64data);
base64data[base64length] = 0;
jsonboard = json_object_new_object();
json_object_object_add(jsonboard, "BoardDataType", json_object_new_int((int)wtpboarddata_board->type));
json_object_object_add(jsonboard, "BoardDataValue", json_object_new_string(base64data));
json_object_array_add(jsonarray, jsonboard);
capwap_free(base64data);
}
json_object_object_add(jsonhash, "BoardDataSubElement", jsonarray);
json_object_object_add(jsonparam, "WTPBoardData", jsonhash);
/* WTPDescriptor */
wtpdescriptor = (struct capwap_wtpdescriptor_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "MaxRadios", json_object_new_int((int)wtpdescriptor->maxradios));
json_object_object_add(jsonhash, "RadiosInUse", json_object_new_int((int)wtpdescriptor->radiosinuse));
jsonarray = json_object_new_array();
for (i = 0; i < wtpdescriptor->encryptsubelement->count; i++) {
struct json_object* jsonencrypt;
struct capwap_wtpdescriptor_encrypt_subelement* wtpdescriptor_encrypt = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(wtpdescriptor->encryptsubelement, i);
jsonencrypt = json_object_new_object();
json_object_object_add(jsonencrypt, "WBID", json_object_new_int((int)wtpdescriptor_encrypt->wbid));
json_object_object_add(jsonencrypt, "EncryptionCapabilities", json_object_new_int((int)wtpdescriptor_encrypt->capabilities));
json_object_array_add(jsonarray, jsonencrypt);
}
json_object_object_add(jsonhash, "EncryptionSubElement", jsonarray);
jsonarray = json_object_new_array();
for (i = 0; i < wtpdescriptor->descsubelement->count; i++) {
struct json_object* jsondesc;
struct capwap_wtpdescriptor_desc_subelement* wtpdescriptor_desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(wtpdescriptor->descsubelement, i);
jsondesc = json_object_new_object();
json_object_object_add(jsondesc, "DescriptorVendorIdentifier", json_object_new_int((int)wtpdescriptor_desc->vendor));
json_object_object_add(jsondesc, "DescriptorType", json_object_new_int((int)wtpdescriptor_desc->type));
json_object_object_add(jsondesc, "DescriptorData", json_object_new_string((char*)wtpdescriptor_desc->data));
json_object_array_add(jsonarray, jsondesc);
}
json_object_object_add(jsonhash, "DescriptorSubElement", jsonarray);
json_object_object_add(jsonparam, "WTPDescriptor", jsonhash);
/* WTPName */
wtpname = (struct capwap_wtpname_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPNAME);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Name", json_object_new_string((char*)wtpname->name));
json_object_object_add(jsonparam, "WTPName", jsonhash);
/* WTPFrameTunnelMode */
wtpframetunnelmode = (struct capwap_wtpframetunnelmode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "NativeFrameTunnel", json_object_new_boolean(((wtpframetunnelmode->mode & CAPWAP_WTP_NATIVE_FRAME_TUNNEL) ? 1 : 0)));
json_object_object_add(jsonhash, "FrameTunnelMode8023", json_object_new_boolean(((wtpframetunnelmode->mode & CAPWAP_WTP_8023_FRAME_TUNNEL) ? 1 : 0)));
json_object_object_add(jsonhash, "LocalBridge", json_object_new_boolean(((wtpframetunnelmode->mode & CAPWAP_WTP_LOCAL_BRIDGING) ? 1 : 0)));
json_object_object_add(jsonparam, "WTPFrameTunnelMode", jsonhash);
/* WTPMACType */
wtpmactype = (struct capwap_wtpmactype_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPMACTYPE);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Type", json_object_new_int((int)wtpmactype->type));
json_object_object_add(jsonparam, "WTPMACType", jsonhash);
/* Binding message */
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct ac_json_ieee80211_wtpradio wtpradio;
struct capwap_list_item* search = packet->messages->first;
/* Reording message by radioid and management */
ac_json_ieee80211_init(&wtpradio);
while (search) {
struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item;
/* Parsing only IEEE 802.11 message element */
if (IS_80211_MESSAGE_ELEMENTS(messageelement->id)) {
if (!ac_json_ieee80211_parsingmessageelement(&wtpradio, messageelement)) {
json_object_put(jsonparam);
return NULL;
}
}
/* Next */
search = search->next;
}
/* Generate JSON tree */
jsonarray = ac_json_ieee80211_getjson(&wtpradio);
json_object_object_add(jsonparam, IEEE80211_BINDING_JSON_ROOT, jsonarray);
/* Free resource */
ac_json_ieee80211_free(&wtpradio);
}
/* ECNSupport */
ecnsupport = (struct capwap_ecnsupport_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ECNSUPPORT);
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Mode", json_object_new_int((int)ecnsupport->flag));
json_object_object_add(jsonparam, "ECNSupport", jsonhash);
/* CAPWAPLocalIPv4Address */
localipv4 = (struct capwap_localipv4_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_LOCALIPV4);
if (localipv4) {
char ipbuffer[INET_ADDRSTRLEN];
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Address", json_object_new_string(inet_ntop(AF_INET, (void*)&localipv4->address, ipbuffer, INET_ADDRSTRLEN)));
json_object_object_add(jsonparam, "CAPWAPLocalIPv4Address", jsonhash);
}
/* CAPWAPLocalIPv6Address */
localipv6 = (struct capwap_localipv6_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_LOCALIPV6);
if (localipv6) {
char ipbuffer[INET6_ADDRSTRLEN];
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "Address", json_object_new_string(inet_ntop(AF_INET6, (void*)&localipv6->address, ipbuffer, INET6_ADDRSTRLEN)));
json_object_object_add(jsonparam, "CAPWAPLocalIPv6Address", jsonhash);
}
/* WTPRebootStatistics */
wtprebootstat = (struct capwap_wtprebootstat_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT);
if (wtprebootstat) {
jsonhash = json_object_new_object();
json_object_object_add(jsonhash, "RebootCount", json_object_new_int((int)wtprebootstat->rebootcount));
json_object_object_add(jsonhash, "ACInitiatedCount", json_object_new_int((int)wtprebootstat->acinitiatedcount));
json_object_object_add(jsonhash, "LinkFailureCount", json_object_new_int((int)wtprebootstat->linkfailurecount));
json_object_object_add(jsonhash, "SWFailureCount", json_object_new_int((int)wtprebootstat->swfailurecount));
json_object_object_add(jsonhash, "HWFailureCount", json_object_new_int((int)wtprebootstat->hwfailurecount));
json_object_object_add(jsonhash, "OtherFailureCount", json_object_new_int((int)wtprebootstat->otherfailurecount));
json_object_object_add(jsonhash, "UnknownFailureCount", json_object_new_int((int)wtprebootstat->unknownfailurecount));
json_object_object_add(jsonhash, "LastFailureType", json_object_new_int((int)wtprebootstat->lastfailuretype));
json_object_object_add(jsonparam, "WTPRebootStatistics", jsonhash);
}
/* Get JSON param and convert base64 */
jsonmessage = json_object_to_json_string(jsonparam);
base64confstatus = capwap_alloc(AC_BASE64_ENCODE_LENGTH(strlen(jsonmessage)));
ac_base64_string_encode(jsonmessage, base64confstatus);
/* Send message */
response = ac_soap_joinwtpsession(session, session->wtpid, base64confstatus);
/* Free JSON */
json_object_put(jsonparam);
capwap_free(base64confstatus);
return response;
}
/* */
static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct ac_soap_response* response, struct capwap_packet_txmng* txmngpacket) {
int i;
int j;
int length;
struct json_object* jsonroot;
struct json_object* jsonelement;
struct capwap_list* controllist;
struct capwap_list_item* item;
unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* Receive SOAP response with JSON result
{
WTPRadioInformation: [
<IEEE 802.11 BINDING>
IEEE80211WTPRadioInformation: {
RadioID: [int],
Mode: [int]
}
]
ACIPv4List: [
{
ACIPAddress: [string]
}
],
ACIPv6List: [
{
ACIPAddress: [string]
}
]
<IEEE 802.11 BINDING>
WTPRadio: [
{
RadioID: [int],
IEEE80211WTPRadioInformation: {
Mode: [int]
}
}
]
}
*/
/* Add message elements response, every local value can be overwrite from backend server */
jsonroot = ac_soapclient_parse_json_response(response);
if (!jsonroot) {
return CAPWAP_RESULTCODE_FAILURE;
}
/* AC Descriptor */
ac_update_statistics();
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor);
/* AC Name */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname);
/* WTP Radio Information */
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct ac_json_ieee80211_wtpradio wtpradio;
struct capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
/* */
ac_json_ieee80211_init(&wtpradio);
/* */
jsonelement = compat_json_object_object_get(jsonroot, IEEE80211_BINDING_JSON_ROOT);
if (jsonelement) {
ac_json_ieee80211_parsingjson(&wtpradio, jsonelement);
}
/* Copy WTP Radio Information if not present into SOAP response */
for (i = 0; i < wtpradioinformation->count; i++) {
ac_json_ieee80211_addmessageelement(&wtpradio, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i), 0);
}
/* */
ac_json_ieee80211_buildpacket(&wtpradio, txmngpacket);
/* Free resource */
ac_json_ieee80211_free(&wtpradio);
}
/* ECN Support */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &session->dfa.ecn);
/* Get information from any local address */
controllist = capwap_list_create();
ac_get_control_information(controllist);
/* CAPWAP Control IP Address */
for (item = controllist->first; item != NULL; item = item->next) {
struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
if (sessioncontrol->localaddress.ss.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_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element);
} else if (sessioncontrol->localaddress.ss.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_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element);
}
}
capwap_list_free(controllist);
/* CAPWAP Local IP Address */
if (session->dtls.localaddr.ss.ss_family == AF_INET) {
struct capwap_localipv4_element addr;
memcpy(&addr.address, &session->dtls.localaddr.sin.sin_addr, sizeof(struct in_addr));
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV4, &addr);
} else if (session->dtls.localaddr.ss.ss_family == AF_INET6) {
struct capwap_localipv6_element addr;
memcpy(&addr.address, &session->dtls.localaddr.sin6.sin6_addr, sizeof(struct in6_addr));
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr);
}
/* ACIPv4List */
jsonelement = NULL;
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "ACIPv4List");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
length = json_object_array_length(jsonelement);
} else {
jsonelement = NULL;
}
}
if (jsonelement) {
struct capwap_acipv4list_element* responseacipv4list;
responseacipv4list = (struct capwap_acipv4list_element*)capwap_alloc(sizeof(struct capwap_acipv4list_element));
responseacipv4list->addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
for (j = 0; j < length; j++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, j);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonitem;
/* ACIPAddress */
jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
const char* value = json_object_get_string(jsonitem);
if (value) {
union sockaddr_capwap address;
if (capwap_address_from_string(value, &address)) {
/* Accept only IPv4 address */
if (address.ss.ss_family == AF_INET) {
struct in_addr* responseaddress_in = (struct in_addr*)capwap_array_get_item_pointer(responseacipv4list->addresses, responseacipv4list->addresses->count);
memcpy(responseaddress_in, &address.sin.sin_addr, sizeof(struct in_addr));
}
}
}
}
}
}
if (responseacipv4list->addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, responseacipv4list);
}
capwap_array_free(responseacipv4list->addresses);
capwap_free(responseacipv4list);
} else if (session->dfa.acipv4list.addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, &session->dfa.acipv4list);
}
/* ACIPv6List */
jsonelement = NULL;
if (jsonroot) {
jsonelement = compat_json_object_object_get(jsonroot, "ACIPv6List");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
length = json_object_array_length(jsonelement);
} else {
jsonelement = NULL;
}
}
if (jsonelement) {
int j;
struct capwap_acipv6list_element* responseacipv6list;
responseacipv6list = (struct capwap_acipv6list_element*)capwap_alloc(sizeof(struct capwap_acipv6list_element));
responseacipv6list->addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
for (j = 0; j < length; j++) {
struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, j);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonitem;
/* ACIPAddress */
jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress");
if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) {
const char* value = json_object_get_string(jsonitem);
if (value) {
union sockaddr_capwap address;
if (capwap_address_from_string(value, &address)) {
/* Accept only IPv6 address */
if (address.ss.ss_family == AF_INET6) {
struct in6_addr* responseaddress_in6 = (struct in6_addr*)capwap_array_get_item_pointer(responseacipv6list->addresses, responseacipv6list->addresses->count);
memcpy(responseaddress_in6, &address.sin6.sin6_addr, sizeof(struct in6_addr));
}
}
}
}
}
}
if (responseacipv6list->addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, responseacipv6list);
}
capwap_array_free(responseacipv6list->addresses);
capwap_free(responseacipv6list);
} else if (session->dfa.acipv6list.addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, &session->dfa.acipv6list);
}
/* CAPWAP Transport Protocol */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &session->dfa.transport);
/* CAPWAP_ELEMENT_IMAGEIDENTIFIER */ /* TODO */
/* CAPWAP_ELEMENT_MAXIMUMLENGTH */ /* TODO */
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
if (jsonroot) {
json_object_put(jsonroot);
}
return CAPWAP_RESULTCODE_SUCCESS;
}
/* */
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
unsigned short binding;
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
struct capwap_sessionid_element* sessionid;
struct capwap_wtpboarddata_element* wtpboarddata;
struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE };
ASSERT(session != NULL);
ASSERT(packet != NULL);
/* Check binding */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (ac_valid_binding(binding)) {
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
/* Get sessionid and verify unique id */
sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID);
if (!ac_has_sessionid(sessionid)) {
char* wtpid;
/* Checking macaddress for detect if WTP already connected */
wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);
/* Get printable WTPID */
wtpid = ac_get_printable_wtpid(wtpboarddata);
if (wtpid && !ac_has_wtpid(wtpid)) {
/* Request authorization of Backend for complete join */
response = ac_soap_authorizewtpsession(session, wtpid);
if (response) {
resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response);
ac_soapclient_free_response(response);
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
} else {
log_printf(LOG_INFO, "WTP Id %s already used in another session", wtpid);
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
}
/* */
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
session->wtpid = wtpid;
memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element));
session->binding = binding;
} else if (wtpid) {
capwap_free(wtpid);
}
} else {
char sessionname[33];
capwap_sessionid_printf(sessionid, sessionname);
log_printf(LOG_INFO, "Session Id %s already used in another session", sessionname);
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
}
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* */
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
response = ac_dfa_state_join_parsing_request(session, packet);
if (response) {
resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket);
ac_soapclient_free_response(response);
}
}
/* Add always result code message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* Join response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Save remote sequence number */
session->remotetype = packet->rxmngpacket->ctrlmsg.type;
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
/* Send Join response to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
ac_session_teardown(session);
}
} else {
/* Error to send packets */
log_printf(LOG_DEBUG, "Warning: error to send join response packet");
ac_session_teardown(session);
}
}
/* */
void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet != NULL);
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
ac_dfa_state_configure(session, packet);
} else if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_IMAGE_DATA_REQUEST) {
ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE);
ac_dfa_state_imagedata(session, packet);
} else {
ac_session_teardown(session);
}
}

View File

@ -1,30 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
unsigned short binding;
ASSERT(session != NULL);
ASSERT(packet != NULL);
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if ((binding == session->binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_RESET_RESPONSE) && (session->localseqnumber == packet->rxmngpacket->ctrlmsg.seq)) {
struct capwap_resultcode_element* resultcode;
/* */
session->localseqnumber++;
/* Check the success of the Request */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
log_printf(LOG_WARNING, "Receive Reset Response with error: %d", (int)resultcode->code);
}
/* */
ac_free_reference_last_request(session);
ac_session_teardown(session);
}
}

View File

@ -1,317 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "capwap_array.h"
#include "ac_session.h"
#include "ac_wlans.h"
/* */
static int receive_echo_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int validsession = 0;
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
/* Check session */
response = ac_soap_checkwtpsession(session, session->wtpid);
if (response) {
if ((response->responsecode == HTTP_RESULT_OK) && response->xmlResponseReturn) {
xmlChar* xmlResult = xmlNodeGetContent(response->xmlResponseReturn);
if (xmlResult) {
if (!xmlStrcmp(xmlResult, (const xmlChar *)"true")) {
validsession = 1;
}
xmlFree(xmlResult);
}
}
ac_soapclient_free_response(response);
}
if (!validsession) {
return -1;
}
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_ECHO_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Add message element */
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
/* Echo response complete, get fragment packets */
ac_free_reference_last_response(session);
capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid);
if (session->responsefragmentpacket->count > 1) {
session->fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Save remote sequence number */
session->remotetype = packet->rxmngpacket->ctrlmsg.type;
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
#ifdef DEBUG
{
char sessionname[33];
capwap_sessionid_printf(&session->sessionid, sessionname);
log_printf(LOG_DEBUG, "Send Echo Response to %s", sessionname);
}
#endif
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
log_printf(LOG_DEBUG, "Warning: error to send echo response packet");
}
return 0;
}
/* */
static void execute_ieee80211_wlan_configuration_addwlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
struct ac_wlan* wlan;
struct capwap_80211_addwlan_element* addwlan;
struct capwap_80211_assignbssid_element* assignbssid;
/* */
addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN);
/* Get BSSID */
assignbssid = (struct capwap_80211_assignbssid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ASSIGN_BSSID);
if (assignbssid && (assignbssid->radioid == addwlan->radioid) && (assignbssid->wlanid == addwlan->wlanid)) {
if (!ac_kmod_addwlan(&session->sessionid, assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid, addwlan->macmode, addwlan->tunnelmode)) {
wlan = ac_wlans_create_bssid(&session->wlans->devices[assignbssid->radioid - 1], assignbssid->wlanid, assignbssid->bssid, addwlan);
/* Assign BSSID to session */
if (ac_wlans_assign_bssid(session, wlan)) {
log_printf(LOG_WARNING, "Unable to add new wlan with radioid: %d, wlanid: %d", (int)assignbssid->radioid, (int)assignbssid->wlanid);
ac_wlans_free_bssid(wlan);
/* TODO: add remove wlan from wtp */
}
} else {
/* TODO: add remove wlan from wtp */
}
}
}
/* */
static void execute_ieee80211_wlan_configuration_updatewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
//struct capwap_80211_updatewlan_element* updatewlan;
/* */
//updatewlan = (struct capwap_80211_updatewlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN);
}
/* */
static void execute_ieee80211_wlan_configuration_deletewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
//struct capwap_80211_deletewlan_element* deletewlan;
/* */
//deletewlan = (struct capwap_80211_deletewlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN);
}
/* */
static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_parsed_packet requestpacket;
struct capwap_packet_rxmng* rxmngrequestpacket;
struct capwap_resultcode_element* resultcode;
/* Check the success of the Request */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (CAPWAP_RESULTCODE_OK(resultcode->code)) {
rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket);
if (rxmngrequestpacket) {
if (capwap_parsing_packet(rxmngrequestpacket, &requestpacket) == PARSING_COMPLETE) {
/* Detect type of IEEE802.11 WLAN Configuration Request */
if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN)) {
execute_ieee80211_wlan_configuration_addwlan(session, packet, &requestpacket);
} else if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN)) {
execute_ieee80211_wlan_configuration_updatewlan(session, packet, &requestpacket);
} else if (capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN)) {
execute_ieee80211_wlan_configuration_deletewlan(session, packet, &requestpacket);
}
}
/* */
capwap_free_parsed_packet(&requestpacket);
capwap_packet_rxmng_free(rxmngrequestpacket);
}
} else {
log_printf(LOG_WARNING, "Receive IEEE802.11 WLAN Configuration Response with error: %d", (int)resultcode->code);
}
/* */
ac_free_reference_last_request(session);
}
/* */
static void execute_ieee80211_station_configuration_response_addstation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
struct ac_wlan* wlan;
struct ac_station* station;
struct capwap_addstation_element* addstation;
struct capwap_80211_station_element* station80211;
struct capwap_resultcode_element* resultcode;
/* */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_ADDSTATION);
/* */
if (GET_WBID_HEADER(packet->rxmngpacket->header) == CAPWAP_WIRELESS_BINDING_IEEE80211) {
station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_STATION);
if (station80211) {
wlan = ac_wlans_get_bssid_with_wlanid(session, station80211->radioid, station80211->wlanid);
if (wlan) {
station = ac_stations_get_station(session, station80211->radioid, wlan->address, addstation->address);
if (station) {
if (CAPWAP_RESULTCODE_OK(resultcode->code)) {
log_printf(LOG_INFO, "Authorized station: " MACSTR,
MAC2STR(station->address));
/* */
station->flags |= AC_STATION_FLAGS_AUTHORIZED;
capwap_timeout_deletetimer(session->timeout, station->idtimeout);
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
} else {
ac_stations_delete_station(session, station);
}
}
}
}
}
}
/* */
static void execute_ieee80211_station_configuration_response_deletestation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
struct ac_station* station;
struct capwap_resultcode_element* resultcode;
struct capwap_deletestation_element* deletestation;
/* */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
deletestation = (struct capwap_deletestation_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_DELETESTATION);
/* */
station = ac_stations_get_station(session, deletestation->radioid, NULL, deletestation->address);
if (station) {
log_printf(LOG_INFO, "Deauthorized station: " MACSTR " with %d result code",
MAC2STR(station->address), (int)resultcode->code);
/* */
ac_stations_delete_station(session, station);
}
}
/* */
static void receive_ieee80211_station_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_packet_rxmng* rxmngrequestpacket;
struct capwap_parsed_packet requestpacket;
/* Parsing request message */
rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket);
if (capwap_parsing_packet(rxmngrequestpacket, &requestpacket) == PARSING_COMPLETE) {
if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_ADDSTATION)) {
execute_ieee80211_station_configuration_response_addstation(session, packet, &requestpacket);
} else if (capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_DELETESTATION)) {
execute_ieee80211_station_configuration_response_deletestation(session, packet, &requestpacket);
}
}
/* */
capwap_free_parsed_packet(&requestpacket);
capwap_packet_rxmng_free(rxmngrequestpacket);
ac_free_reference_last_request(session);
}
/* */
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet != NULL);
if (capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type) || (session->localseqnumber == packet->rxmngpacket->ctrlmsg.seq)) {
/* Update sequence number */
if (!capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type)) {
session->localseqnumber++;
}
/* Parsing message */
switch (packet->rxmngpacket->ctrlmsg.type) {
case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_ECHO_REQUEST: {
#ifdef DEBUG
{
char sessionname[33];
capwap_sessionid_printf(&session->sessionid, sessionname);
log_printf(LOG_DEBUG, "Receive Echo Request from %s", sessionname);
}
#endif
if (!receive_echo_request(session, packet)) {
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
ac_session_teardown(session);
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_WTP_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
receive_ieee80211_station_configuration_response(session, packet);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
receive_ieee80211_wlan_configuration_response(session, packet);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
}
}
}

View File

@ -1,20 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "ac_session.h"
/* */
void ac_dfa_state_teardown(struct ac_session_t* session) {
ASSERT(session != NULL);
// Notify teardown session
if (session->wtpid) {
struct ac_soap_response* response = ac_soap_teardownwtpsession(session, session->wtpid);
if (response) {
ac_soapclient_free_response(response);
}
}
/* Defered free resource */
ac_dfa_change_state(session, CAPWAP_DEAD_STATE);
}

View File

@ -1,256 +0,0 @@
#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;
union sockaddr_capwap sender;
char data[0];
};
static struct ac_discovery_t g_ac_discovery;
/* */
void ac_discovery_add_packet(void* buffer, int buffersize, int sock, union sockaddr_capwap* 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(union sockaddr_capwap));
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_packet_txmng* ac_create_discovery_response(struct capwap_parsed_packet* packet) {
int i;
unsigned short binding;
struct capwap_list* controllist;
struct capwap_list_item* item;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
/* Check is valid binding */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (!ac_valid_binding(binding)) {
return NULL;
}
/* Update statistics */
ac_update_statistics();
/* Build packet */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_DISCOVERY_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_ac.mtu);
/* Prepare discovery response */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname);
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
for (i = 0; i < wtpradioinformation->count; i++) {
struct capwap_80211_wtpradioinformation_element* radio;
radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio);
}
}
/* 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.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_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element);
} else if (sessioncontrol->localaddress.ss.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_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element);
}
}
capwap_list_free(controllist);
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
return txmngpacket;
}
/* 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 ac_discovery_packet* acpacket;
struct capwap_parsed_packet packet;
struct capwap_packet_rxmng* rxmngpacket;
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;
}
/* */
acpacket = (struct ac_discovery_packet*)itempacket->item;
sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet);
/* Accept only discovery request don't fragment */
rxmngpacket = capwap_packet_rxmng_create_message();
if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, acpacket->data, sizedata) == CAPWAP_RECEIVE_COMPLETE_PACKET) {
/* Validate message */
if (capwap_check_message_type(rxmngpacket) == VALID_MESSAGE_TYPE) {
/* Parsing packet */
if (capwap_parsing_packet(rxmngpacket, &packet) == PARSING_COMPLETE) {
/* Validate packet */
if (!capwap_validate_parsed_packet(&packet, NULL)) {
struct capwap_packet_txmng* txmngpacket;
/* */
log_printf(LOG_DEBUG, "Receive discovery request packet");
/* Creare discovery response */
txmngpacket = ac_create_discovery_response(&packet);
if (txmngpacket) {
struct capwap_list* responsefragmentpacket;
/* Discovery response complete, get fragment packets */
responsefragmentpacket = capwap_list_create();
capwap_packet_txmng_get_fragment_packets(txmngpacket, responsefragmentpacket, g_ac_discovery.fragmentid);
if (responsefragmentpacket->count > 1) {
g_ac_discovery.fragmentid++;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Send discovery response to WTP */
if (!capwap_sendto_fragmentpacket(acpacket->sendsock, responsefragmentpacket, &acpacket->sender)) {
log_printf(LOG_DEBUG, "Warning: error to send discovery response packet");
}
/* Don't buffering a packets sent */
capwap_list_free(responsefragmentpacket);
}
}
}
/* Free resource */
capwap_free_parsed_packet(&packet);
}
}
/* Free resource */
capwap_packet_rxmng_free(rxmngpacket);
/* Free packet */
capwap_itemlist_free(itempacket);
}
}
/* */
static void* ac_discovery_thread(void* param) {
log_printf(LOG_DEBUG, "Discovery start");
ac_discovery_run();
log_printf(LOG_DEBUG, "Discovery stop");
/* Thread exit */
pthread_exit(NULL);
return NULL;
}
/* */
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) {
log_printf(LOG_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_destroy(&g_ac_discovery.packetslock);
capwap_list_free(g_ac_discovery.packets);
}

View File

@ -1,8 +0,0 @@
#ifndef __AC_DISCOVERY_HEADER__
#define __AC_DISCOVERY_HEADER__
int ac_discovery_start(void);
void ac_discovery_stop(void);
void ac_discovery_add_packet(void* buffer, int buffersize, int sock, union sockaddr_capwap* sender);
#endif /* __AC_DISCOVERY_HEADER__ */

View File

@ -1,950 +0,0 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "ac_session.h"
#include "ac_discovery.h"
#include "ac_backend.h"
#include "ac_wlans.h"
#include <signal.h>
#define MAX_MTU 9000
#define MIN_MTU 500
#define AC_RECV_NOERROR_MSGQUEUE -1001
#define AC_RECV_NOERROR_KMODEVENT -1002
#define AC_RECV_NOERROR_BACKENDNOCONNECT -1003
#define AC_IFACE_MAX_INDEX 256
#define AC_IFACE_NAME "capwap%lu"
/* */
static void ac_close_sessions(void);
/* */
static int ac_update_configuration_create_datachannelinterfaces(struct ac_if_datachannel* datachannel) {
/* Create virtual interface */
sprintf(datachannel->ifname, AC_IFACE_NAME, datachannel->index);
datachannel->ifindex = ac_kmod_create_iface(datachannel->ifname, datachannel->mtu);
if (datachannel->ifindex < 0) {
return datachannel->ifindex;
}
/* TODO manage bridge */
return 0;
}
/* */
static int ac_update_configuration_getdatachannel_params(struct json_object* jsonvalue, int* mtu, const char** bridge) {
int result = -1;
struct json_object* jsonmtu;
/* */
jsonmtu = compat_json_object_object_get(jsonvalue, "MTU");
if (jsonmtu && (json_object_get_type(jsonmtu) == json_type_int)) {
*mtu = json_object_get_int(jsonmtu);
if ((*mtu >= MIN_MTU) && (*mtu <= MAX_MTU)) {
struct json_object* jsonbridge = compat_json_object_object_get(jsonvalue, "Bridge");
*bridge = ((jsonbridge && (json_object_get_type(jsonmtu) == json_type_string)) ? json_object_get_string(jsonbridge) : NULL);
result = 0;
}
}
return result;
}
/* */
static int ac_update_configuration_datachannelinterfaces(void* data, void* param) {
int i;
int mtu;
int length;
const char* bridge;
struct ac_if_datachannel* iface = (struct ac_if_datachannel*)data;
struct array_list* interfaces = (struct array_list*)param;
/* Search interface */
length = array_list_length(interfaces);
for (i = 0; i < length; i++) {
struct json_object* jsonvalue = array_list_get_idx(interfaces, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonindex = compat_json_object_object_get(jsonvalue, "Index");
if (jsonindex && (json_object_get_type(jsonindex) == json_type_int)) {
if (iface->index == (unsigned long)json_object_get_int(jsonindex)) {
if (!ac_update_configuration_getdatachannel_params(jsonvalue, &mtu, &bridge)) {
/* TODO update interface */
}
/* Interface found */
array_list_put_idx(interfaces, i, NULL);
break;
}
}
}
}
return ((i == length) ? HASH_DELETE_AND_CONTINUE : HASH_CONTINUE);
}
/* */
static void ac_update_configuration(struct json_object* jsonroot) {
int i;
int mtu;
int length;
const char* bridge;
struct json_object* jsonelement;
struct ac_if_datachannel* datachannel;
ASSERT(jsonroot != NULL);
/* Params
{
DataChannelInterfaces: [
{
Index: [int],
MTU: [int],
Bridge: [string]
}
]
}
*/
/* DataChannelInterfaces */
jsonelement = compat_json_object_object_get(jsonroot, "DataChannelInterfaces");
if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) {
struct array_list* interfaces = json_object_get_array(jsonelement);
capwap_rwlock_wrlock(&g_ac.ifdatachannellock);
/* Update and Remove active interfaces*/
capwap_hash_foreach(g_ac.ifdatachannel, ac_update_configuration_datachannelinterfaces, interfaces);
/* Add new interfaces*/
length = array_list_length(interfaces);
for (i = 0; i < length; i++) {
struct json_object* jsonvalue = array_list_get_idx(interfaces, i);
if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) {
struct json_object* jsonindex = compat_json_object_object_get(jsonvalue, "Index");
if (jsonindex && (json_object_get_type(jsonindex) == json_type_int)) {
int index = json_object_get_int(jsonindex);
if ((index >= 0) && (index < AC_IFACE_MAX_INDEX) && !ac_update_configuration_getdatachannel_params(jsonvalue, &mtu, &bridge)) {
datachannel = (struct ac_if_datachannel*)capwap_alloc(sizeof(struct ac_if_datachannel));
memset(datachannel, 0, sizeof(struct ac_if_datachannel));
/* */
datachannel->index = (unsigned long)index;
datachannel->mtu = mtu;
if (bridge && (strlen(bridge) < IFNAMSIZ)) {
strcpy(datachannel->bridge, bridge);
}
/* */
if (!ac_update_configuration_create_datachannelinterfaces(datachannel)) {
capwap_hash_add(g_ac.ifdatachannel, (void*)datachannel);
} else {
capwap_free(datachannel);
}
}
}
}
}
capwap_rwlock_unlock(&g_ac.ifdatachannellock);
}
}
/* */
static int ac_recvmsgqueue(int fd, struct ac_session_msgqueue_item_t* item) {
int packetsize = -1;
do {
packetsize = recv(fd, (void*)item, sizeof(struct ac_session_msgqueue_item_t), 0);
} while ((packetsize < 0) && ((errno == EAGAIN) || (errno == EINTR)));
return ((packetsize == sizeof(struct ac_session_msgqueue_item_t)) ? 1 : 0);
}
/* */
static void ac_session_msgqueue_parsing_item(struct ac_session_msgqueue_item_t* item) {
switch (item->message) {
case AC_MESSAGE_QUEUE_CLOSE_THREAD: {
struct capwap_list_item* search = g_ac.sessionsthread->first;
while (search != NULL) {
struct ac_session_thread_t* sessionthread = (struct ac_session_thread_t*)search->item;
ASSERT(sessionthread != NULL);
if (sessionthread->threadid == item->message_close_thread.threadid) {
void* dummy;
/* Clean thread resource */
pthread_join(sessionthread->threadid, &dummy);
capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessionsthread, search));
break;
}
/* */
search = search->next;
}
break;
}
case AC_MESSAGE_QUEUE_UPDATE_CONFIGURATION: {
ac_update_configuration(item->message_configuration.jsonroot);
/* Free JSON */
json_object_put(item->message_configuration.jsonroot);
break;
}
case AC_MESSAGE_QUEUE_CLOSE_ALLSESSIONS: {
ac_close_sessions(); /* Close all sessions */
break;
}
default: {
log_printf(LOG_DEBUG, "Unknown message queue item: %lu", item->message);
break;
}
}
}
/* */
static void ac_wait_terminate_allsessions(void) {
struct ac_session_msgqueue_item_t item;
/* Wait that list is empty */
while (g_ac.sessionsthread->count > 0) {
log_printf(LOG_DEBUG, "Waiting for %d session terminate", g_ac.sessionsthread->count);
/* Receive message queue packet */
if (!ac_recvmsgqueue(g_ac.fdmsgsessions[1], &item)) {
log_printf(LOG_DEBUG, "Unable to receive message queue");
break;
}
/* Parsing message queue packet */
if (item.message == AC_MESSAGE_QUEUE_CLOSE_THREAD) {
ac_session_msgqueue_parsing_item(&item);
}
}
log_printf(LOG_DEBUG, "Close all sessions");
}
/* Initialize message queue */
int ac_msgqueue_init(void) {
if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_ac.fdmsgsessions)) {
return 0;
}
return 1;
}
/* Free sessions message queue */
void ac_msgqueue_free(void) {
close(g_ac.fdmsgsessions[1]);
close(g_ac.fdmsgsessions[0]);
}
/* */
int ac_msgqueue_notify_closethread(pthread_t threadid) {
struct ac_session_msgqueue_item_t item;
/* Send message */
memset(&item, 0, sizeof(struct ac_session_msgqueue_item_t));
item.message = AC_MESSAGE_QUEUE_CLOSE_THREAD;
item.message_close_thread.threadid = threadid;
send(g_ac.fdmsgsessions[0], (void*)&item, sizeof(struct ac_session_msgqueue_item_t), 0);
return ((send(g_ac.fdmsgsessions[0], (void*)&item, sizeof(struct ac_session_msgqueue_item_t), 0) == sizeof(struct ac_session_msgqueue_item_t)) ? 0 : -1);
}
/* */
int ac_msgqueue_update_configuration(struct json_object* jsonroot) {
struct ac_session_msgqueue_item_t item;
ASSERT(jsonroot != NULL);
/* Send message */
memset(&item, 0, sizeof(struct ac_session_msgqueue_item_t));
item.message = AC_MESSAGE_QUEUE_UPDATE_CONFIGURATION;
item.message_configuration.jsonroot = jsonroot;
return ((send(g_ac.fdmsgsessions[0], (void*)&item, sizeof(struct ac_session_msgqueue_item_t), 0) == sizeof(struct ac_session_msgqueue_item_t)) ? 0 : -1);
}
/* */
int ac_msgqueue_close_allsessions(void) {
struct ac_session_msgqueue_item_t item;
/* Send message */
memset(&item, 0, sizeof(struct ac_session_msgqueue_item_t));
item.message = AC_MESSAGE_QUEUE_CLOSE_ALLSESSIONS;
return ((send(g_ac.fdmsgsessions[0], (void*)&item, sizeof(struct ac_session_msgqueue_item_t), 0) == sizeof(struct ac_session_msgqueue_item_t)) ? 0 : -1);
}
/* */
static int ac_recvfrom(struct ac_fds* fds, void* buffer, int* size, union sockaddr_capwap* fromaddr, union sockaddr_capwap* toaddr) {
int index;
ASSERT(fds);
ASSERT(fds->fdspoll != NULL);
ASSERT(fds->fdstotalcount > 0);
ASSERT(buffer != NULL);
ASSERT(size != NULL);
ASSERT(*size > 0);
ASSERT(fromaddr != NULL);
/* Wait packet */
index = capwap_wait_recvready(fds->fdspoll, fds->fdstotalcount, NULL);
if (index < 0) {
return index;
} else if ((fds->kmodeventsstartpos >= 0) && (index >= fds->kmodeventsstartpos)) {
int pos = index - fds->kmodeventsstartpos;
if (pos < fds->kmodeventscount) {
if (!fds->kmodevents[pos].event_handler) {
return CAPWAP_RECV_ERROR_SOCKET;
}
fds->kmodevents[pos].event_handler(fds->fdspoll[index].fd, fds->kmodevents[pos].params, fds->kmodevents[pos].paramscount);
}
return AC_RECV_NOERROR_KMODEVENT;
} else if ((fds->msgqueuestartpos >= 0) && (index >= fds->msgqueuestartpos)) {
struct ac_session_msgqueue_item_t item;
/* Receive message queue packet */
if (!ac_recvmsgqueue(fds->fdspoll[index].fd, &item)) {
return CAPWAP_RECV_ERROR_SOCKET;
}
/* Parsing message queue packet */
ac_session_msgqueue_parsing_item(&item);
return AC_RECV_NOERROR_MSGQUEUE;
} else if (!ac_backend_isconnect()) {
return AC_RECV_NOERROR_BACKENDNOCONNECT;
}
/* Receive packet */
if (capwap_recvfrom(fds->fdspoll[index].fd, buffer, size, fromaddr, toaddr)) {
return CAPWAP_RECV_ERROR_SOCKET;
}
return index;
}
/* Add packet to session */
static void ac_session_add_packet(struct ac_session_t* session, char* buffer, int size, 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->sessionlock);
capwap_itemlist_insert_after(session->packets, NULL, item);
capwap_event_signal(&session->waitpacket);
capwap_lock_exit(&session->sessionlock);
}
/* Add action to session */
void ac_session_send_action(struct ac_session_t* session, long action, long param, const void* data, long length) {
struct capwap_list_item* item;
struct ac_session_action* actionsession;
struct capwap_list_item* search;
ASSERT(session != NULL);
ASSERT(length >= 0);
/* */
item = capwap_itemlist_create(sizeof(struct ac_session_action) + length);
actionsession = (struct ac_session_action*)item->item;
actionsession->action = action;
actionsession->param = param;
actionsession->length = length;
if (length > 0) {
ASSERT(data != NULL);
memcpy(actionsession->data, data, length);
}
/* Validate session before use */
capwap_rwlock_rdlock(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
if (session == (struct ac_session_t*)search->item) {
/* Append to actions list */
capwap_lock_enter(&session->sessionlock);
capwap_itemlist_insert_after(session->action, NULL, item);
capwap_event_signal(&session->waitpacket);
capwap_lock_exit(&session->sessionlock);
break;
}
/* */
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
}
/* Find AC sessions */
static struct ac_session_t* ac_search_session_from_wtpaddress(union sockaddr_capwap* address) {
struct ac_session_t* result = NULL;
struct capwap_list_item* search;
ASSERT(address != NULL);
capwap_rwlock_rdlock(&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, &session->dtls.peeraddr)) {
/* Increment session count */
capwap_lock_enter(&session->sessionlock);
session->count++;
capwap_event_signal(&session->changereference);
capwap_lock_exit(&session->sessionlock);
/* */
result = session;
break;
}
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
return result;
}
/* Find session from wtp id */
struct ac_session_t* ac_search_session_from_wtpid(const char* wtpid) {
struct ac_session_t* result = NULL;
struct capwap_list_item* search;
ASSERT(wtpid != NULL);
capwap_rwlock_rdlock(&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 (session->wtpid && !strcmp(session->wtpid, wtpid)) {
/* Increment session count */
capwap_lock_enter(&session->sessionlock);
session->count++;
capwap_event_signal(&session->changereference);
capwap_lock_exit(&session->sessionlock);
/* */
result = session;
break;
}
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
return result;
}
/* Find session from wtp id */
struct ac_session_t* ac_search_session_from_sessionid(struct capwap_sessionid_element* sessionid) {
struct ac_session_t* result = NULL;
struct capwap_list_item* search;
ASSERT(sessionid != NULL);
capwap_rwlock_rdlock(&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))) {
/* Increment session count */
capwap_lock_enter(&session->sessionlock);
session->count++;
capwap_event_signal(&session->changereference);
capwap_lock_exit(&session->sessionlock);
/* */
result = session;
break;
}
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
return result;
}
/* */
int ac_has_sessionid(struct capwap_sessionid_element* sessionid) {
int result = 0;
struct capwap_list_item* search;
ASSERT(sessionid != NULL);
capwap_rwlock_rdlock(&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))) {
result = 1;
break;
}
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
return result;
}
/* */
int ac_has_wtpid(const char* wtpid) {
int result = 0;
struct capwap_list_item* search;
if (!wtpid || !wtpid[0]) {
return -1;
}
capwap_rwlock_rdlock(&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 (session->wtpid && !strcmp(session->wtpid, wtpid)) {
result = 1;
break;
}
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
return result;
}
/* */
char* ac_get_printable_wtpid(struct capwap_wtpboarddata_element* wtpboarddata) {
char* wtpid = NULL;
struct capwap_wtpboarddata_board_subelement* wtpboarddatamacaddress;
ASSERT(wtpboarddata != NULL);
/* TODO: build printable wtpid depending on the model device */
/* Get macaddress */
wtpboarddatamacaddress = capwap_wtpboarddata_get_subelement(wtpboarddata, CAPWAP_BOARD_SUBELEMENT_MACADDRESS);
if (wtpboarddatamacaddress != NULL) {
wtpid = capwap_alloc(((wtpboarddatamacaddress->length == MACADDRESS_EUI48_LENGTH) ? CAPWAP_MACADDRESS_EUI48_BUFFER : CAPWAP_MACADDRESS_EUI64_BUFFER));
capwap_printf_macaddress(wtpid, (unsigned char*)wtpboarddatamacaddress->data, wtpboarddatamacaddress->length);
}
return wtpid;
}
/* */
void ac_session_close(struct ac_session_t* session) {
capwap_lock_enter(&session->sessionlock);
session->running = 0;
capwap_event_signal(&session->waitpacket);
capwap_lock_exit(&session->sessionlock);
}
/* Close sessions */
static void ac_close_sessions(void) {
struct capwap_list_item* search;
capwap_rwlock_rdlock(&g_ac.sessionslock);
/* Session */
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
ac_session_close(session);
search = search->next;
}
capwap_rwlock_unlock(&g_ac.sessionslock);
}
/* Create new session */
static struct ac_session_t* ac_create_session(int sock, union sockaddr_capwap* fromaddr, union sockaddr_capwap* toaddr) {
int result;
struct capwap_list_item* itemlist;
struct ac_session_t* session;
ASSERT(sock >= 0);
ASSERT(fromaddr != NULL);
ASSERT(toaddr != 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->itemlist = itemlist;
session->running = 1;
/* */
capwap_crypt_setconnection(&session->dtls, sock, toaddr, fromaddr);
/* */
ac_wlans_init(session);
/* */
session->count = 2;
capwap_event_init(&session->changereference);
/* */
session->timeout = capwap_timeout_init();
session->idtimercontrol = capwap_timeout_createtimer(session->timeout);
session->idtimerkeepalivedead = capwap_timeout_createtimer(session->timeout);
/* Duplicate state for DFA */
memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
session->dfa.acipv4list.addresses = capwap_array_clone(g_ac.dfa.acipv4list.addresses);
if (!session->dfa.acipv4list.addresses->count && (session->dtls.localaddr.ss.ss_family == AF_INET)) {
memcpy(capwap_array_get_item_pointer(session->dfa.acipv4list.addresses, 0), &session->dtls.localaddr.sin.sin_addr, sizeof(struct in_addr));
}
session->dfa.acipv6list.addresses = capwap_array_clone(g_ac.dfa.acipv6list.addresses);
if (!session->dfa.acipv6list.addresses->count && (session->dtls.localaddr.ss.ss_family == AF_INET6)) {
memcpy(capwap_array_get_item_pointer(session->dfa.acipv6list.addresses, 0), &session->dtls.localaddr.sin6.sin6_addr, sizeof(struct in6_addr));
}
/* Init */
capwap_event_init(&session->waitpacket);
capwap_lock_init(&session->sessionlock);
session->action = capwap_list_create();
session->packets = capwap_list_create();
session->requestfragmentpacket = capwap_list_create();
session->responsefragmentpacket = capwap_list_create();
session->notifyevent = capwap_list_create();
session->mtu = g_ac.mtu;
session->state = CAPWAP_IDLE_STATE;
/* Update session list */
capwap_rwlock_wrlock(&g_ac.sessionslock);
capwap_itemlist_insert_after(g_ac.sessions, NULL, itemlist);
capwap_rwlock_unlock(&g_ac.sessionslock);
/* Create thread */
result = pthread_create(&session->threadid, NULL, ac_session_thread, (void*)session);
if (!result) {
struct ac_session_thread_t* sessionthread;
/* Keeps trace of active threads */
itemlist = capwap_itemlist_create(sizeof(struct ac_session_thread_t));
sessionthread = (struct ac_session_thread_t*)itemlist->item;
sessionthread->threadid = session->threadid;
/* */
capwap_itemlist_insert_after(g_ac.sessionsthread, NULL, itemlist);
} else {
log_printf(LOG_EMERG, "Unable create session thread, error code %d", result);
capwap_exit(CAPWAP_OUT_OF_MEMORY);
}
return session;
}
/* Release reference of session */
void ac_session_release_reference(struct ac_session_t* session) {
ASSERT(session != NULL);
capwap_lock_enter(&session->sessionlock);
ASSERT(session->count > 0);
session->count--;
capwap_event_signal(&session->changereference);
capwap_lock_exit(&session->sessionlock);
}
/* Update statistics */
void ac_update_statistics(void) {
g_ac.descriptor.stations = 0; /* TODO */
capwap_rwlock_rdlock(&g_ac.sessionslock);
g_ac.descriptor.activewtp = g_ac.sessions->count;
capwap_rwlock_unlock(&g_ac.sessionslock);
}
/* Handler signal */
static void ac_signal_handler(int signum) {
if ((signum == SIGINT) || (signum == SIGTERM)) {
g_ac.running = 0;
}
}
/* */
static int ac_execute_init_fdspool(struct ac_fds* fds, struct capwap_network* net, int fdmsgqueue) {
ASSERT(fds != NULL);
ASSERT(net != NULL);
ASSERT(fdmsgqueue > 0);
/* */
memset(fds, 0, sizeof(struct ac_fds));
fds->fdsnetworkcount = capwap_network_set_pollfd(net, NULL, 0);
fds->msgqueuecount = 1;
fds->fdspoll = (struct pollfd*)capwap_alloc(sizeof(struct pollfd) * (fds->fdsnetworkcount + fds->msgqueuecount));
/* Retrive all socket for polling */
fds->fdstotalcount = capwap_network_set_pollfd(net, fds->fdspoll, fds->fdsnetworkcount);
if (fds->fdsnetworkcount != fds->fdstotalcount) {
capwap_free(fds->fdspoll);
return -1;
}
/* Unix socket message queue */
fds->msgqueuestartpos = fds->fdsnetworkcount;
fds->fdspoll[fds->msgqueuestartpos].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
fds->fdspoll[fds->msgqueuestartpos].fd = fdmsgqueue;
fds->fdstotalcount += fds->msgqueuecount;
return ac_execute_update_fdspool(fds);
}
/* */
static void ac_execute_free_fdspool(struct ac_fds* fds) {
ASSERT(fds != NULL);
if (fds->fdspoll) {
capwap_free(fds->fdspoll);
}
if (fds->kmodevents) {
capwap_free(fds->kmodevents);
}
}
/* */
int ac_execute_update_fdspool(struct ac_fds* fds) {
int totalcount;
int kmodcount;
struct pollfd* fdsbuffer;
ASSERT(fds != NULL);
/* Retrieve number of Dynamic File Descriptor Event */
kmodcount = ac_kmod_getfd(NULL, NULL, 0);
if (kmodcount < 0) {
return -1;
}
/* Kernel Module Events Callback */
fds->kmodeventsstartpos = -1;
if (kmodcount != fds->kmodeventscount) {
if (fds->kmodevents) {
capwap_free(fds->kmodevents);
}
/* */
fds->kmodeventscount = kmodcount;
fds->kmodevents = (struct ac_kmod_event*)((kmodcount > 0) ? capwap_alloc(sizeof(struct ac_kmod_event) * kmodcount) : NULL);
}
/* Resize poll */
totalcount = fds->fdsnetworkcount + fds->msgqueuecount + fds->kmodeventscount;
if (fds->fdstotalcount != totalcount) {
fdsbuffer = (struct pollfd*)capwap_alloc(sizeof(struct pollfd) * totalcount);
if (fds->fdspoll) {
int count = fds->fdsnetworkcount + fds->msgqueuecount;
if (count > 0) {
memcpy(fdsbuffer, fds->fdspoll, sizeof(struct pollfd) * count);
}
capwap_free(fds->fdspoll);
}
/* */
fds->fdspoll = fdsbuffer;
fds->fdstotalcount = totalcount;
}
/* Retrieve File Descriptor Kernel Module Event */
if (fds->kmodeventscount > 0) {
fds->kmodeventsstartpos = fds->fdsnetworkcount + fds->msgqueuecount;
ac_kmod_getfd(&fds->fdspoll[fds->kmodeventsstartpos], fds->kmodevents, fds->kmodeventscount);
}
return fds->fdstotalcount;
}
/* AC running */
int ac_execute(void) {
int result = CAPWAP_SUCCESSFUL;
int index;
int check;
union sockaddr_capwap fromaddr;
union sockaddr_capwap toaddr;
struct ac_session_t* session;
char buffer[CAPWAP_MAX_PACKET_SIZE];
int buffersize;
struct ac_fds fds;
/* Set file descriptor pool */
if (ac_execute_init_fdspool(&fds, &g_ac.net, g_ac.fdmsgsessions[1]) <= 0) {
log_printf(LOG_DEBUG, "Unable to initialize file descriptor pool");
return AC_ERROR_SYSTEM_FAILER;
}
/* Handler signal */
g_ac.running = 1;
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, ac_signal_handler);
signal(SIGTERM, ac_signal_handler);
/* Start discovery thread */
if (!ac_discovery_start()) {
ac_execute_free_fdspool(&fds);
log_printf(LOG_DEBUG, "Unable to start discovery thread");
return AC_ERROR_SYSTEM_FAILER;
}
/* Enable Backend Management */
if (!ac_backend_start()) {
ac_execute_free_fdspool(&fds);
ac_discovery_stop();
log_printf(LOG_ERR, "Unable start backend management");
return AC_ERROR_SYSTEM_FAILER;
}
/* */
while (g_ac.running) {
/* Receive packet */
buffersize = sizeof(buffer);
index = ac_recvfrom(&fds, buffer, &buffersize, &fromaddr, &toaddr);
if (!g_ac.running) {
log_printf(LOG_DEBUG, "Closing AC");
break;
}
/* */
if (index >= 0) {
/* Search the AC session */
session = ac_search_session_from_wtpaddress(&fromaddr);
if (session) {
/* Add packet*/
ac_session_add_packet(session, buffer, buffersize, 0);
/* Release reference */
ac_session_release_reference(session);
} else {
unsigned short sessioncount;
/* TODO prevent dos attack add filtering ip for multiple error */
/* Get current session number */
capwap_rwlock_rdlock(&g_ac.sessionslock);
sessioncount = g_ac.sessions->count;
capwap_rwlock_unlock(&g_ac.sessionslock);
/* */
if (ac_backend_isconnect() && (sessioncount < g_ac.descriptor.maxwtp)) {
check = capwap_sanity_check(CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls);
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) {
ac_discovery_add_packet(buffer, buffersize, fds.fdspoll[index].fd, &fromaddr);
} else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) {
/* Create a new session */
session = ac_create_session(fds.fdspoll[index].fd, &fromaddr, &toaddr);
ac_session_add_packet(session, buffer, buffersize, 1);
/* Release reference */
ac_session_release_reference(session);
}
}
}
} else if (check == CAPWAP_DTLS_PACKET) {
/* Before create new session check if receive DTLS Client Hello */
if (capwap_crypt_has_dtls_clienthello(&((char*)buffer)[sizeof(struct capwap_dtls_header)], buffersize - sizeof(struct capwap_dtls_header))) {
/* Create a new session */
session = ac_create_session(fds.fdspoll[index].fd, &fromaddr, &toaddr);
ac_session_add_packet(session, buffer, buffersize, 0);
/* Release reference */
ac_session_release_reference(session);
}
}
}
}
} else if (index == CAPWAP_RECV_ERROR_SOCKET) {
break; /* Socket close */
}
}
/* Disable Backend Management */
ac_backend_stop();
/* Terminate discovery thread */
ac_discovery_stop();
/* Close all sessions */
ac_close_sessions();
/* Wait to terminate all sessions */
ac_wait_terminate_allsessions();
/* Close data channel interfaces */
capwap_hash_deleteall(g_ac.ifdatachannel);
/* Free Backend Management */
ac_backend_free();
/* Free file description pool */
ac_execute_free_fdspool(&fds);
return result;
}

View File

@ -1,476 +0,0 @@
#include "ac.h"
#include "ac_session.h"
#include "ac_wlans.h"
/* */
static void ac_ieee80211_mgmt_probe_request_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Accept probe request only if not sent by WTP */
if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH)) {
return;
}
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
struct ac_wlan* wlan;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->authetication.ie[0], ielength)) {
return;
}
/* */
if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && !memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_create_station(session, radioid, mgmt->bssid, mgmt->sa);
if (!station || !station->wlan) {
return;
}
/* */
log_printf(LOG_INFO, "Receive IEEE802.11 Authentication Request "
"from " MACSTR " station", MAC2STR(station->address));
/* A station is removed if the association does not complete within a given period of time */
station->timeoutaction = AC_STATION_TIMEOUT_ACTION_DEAUTHENTICATE;
station->idtimeout = capwap_timeout_set(session->timeout, station->idtimeout, AC_STATION_TIMEOUT_ASSOCIATION_COMPLETE, ac_stations_timeout, station, session);
/* */
wlan = station->wlan;
if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
uint16_t algorithm;
uint16_t transactionseqnumber;
uint16_t responsestatuscode;
uint8_t buffer[IEEE80211_MTU];
struct ieee80211_authentication_params ieee80211_params;
int responselength;
/* Parsing Information Elements */
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->authetication.ie[0], ielength)) {
log_printf(LOG_INFO, "Invalid IEEE802.11 Authentication Request "
"from " MACSTR " station", MAC2STR(station->address));
return;
}
/* */
algorithm = __le16_to_cpu(mgmt->authetication.algorithm);
transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber);
/* */
responsestatuscode = IEEE80211_STATUS_NOT_SUPPORTED_AUTHENTICATION_ALGORITHM;
if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (wlan->authmode == CAPWAP_ADD_WLAN_AUTHTYPE_OPEN)) {
if (transactionseqnumber == 1) {
responsestatuscode = IEEE80211_STATUS_SUCCESS;
station->authalgorithm = IEEE80211_AUTHENTICATION_ALGORITHM_OPEN;
} else {
responsestatuscode = IEEE80211_STATUS_UNKNOWN_AUTHENTICATION_TRANSACTION;
}
} else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY) && (wlan->authmode == CAPWAP_ADD_WLAN_AUTHTYPE_WEP)) {
/* TODO */
}
/* Create authentication packet */
memset(&ieee80211_params, 0, sizeof(struct ieee80211_authentication_params));
memcpy(ieee80211_params.bssid, wlan->address, MACADDRESS_EUI48_LENGTH);
memcpy(ieee80211_params.station, mgmt->sa, MACADDRESS_EUI48_LENGTH);
ieee80211_params.algorithm = algorithm;
ieee80211_params.transactionseqnumber = transactionseqnumber + 1;
ieee80211_params.statuscode = responsestatuscode;
responselength = ieee80211_create_authentication_response(buffer, sizeof(buffer), &ieee80211_params);
if (responselength > 0) {
/* Send authentication response */
if (!ac_kmod_send_data(&session->sessionid, wlan->device->radioid, session->binding, buffer, responselength)) {
log_printf(LOG_INFO, "Sent IEEE802.11 Authentication Response "
"to " MACSTR " station with %d status code",
MAC2STR(station->address), (int)responsestatuscode);
station->flags |= AC_STATION_FLAGS_AUTHENTICATED;
} else {
log_printf(LOG_WARNING, "Unable to send IEEE802.11 Authentication Response "
"to " MACSTR " station", MAC2STR(station->address));
ac_stations_delete_station(session, station);
}
} else {
log_printf(LOG_WARNING, "Unable to create IEEE802.11 Authentication Response "
"to " MACSTR " station", MAC2STR(station->address));
ac_stations_delete_station(session, station);
}
}
} else if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(session, radioid, mgmt->bssid, mgmt->da);
if (station && station->wlan && (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) {
uint16_t algorithm;
uint16_t transactionseqnumber;
uint16_t statuscode;
/* */
statuscode = __le16_to_cpu(mgmt->authetication.statuscode);
/* */
log_printf(LOG_INFO, "Receive IEEE802.11 Authentication Response "
"to " MACSTR " station with %d status code",
MAC2STR(station->address), (int)statuscode);
if (statuscode == IEEE80211_STATUS_SUCCESS) {
algorithm = __le16_to_cpu(mgmt->authetication.algorithm);
transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber);
/* Check if authenticate */
if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (transactionseqnumber == 2)) {
station->flags |= AC_STATION_FLAGS_AUTHENTICATED;
} else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY) && (transactionseqnumber == 4)) {
/* TODO */
}
}
}
}
}
/* */
static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
struct ac_wlan* wlan;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->associationrequest.ie[0], ielength)) {
return;
}
/* Get station */
if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && !memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(session, radioid, mgmt->bssid, mgmt->sa);
if (!station || !station->wlan) {
return;
}
/* */
log_printf(LOG_INFO, "Receive IEEE802.11 Association Request "
"from " MACSTR " station", MAC2STR(station->address));
/* */
wlan = station->wlan;
if (!(station->flags & AC_STATION_FLAGS_AUTHENTICATED)) {
/* Invalid station, delete station */
log_printf(LOG_INFO, "Receive IEEE802.11 Association Request "
"from " MACSTR " unauthorized station", MAC2STR(station->address));
ac_stations_delete_station(session, station);
return;
}
/* Get Station Info */
station->capability = __le16_to_cpu(mgmt->associationrequest.capability);
station->listeninterval = __le16_to_cpu(mgmt->associationrequest.listeninterval);
/* Get supported rates */
if (ieitems.supported_rates && ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) <= sizeof(station->supportedrates))) {
station->supportedratescount = ieitems.supported_rates->len;
memcpy(station->supportedrates, ieitems.supported_rates->rates, ieitems.supported_rates->len);
if (ieitems.extended_supported_rates) {
station->supportedratescount += ieitems.extended_supported_rates->len;
memcpy(&station->supportedrates[ieitems.supported_rates->len], ieitems.extended_supported_rates->rates, ieitems.extended_supported_rates->len);
}
/* */
if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
int responselength;
struct ieee80211_ie_items ieitems;
struct ieee80211_associationresponse_params ieee80211_params;
uint16_t resultstatuscode;
uint8_t buffer[IEEE80211_MTU];
/* Parsing Information Elements */
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->associationrequest.ie[0], ielength)) {
log_printf(LOG_INFO, "Invalid IEEE802.11 Association Request "
"from " MACSTR " station", MAC2STR(station->address));
ac_stations_delete_station(session, station);
return;
}
/* Verify SSID */
if (ieee80211_is_valid_ssid(wlan->ssid, ieitems.ssid, NULL) != IEEE80211_VALID_SSID) {
resultstatuscode = IEEE80211_STATUS_UNSPECIFIED_FAILURE;
} else {
/* Check supported rates */
if (!ieitems.supported_rates || ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) > sizeof(station->supportedrates))) {
resultstatuscode = IEEE80211_STATUS_UNSPECIFIED_FAILURE;
} else {
station->capability = __le16_to_cpu(mgmt->associationrequest.capability);
station->listeninterval = __le16_to_cpu(mgmt->associationrequest.listeninterval);
if (ieee80211_aid_create(wlan->aidbitfield, &station->aid)) {
resultstatuscode = IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
} else {
/* Get supported rates */
station->supportedratescount = ieitems.supported_rates->len;
memcpy(station->supportedrates, ieitems.supported_rates->rates, ieitems.supported_rates->len);
if (ieitems.extended_supported_rates) {
station->supportedratescount += ieitems.extended_supported_rates->len;
memcpy(&station->supportedrates[ieitems.supported_rates->len], ieitems.extended_supported_rates->rates, ieitems.extended_supported_rates->len);
}
/* */
resultstatuscode = IEEE80211_STATUS_SUCCESS;
}
}
}
/* Create association response packet */
memset(&ieee80211_params, 0, sizeof(struct ieee80211_authentication_params));
memcpy(ieee80211_params.bssid, wlan->address, ETH_ALEN);
memcpy(ieee80211_params.station, mgmt->sa, ETH_ALEN);
ieee80211_params.capability = wlan->capability;
ieee80211_params.statuscode = resultstatuscode;
ieee80211_params.aid = IEEE80211_AID_FIELD | station->aid;
memcpy(ieee80211_params.supportedrates, wlan->device->supportedrates, wlan->device->supportedratescount);
ieee80211_params.supportedratescount = wlan->device->supportedratescount;
responselength = ieee80211_create_associationresponse_response(buffer, sizeof(buffer), &ieee80211_params);
if (responselength > 0) {
/* Send association response */
if (!ac_kmod_send_data(&session->sessionid, wlan->device->radioid, session->binding, buffer, responselength)) {
log_printf(LOG_INFO, "Sent IEEE802.11 Association Response "
"to " MACSTR " station with %d status code",
MAC2STR(station->address), (int)resultstatuscode);
/* Active Station */
station->flags |= AC_STATION_FLAGS_ASSOCIATE;
ac_stations_authorize_station(session, station);
} else {
log_printf(LOG_WARNING, "Unable to send IEEE802.11 Association Response "
"to " MACSTR " station", MAC2STR(station->address));
ac_stations_delete_station(session, station);
}
} else {
log_printf(LOG_WARNING, "Unable to create IEEE802.11 Association Response "
"to " MACSTR " station", MAC2STR(station->address));
ac_stations_delete_station(session, station);
}
}
}
}
}
/* */
static void ac_ieee80211_mgmt_association_response_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationresponse));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->associationresponse.ie[0], ielength)) {
return;
}
/* Get station */
if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(session, radioid, mgmt->bssid, mgmt->da);
if (station && station->wlan && (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) {
log_printf(LOG_INFO, "Receive IEEE802.11 Association Response "
"to " MACSTR " station with %d status code",
MAC2STR(station->address), (int)mgmt->associationresponse.statuscode);
if (mgmt->associationresponse.statuscode == IEEE80211_STATUS_SUCCESS) {
/* Get Station Info */
station->capability = __le16_to_cpu(mgmt->associationresponse.capability);
station->aid = __le16_to_cpu(mgmt->associationresponse.aid);
station->flags |= AC_STATION_FLAGS_ASSOCIATE;
/* Get supported rates */
if (ieitems.supported_rates && ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) <= sizeof(station->supportedrates))) {
station->supportedratescount = ieitems.supported_rates->len;
memcpy(station->supportedrates, ieitems.supported_rates->rates, ieitems.supported_rates->len);
if (ieitems.extended_supported_rates) {
station->supportedratescount += ieitems.extended_supported_rates->len;
memcpy(&station->supportedrates[ieitems.supported_rates->len], ieitems.extended_supported_rates->rates, ieitems.extended_supported_rates->len);
}
/* Active Station */
ac_stations_authorize_station(session, station);
}
}
}
}
}
/* */
static void ac_ieee80211_mgmt_reassociation_request_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationrequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->reassociationrequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_reassociation_response_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationresponse));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->reassociationresponse.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_disassociation_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->disassociation.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
const uint8_t* stationaddress;
struct ac_station* station;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->deauthetication.ie[0], ielength)) {
return;
}
/* Get station address */
stationaddress = (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) ? mgmt->sa : mgmt->da);
/* Delete station */
station = ac_stations_get_station(session, radioid, NULL, stationaddress);
if (station) {
/* Delete station without forward another IEEE802.11 deauthentication message */
station->flags &= ~(AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE);
ac_stations_delete_station(session, station);
}
}
/* */
static void ac_ieee80211_mgmt_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, uint16_t framecontrol_subtype) {
switch (framecontrol_subtype) {
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest))) {
ac_ieee80211_mgmt_probe_request_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication))) {
ac_ieee80211_mgmt_authentication_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest))) {
ac_ieee80211_mgmt_association_request_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->associationresponse))) {
ac_ieee80211_mgmt_association_response_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationrequest))) {
ac_ieee80211_mgmt_reassociation_request_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_RESPONSE: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationresponse))) {
ac_ieee80211_mgmt_reassociation_response_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation))) {
ac_ieee80211_mgmt_disassociation_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication))) {
ac_ieee80211_mgmt_deauthentication_packet(session, radioid, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION: {
break;
}
}
}
/* */
void ac_ieee80211_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header* header, int length) {
uint16_t framecontrol;
uint16_t framecontrol_type;
uint16_t framecontrol_subtype;
ASSERT(session != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(header != NULL);
ASSERT(length >= sizeof(struct ieee80211_header));
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
framecontrol_subtype = IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol);
/* Parsing frame */
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
ac_ieee80211_mgmt_packet(session, radioid, (const struct ieee80211_header_mgmt*)header, length, framecontrol_subtype);
}
}

View File

@ -1,94 +0,0 @@
#ifndef __AC_JSON_HEADER__
#define __AC_JSON_HEADER__
#include "capwap_array.h"
#include <json-c/json.h>
#define IEEE80211_BINDING_JSON_ROOT "WTPRadio"
struct ac_json_ieee80211_item {
int valid;
struct capwap_80211_addwlan_element* addwlan;
struct capwap_80211_antenna_element* antenna;
struct capwap_80211_assignbssid_element* assignbssid;
struct capwap_80211_deletewlan_element* deletewlan;
struct capwap_80211_directsequencecontrol_element* directsequencecontrol;
struct capwap_array* iearray;
struct capwap_80211_macoperation_element* macoperation;
struct capwap_80211_miccountermeasures_element* miccountermeasures;
struct capwap_80211_multidomaincapability_element* multidomaincapability;
struct capwap_80211_ofdmcontrol_element* ofdmcontrol;
struct capwap_80211_rateset_element* rateset;
struct capwap_80211_rsnaerrorreport_element* rsnaerrorreport;
struct capwap_80211_statistics_element* statistics;
struct capwap_80211_supportedrates_element* supportedrates;
struct capwap_80211_txpower_element* txpower;
struct capwap_80211_txpowerlevel_element* txpowerlevel;
struct capwap_80211_updatewlan_element* updatewlan;
struct capwap_80211_wtpqos_element* wtpqos;
struct capwap_80211_wtpradioconf_element* wtpradioconf;
struct capwap_80211_wtpradiofailalarm_element* wtpradiofailalarm;
struct capwap_80211_wtpradioinformation_element* wtpradioinformation;
};
struct ac_json_ieee80211_wtpradio {
struct ac_json_ieee80211_item items[RADIOID_MAX_COUNT];
};
/* JSON IEEE 802.11 message elements */
#include "ac_80211_json_addwlan.h"
#include "ac_80211_json_antenna.h"
#include "ac_80211_json_assignbssid.h"
#include "ac_80211_json_deletewlan.h"
#include "ac_80211_json_directsequencecontrol.h"
#include "ac_80211_json_ie.h"
#include "ac_80211_json_macoperation.h"
#include "ac_80211_json_miccountermeasures.h"
#include "ac_80211_json_multidomaincapability.h"
#include "ac_80211_json_ofdmcontrol.h"
#include "ac_80211_json_rateset.h"
#include "ac_80211_json_rsnaerrorreport.h"
#include "ac_80211_json_statistics.h"
#include "ac_80211_json_supportedrates.h"
#include "ac_80211_json_txpower.h"
#include "ac_80211_json_txpowerlevel.h"
#include "ac_80211_json_updatewlan.h"
#include "ac_80211_json_wtpqos.h"
#include "ac_80211_json_wtpradioconf.h"
#include "ac_80211_json_wtpradiofailalarm.h"
#include "ac_80211_json_wtpradioinformation.h"
/* */
struct ac_json_ieee80211_ops {
/* Message Element Type */
struct capwap_message_element_id type;
/* Message Element JSON Type */
char* json_type;
/* Build message element */
void* (*create)(struct json_object* jsonparent, uint16_t radioid);
int (*add_message_element)(struct ac_json_ieee80211_wtpradio* wtpradio, void* data, int overwrite);
/* Build JSON */
void (*create_json)(struct json_object* jsonparent, void* data);
};
/* */
void ac_json_ieee80211_init(struct ac_json_ieee80211_wtpradio* wtpradio);
void ac_json_ieee80211_free(struct ac_json_ieee80211_wtpradio* wtpradio);
/* */
int ac_json_ieee80211_addmessageelement(struct ac_json_ieee80211_wtpradio *wtpradio,
const struct capwap_message_element_id id,
void *data, int overwrite);
int ac_json_ieee80211_parsingmessageelement(struct ac_json_ieee80211_wtpradio* wtpradio, struct capwap_message_element_itemlist* messageelement);
int ac_json_ieee80211_parsingjson(struct ac_json_ieee80211_wtpradio* wtpradio, struct json_object* jsonroot);
/* */
struct json_object* ac_json_ieee80211_getjson(struct ac_json_ieee80211_wtpradio* wtpradio);
void ac_json_ieee80211_buildpacket(struct ac_json_ieee80211_wtpradio* wtpradio, struct capwap_packet_txmng* txmngpacket);
#endif /* __AC_JSON_HEADER__ */

View File

@ -1,703 +0,0 @@
#include "ac.h"
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include "ac_session.h"
#include "nlsmartcapwap.h"
/* Compatibility functions */
#ifdef HAVE_LIBNL_10
static uint32_t g_portbitmap[32] = { 0 };
static struct nl_sock* nl_socket_alloc_cb(void* cb) {
int i;
struct nl_sock* handle;
uint32_t pid = getpid() & 0x3FFFFF;
handle = nl_handle_alloc_cb(cb);
for (i = 0; i < 1024; i++) {
if (g_portbitmap[i / 32] & (1 << (i % 32))) {
continue;
}
g_portbitmap[i / 32] |= 1 << (i % 32);
pid += i << 22;
break;
}
nl_socket_set_local_port(handle, pid);
return handle;
}
static void nl_socket_free(struct nl_sock* handle) {
uint32_t port = nl_socket_get_local_port(handle);
port >>= 22;
g_portbitmap[port / 32] &= ~(1 << (port % 32));
nl_handle_destroy(handle);
}
#endif
/* */
typedef int (*ac_kmod_valid_cb)(struct nl_msg* msg, void* data);
/* */
static struct nl_sock* nl_create_handle(struct nl_cb* cb) {
struct nl_sock* handle;
handle = nl_socket_alloc_cb(cb);
if (!handle) {
return NULL;
}
if (genl_connect(handle)) {
nl_socket_free(handle);
return NULL;
}
return handle;
}
/* */
static int ac_kmod_no_seq_check(struct nl_msg* msg, void* arg) {
return NL_OK;
}
/* */
static int ac_kmod_error_handler(struct sockaddr_nl* nla, struct nlmsgerr* err, void* arg) {
*((int*)arg) = err->error;
return NL_STOP;
}
/* */
static int ac_kmod_finish_handler(struct nl_msg* msg, void* arg) {
*((int*)arg) = 0;
return NL_SKIP;
}
/* */
static int ac_kmod_ack_handler(struct nl_msg* msg, void* arg) {
*((int*)arg) = 0;
return NL_STOP;
}
/* */
static int ac_kmod_event_handler(struct genlmsghdr* gnlh, struct nlattr** tb_msg, void* data) {
switch (gnlh->cmd) {
case NLSMARTCAPWAP_CMD_RECV_KEEPALIVE: {
if (tb_msg[NLSMARTCAPWAP_ATTR_SESSION_ID]) {
struct capwap_sessionid_element* sessionid = (struct capwap_sessionid_element*)nla_data(tb_msg[NLSMARTCAPWAP_ATTR_SESSION_ID]);
struct ac_session_t* session = ac_search_session_from_sessionid(sessionid);
if (session) {
ac_kmod_send_keepalive(sessionid);
ac_session_send_action(session, AC_SESSION_ACTION_RECV_KEEPALIVE, 0, NULL, 0);
ac_session_release_reference(session);
}
}
break;
}
case NLSMARTCAPWAP_CMD_RECV_DATA: {
if (tb_msg[NLSMARTCAPWAP_ATTR_SESSION_ID] && tb_msg[NLSMARTCAPWAP_ATTR_DATA_FRAME]) {
struct ac_session_t* session = ac_search_session_from_sessionid((struct capwap_sessionid_element*)nla_data(tb_msg[NLSMARTCAPWAP_ATTR_SESSION_ID]));
if (session) {
ac_session_send_action(session, AC_SESSION_ACTION_RECV_IEEE80211_MGMT_PACKET, 0, nla_data(tb_msg[NLSMARTCAPWAP_ATTR_DATA_FRAME]), nla_len(tb_msg[NLSMARTCAPWAP_ATTR_DATA_FRAME]));
ac_session_release_reference(session);
}
}
break;
}
}
return NL_SKIP;
}
/* */
static int ac_kmod_valid_handler(struct nl_msg* msg, void* data) {
struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1];
struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg));
nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
return ac_kmod_event_handler(gnlh, tb_msg, data);
}
/* */
static int ac_kmod_send_and_recv(struct nl_sock* nl, struct nl_cb* nl_cb, struct nl_msg* msg, ac_kmod_valid_cb valid_cb, void* data) {
int result;
struct nl_cb* cb;
/* Clone netlink callback */
cb = nl_cb_clone(nl_cb);
if (!cb) {
return -1;
}
/* */
capwap_lock_enter(&g_ac.kmodhandle.msglock);
/* Complete send message */
result = nl_send_auto_complete(nl, msg);
if (result >= 0) {
/* Customize message callback */
nl_cb_err(cb, NL_CB_CUSTOM, ac_kmod_error_handler, &result);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, ac_kmod_finish_handler, &result);
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ac_kmod_ack_handler, &result);
if (valid_cb) {
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_cb, data);
}
result = 1;
while (result > 0) {
nl_recvmsgs(nl, cb);
}
}
/* */
capwap_lock_exit(&g_ac.kmodhandle.msglock);
nl_cb_put(cb);
return result;
}
/* */
static int ac_kmod_send_and_recv_msg(struct nl_msg* msg, ac_kmod_valid_cb valid_cb, void* data) {
return ac_kmod_send_and_recv(g_ac.kmodhandle.nlmsg, g_ac.kmodhandle.nlmsg_cb, msg, valid_cb, data);
}
/* */
static int ac_kmod_link(void) {
int result;
struct nl_msg* msg;
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_LINK, 0);
/* */
result = ac_kmod_send_and_recv(g_ac.kmodhandle.nl, g_ac.kmodhandle.nl_cb, msg, NULL, NULL);
if (result) {
if (result == -EALREADY) {
result = 0;
} else {
log_printf(LOG_WARNING, "Unable to connect kernel module, error code: %d", result);
}
}
/* */
nlmsg_free(msg);
return result;
}
/* */
static void ac_kmod_event_receive(int fd, void** params, int paramscount) {
int res;
ASSERT(fd >= 0);
ASSERT(params != NULL);
ASSERT(paramscount == 2);
/* */
res = nl_recvmsgs((struct nl_sock*)params[0], (struct nl_cb*)params[1]);
if (res) {
log_printf(LOG_WARNING, "Receive kernel module message failed: %d", res);
}
}
/* */
int ac_kmod_send_keepalive(struct capwap_sessionid_element* sessionid) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_SEND_KEEPALIVE, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
/* */
log_printf(LOG_DEBUG, "Prepare to send keep-alive");
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to send keep-alive: %d", result);
}
log_printf(LOG_DEBUG, "Sent keep-alive");
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_send_data(struct capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t binding, const uint8_t* data, int length) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
ASSERT(data != NULL);
ASSERT(length > 0);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_SEND_DATA, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_BINDING, binding);
nla_put(msg, NLSMARTCAPWAP_ATTR_DATA_FRAME, length, data);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to send data: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_isconnected(void) {
return (g_ac.kmodhandle.nlsmartcapwap_id ? 1 : 0);
}
/* */
int ac_kmod_getfd(struct pollfd* fds, struct ac_kmod_event* events, int count) {
int kmodcount = (ac_kmod_isconnected() ? 1 : 0);
/* */
if (!kmodcount) {
return 0;
} else if (!fds && !events && !count) {
return kmodcount;
} else if ((count > 0) && (!fds || !events)) {
return -1;
} else if (count < kmodcount) {
return -1;
}
/* */
fds[0].fd = g_ac.kmodhandle.nl_fd;
fds[0].events = POLLIN | POLLERR | POLLHUP;
/* */
events[0].event_handler = ac_kmod_event_receive;
events[0].params[0] = (void*)g_ac.kmodhandle.nl;
events[0].params[1] = (void*)g_ac.kmodhandle.nl_cb;
events[0].paramscount = 2;
return kmodcount;
}
/* */
int ac_kmod_createdatachannel(int family, unsigned short port) {
int result;
struct nl_msg* msg;
struct sockaddr_storage sockaddr;
ASSERT((family == AF_INET) || (family == AF_INET6));
ASSERT(port != 0);
/* */
memset(&sockaddr, 0, sizeof(struct sockaddr_storage));
sockaddr.ss_family = family;
if (sockaddr.ss_family == AF_INET) {
((struct sockaddr_in*)&sockaddr)->sin_port = htons(port);
} else if (sockaddr.ss_family == AF_INET6) {
((struct sockaddr_in6*)&sockaddr)->sin6_port = htons(port);
}
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_BIND, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_ADDRESS, sizeof(struct sockaddr_storage), &sockaddr);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to bind kernel socket: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_new_datasession(struct capwap_sessionid_element* sessionid, uint8_t binding, uint16_t mtu) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_NEW_SESSION, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_BINDING, binding);
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_MTU, mtu);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to create data session: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_delete_datasession(struct capwap_sessionid_element* sessionid) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_DELETE_SESSION, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result && (result != ENOENT)) {
log_printf(LOG_ERR, "Unable to delete data session: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_addwlan(struct capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, uint8_t macmode, uint8_t tunnelmode) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
ASSERT(bssid != NULL);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_ADD_WLAN, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_WLANID, wlanid);
nla_put(msg, NLSMARTCAPWAP_ATTR_MACADDRESS, MACADDRESS_EUI48_LENGTH, bssid);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_MACMODE, macmode);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_TUNNELMODE, tunnelmode);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to add wlan: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_removewlan(struct capwap_sessionid_element* sessionid) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_REMOVE_WLAN, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result && (result != ENOENT)) {
log_printf(LOG_ERR, "Unable to remove wlan: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
static int cb_kmod_create_iface(struct nl_msg* msg, void* data) {
struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1];
struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg));
uint32_t* ifindex = (uint32_t*)data;
nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
if (tb_msg[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]) {
*ifindex = nla_get_u32(tb_msg[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]);
}
return NL_SKIP;
}
/* */
int ac_kmod_create_iface(const char* ifname, uint16_t mtu) {
int result;
struct nl_msg* msg;
uint32_t ifindex = 0;
ASSERT(ifname != NULL);
ASSERT(mtu > 0);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_ADD_IFACE, 0);
nla_put_string(msg, NLSMARTCAPWAP_ATTR_IFPHY_NAME, ifname);
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_MTU, mtu);
/* */
result = ac_kmod_send_and_recv_msg(msg, cb_kmod_create_iface, &ifindex);
if (!result) {
result = (ifindex ? (int)ifindex : -1);
} else {
log_printf(LOG_ERR, "Unable to create data session: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_delete_iface(int ifindex) {
int result;
struct nl_msg* msg;
ASSERT(ifindex > 0);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_DELETE_IFACE, 0);
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFPHY_INDEX, (uint32_t)ifindex);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result && (result != ENOENT)) {
log_printf(LOG_ERR, "Unable to delete interface: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_authorize_station(struct capwap_sessionid_element* sessionid, const uint8_t* macaddress, int ifindex, uint8_t radioid, uint8_t wlanid, uint16_t vlan) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
ASSERT(macaddress != NULL);
ASSERT(ifindex >= 0);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(vlan < VLAN_MAX);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_AUTH_STATION, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
nla_put(msg, NLSMARTCAPWAP_ATTR_MACADDRESS, MACADDRESS_EUI48_LENGTH, macaddress);
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFPHY_INDEX, (unsigned long)ifindex);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
nla_put_u8(msg, NLSMARTCAPWAP_ATTR_WLANID, wlanid);
if (vlan > 0) {
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_VLAN, ifindex);
}
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to authorize station: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_deauthorize_station(struct capwap_sessionid_element* sessionid, const uint8_t* macaddress) {
int result;
struct nl_msg* msg;
ASSERT(sessionid != NULL);
ASSERT(macaddress != NULL);
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_DEAUTH_STATION, 0);
nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
nla_put(msg, NLSMARTCAPWAP_ATTR_MACADDRESS, MACADDRESS_EUI48_LENGTH, macaddress);
/* */
result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
if (result) {
log_printf(LOG_ERR, "Unable to deauthorize station: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int ac_kmod_init(void) {
int result;
/* */
capwap_lock_init(&g_ac.kmodhandle.msglock);
/* Configure netlink callback */
g_ac.kmodhandle.nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!g_ac.kmodhandle.nl_cb) {
ac_kmod_free();
return -1;
}
/* Create netlink socket */
g_ac.kmodhandle.nl = nl_create_handle(g_ac.kmodhandle.nl_cb);
if (!g_ac.kmodhandle.nl) {
ac_kmod_free();
return -1;
}
g_ac.kmodhandle.nl_fd = nl_socket_get_fd(g_ac.kmodhandle.nl);
/* Get nlsmartcapwap netlink family */
g_ac.kmodhandle.nlsmartcapwap_id = genl_ctrl_resolve(g_ac.kmodhandle.nl, NLSMARTCAPWAP_GENL_NAME);
if (g_ac.kmodhandle.nlsmartcapwap_id < 0) {
log_printf(LOG_WARNING, "Unable to found kernel module");
ac_kmod_free();
return -1;
}
/* Configure callback function */
nl_cb_set(g_ac.kmodhandle.nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, ac_kmod_no_seq_check, NULL);
nl_cb_set(g_ac.kmodhandle.nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ac_kmod_valid_handler, NULL);
/* Link to kernel module */
result = ac_kmod_link();
if (result) {
ac_kmod_free();
return result;
}
/* Configure netlink message socket */
g_ac.kmodhandle.nlmsg_cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!g_ac.kmodhandle.nlmsg_cb) {
ac_kmod_free();
return -1;
}
/* */
g_ac.kmodhandle.nlmsg = nl_create_handle(g_ac.kmodhandle.nlmsg_cb);
if (!g_ac.kmodhandle.nlmsg) {
ac_kmod_free();
return -1;
}
return 0;
}
/* */
void ac_kmod_free(void) {
if (g_ac.kmodhandle.nl) {
nl_socket_free(g_ac.kmodhandle.nl);
}
if (g_ac.kmodhandle.nl_cb) {
nl_cb_put(g_ac.kmodhandle.nl_cb);
}
if (g_ac.kmodhandle.nlmsg) {
nl_socket_free(g_ac.kmodhandle.nlmsg);
}
if (g_ac.kmodhandle.nlmsg_cb) {
nl_cb_put(g_ac.kmodhandle.nlmsg_cb);
}
/* */
capwap_lock_destroy(&g_ac.kmodhandle.msglock);
/* */
memset(&g_ac.kmodhandle, 0, sizeof(struct ac_kmod_handle));
}

View File

@ -1,71 +0,0 @@
#ifndef __AC_KMOD_HEADER__
#define __AC_KMOD_HEADER__
/* */
#ifdef HAVE_LIBNL_10
#define nl_sock nl_handle
#endif
/* */
#define AC_KMOD_MODE_LOCAL 0x00000001
#define AC_KMOD_MODE_TUNNEL_USERMODE 0x00000002
#define AC_KMOD_MODE_TUNNEL_KERNELMODE 0x00000003
/* */
#define AC_KMOD_FLAGS_TUNNEL_NATIVE 0x00000000
#define AC_KMOD_FLAGS_TUNNEL_8023 0x00000001
/* */
struct ac_kmod_handle {
/* Callback */
struct nl_sock* nl;
int nl_fd;
struct nl_cb* nl_cb;
int nlsmartcapwap_id;
/* Send message */
capwap_lock_t msglock;
struct nl_sock* nlmsg;
struct nl_cb* nlmsg_cb;
};
/* */
#define AC_KMOD_EVENT_MAX_ITEMS 2
struct ac_kmod_event {
void (*event_handler)(int fd, void** params, int paramscount);
int paramscount;
void* params[AC_KMOD_EVENT_MAX_ITEMS];
};
/* */
int ac_kmod_init(void);
void ac_kmod_free(void);
/* */
int ac_kmod_isconnected(void);
int ac_kmod_getfd(struct pollfd* fds, struct ac_kmod_event* events, int count);
/* */
int ac_kmod_createdatachannel(int family, unsigned short port);
/* */
int ac_kmod_send_keepalive(struct capwap_sessionid_element* sessionid);
int ac_kmod_send_data(struct capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t binding, const uint8_t* data, int length);
/* */
int ac_kmod_create_iface(const char* ifname, uint16_t mtu);
int ac_kmod_delete_iface(int ifindex);
/* */
int ac_kmod_new_datasession(struct capwap_sessionid_element* sessionid, uint8_t binding, uint16_t mtu);
int ac_kmod_delete_datasession(struct capwap_sessionid_element* sessionid);
/* */
int ac_kmod_addwlan(struct capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, uint8_t macmode, uint8_t tunnelmode);
int ac_kmod_removewlan(struct capwap_sessionid_element* sessionid);
/* */
int ac_kmod_authorize_station(struct capwap_sessionid_element* sessionid, const uint8_t* macaddress, int ifindex, uint8_t radioid, uint8_t wlanid, uint16_t vlan);
int ac_kmod_deauthorize_station(struct capwap_sessionid_element* sessionid, const uint8_t* macaddress);
#endif /* __AC_KMOD_HEADER__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,219 +0,0 @@
#ifndef __AC_SESSION_HEADER__
#define __AC_SESSION_HEADER__
#include "capwap_dtls.h"
#include "capwap_event.h"
#include "capwap_lock.h"
#include "ac_soap.h"
#include "ieee80211.h"
/* AC packet */
struct ac_packet {
int plainbuffer;
char buffer[0];
};
/* */
struct ac_session_control {
union sockaddr_capwap localaddress;
unsigned short count;
};
/* */
#define AC_SESSION_ACTION_CLOSE 0
#define AC_SESSION_ACTION_RESET_WTP 1
#define AC_SESSION_ACTION_NOTIFY_EVENT 2
#define AC_SESSION_ACTION_RECV_KEEPALIVE 10
#define AC_SESSION_ACTION_RECV_IEEE80211_MGMT_PACKET 11
#define AC_SESSION_ACTION_ADDWLAN 20
#define AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION 30
#define AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION 31
#define AC_SESSION_ACTION_STATION_ROAMING 32
/* */
struct ac_session_action {
long action;
long param;
long length;
char data[0];
};
/* */
#define NOTIFY_ACTION_CHANGE_STATE 0
#define NOTIFY_ACTION_RECEIVE_REQUEST_CONTROLMESSAGE 1
#define NOTIFY_ACTION_RECEIVE_RESPONSE_CONTROLMESSAGE 1
struct ac_session_notify_event_t {
char idevent[65];
int action;
union {
unsigned long session_state;
uint32_t ctrlmsg_type;
};
};
/* Reset notification */
struct ac_notify_reset_t {
uint32_t vendor;
uint8_t name[0];
};
/* Add WLAN notification */
struct ac_notify_addwlan_t {
uint8_t radioid;
uint8_t wlanid;
uint16_t capability;
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t suppressssid;
char ssid[CAPWAP_ADD_WLAN_SSID_LENGTH + 1];
};
/* Station Configuration IEEE802.11 add station notification */
struct ac_notify_station_configuration_ieee8011_add_station {
uint8_t radioid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint8_t wlanid;
uint16_t associationid;
uint16_t capabilities;
uint8_t supportedratescount;
uint8_t supportedrates[CAPWAP_STATION_RATES_MAXLENGTH];
};
/* Station Configuration IEEE802.11 delete station notification */
struct ac_notify_station_configuration_ieee8011_delete_station {
uint8_t radioid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
};
/* */
struct ac_session_t;
/* AC sessions */
struct ac_session_t {
int running;
pthread_t threadid;
struct capwap_list_item* itemlist; /* My itemlist into g_ac.sessions */
/* Reference */
long count;
capwap_event_t changereference;
/* Soap */
struct ac_http_soap_request* soaprequest;
/* WLAN Reference */
struct ac_wlans* wlans;
/* */
char* wtpid;
unsigned long state;
struct ac_state dfa;
/* */
unsigned short binding;
struct capwap_sessionid_element sessionid;
unsigned short mtu;
struct capwap_dtls dtls;
struct capwap_timeout* timeout;
unsigned long idtimercontrol;
unsigned long idtimerkeepalivedead;
capwap_event_t waitpacket;
capwap_lock_t sessionlock;
struct capwap_list* action;
struct capwap_list* packets;
struct capwap_list* notifyevent;
unsigned short fragmentid;
struct capwap_packet_rxmng* rxmngpacket;
uint8_t localseqnumber;
struct capwap_list* requestfragmentpacket;
int retransmitcount;
uint32_t remotetype;
uint8_t remoteseqnumber;
struct capwap_list* responsefragmentpacket;
};
/* Session */
void* ac_session_thread(void* param);
void ac_session_send_action(struct ac_session_t* session, long action, long param, const void* data, long length);
void ac_session_teardown(struct ac_session_t* session);
void ac_session_close(struct ac_session_t* session);
void ac_session_release_reference(struct ac_session_t* session);
/* */
struct ac_session_t* ac_search_session_from_sessionid(struct capwap_sessionid_element* sessionid);
int ac_has_sessionid(struct capwap_sessionid_element* sessionid);
/* */
struct ac_session_t* ac_search_session_from_wtpid(const char* wtpid);
int ac_has_wtpid(const char* wtpid);
/* */
char* ac_get_printable_wtpid(struct capwap_wtpboarddata_element* wtpboarddata);
/* */
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);
/* */
void ac_ieee80211_packet(struct ac_session_t* session, uint8_t radioid, const struct ieee80211_header* header, int length);
/* */
int ac_msgqueue_init(void);
void ac_msgqueue_free(void);
/* */
int ac_msgqueue_notify_closethread(pthread_t threadid);
int ac_msgqueue_update_configuration(struct json_object* jsonroot);
int ac_msgqueue_close_allsessions(void);
/* */
int ac_dtls_setup(struct ac_session_t* session);
/* */
void ac_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void ac_dfa_teardown_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
/* */
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet);
void ac_dfa_state_teardown(struct ac_session_t* session);
/* Soap function */
struct ac_soap_response* ac_session_send_soap_request(struct ac_session_t* session, char* method, int numparam, ...);
#define ac_soap_authorizewtpsession(s, wtpid) ac_session_send_soap_request((s), "authorizeWTPSession", 1, "xs:string", "idwtp", wtpid)
#define ac_soap_joinwtpsession(s, wtpid, joinparam) ac_session_send_soap_request((s), "joinWTPSession", 2, "xs:string", "idwtp", wtpid, "xs:base64Binary", "join", joinparam)
#define ac_soap_configurestatuswtpsession(s, wtpid, confstatusparam) ac_session_send_soap_request((s), "configureStatusWTPSession", 2, "xs:string", "idwtp", wtpid, "xs:base64Binary", "confstatus", confstatusparam)
#define ac_soap_changestatewtpsession(s, wtpid, changestateparam) ac_session_send_soap_request((s), "changeStateWTPSession", 2, "xs:string", "idwtp", wtpid, "xs:base64Binary", "changestate", changestateparam)
#define ac_soap_runningwtpsession(s, wtpid) ac_session_send_soap_request((s), "runningWTPSession", 1, "xs:string", "idwtp", wtpid)
#define ac_soap_teardownwtpsession(s, wtpid) ac_session_send_soap_request((s), "teardownWTPSession", 1, "xs:string", "idwtp", wtpid)
#define ac_soap_checkwtpsession(s, wtpid) ac_session_send_soap_request((s), "checkWTPSession", 1, "xs:string", "idwtp", wtpid)
#define ac_soap_updatebackendevent(s, idevent, status) ac_session_send_soap_request((s), "updateBackendEvent", 2, "xs:string", "idevent", idevent, "xs:int", "status", status)
#define ac_soap_authorizestation(s, wtpid, stationparam) ac_session_send_soap_request((s), "authorizeStation", 2, "xs:string", "idwtp", wtpid, "xs:base64Binary", "station", stationparam)
#endif /* __AC_SESSION_HEADER__ */

View File

@ -1,868 +0,0 @@
#include "ac.h"
#include "ac_soap.h"
#include "capwap_socket.h"
/* */
#define SOAP_PROTOCOL_CONNECT_TIMEOUT 10000
/* */
#define HTTP_RESPONSE_STATUS_CODE 0
#define HTTP_RESPONSE_HEADER 1
#define HTTP_RESPONSE_BODY 2
#define HTTP_RESPONSE_ERROR 3
/* */
static const char l_encodeblock[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char l_decodeblock[] =
"\x3f\x00\x00\x00\x40\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x00"
"\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
"\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a"
"\x00\x00\x00\x00\x00\x00\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24"
"\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34";
/* */
xmlNodePtr ac_xml_get_children(xmlNodePtr parent) {
xmlNodePtr children;
ASSERT(parent != NULL);
/* */
children = parent->xmlChildrenNode;
while ((children != NULL) && (children->type != XML_ELEMENT_NODE)) {
children = children->next;
}
return children;
}
/* */
xmlNodePtr ac_xml_get_next(xmlNodePtr element) {
xmlNodePtr node;
ASSERT(element != NULL);
node = element->next;
while ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
node = node->next;
}
return node;
}
xmlNodePtr ac_xml_search_child(xmlNodePtr parent, char* prefix, char* name) {
xmlNodePtr children;
ASSERT(parent != NULL);
ASSERT(name != NULL);
children = ac_xml_get_children(parent);
while (children != NULL) {
if (!xmlStrcmp(children->name, BAD_CAST name) && (!prefix || !xmlStrcmp(children->ns->prefix, BAD_CAST prefix))) {
break;
}
/* */
children = ac_xml_get_next(children);
}
return children;
}
/* */
static int ac_soapclient_parsing_url(struct ac_http_soap_server* server, const char* url) {
int length;
int protocol;
int host;
int port;
int hostlength;
int pathlength;
ASSERT(server != NULL);
ASSERT(url != NULL);
/* */
length = strlen(url);
if (length < 8) {
/* Invalid URL */
return 0;
}
/* Search protocol */
protocol = 0;
while (url[protocol] && url[protocol] != ':') {
protocol++;
}
if (!protocol || (protocol + 3 >= length)) {
/* Invalid URL */
return 0;
} else if ((url[protocol] != ':') || (url[protocol + 1] != '/') || (url[protocol + 2] != '/')) {
/* Invalid URL */
return 0;
}
/* Parsing protocol */
if (!strncasecmp(url, "http", protocol)) {
server->protocol = SOAP_HTTP_PROTOCOL;
} else if (!strncasecmp(url, "https", protocol)) {
server->protocol = SOAP_HTTPS_PROTOCOL;
} else {
/* Unknown protocol */
return 0;
}
protocol += 3;
/* Search hostname */
host = protocol;
while (url[host] && (url[host] != ':') && (url[host] != '/')) {
host++;
}
if (host == protocol) {
/* Invalid hostname */
return 0;
}
/* Search port */
port = host;
if (url[port] == ':') {
while (url[port] && (url[port] != '/')) {
port++;
}
}
/* Retrieve hostname */
hostlength = port - protocol;
server->host = capwap_alloc(hostlength + 1);
strncpy(server->host, &url[protocol], hostlength);
server->host[hostlength] = 0;
/* Parsing hostname */
if (!capwap_address_from_string(server->host, &server->address)) {
/* Invalid hostname */
return 0;
}
if (port == host) {
/* Get default port */
if (server->protocol == SOAP_HTTP_PROTOCOL) {
CAPWAP_SET_NETWORK_PORT(&server->address, SOAP_HTTP_PORT);
} else if (server->protocol == SOAP_HTTPS_PROTOCOL) {
CAPWAP_SET_NETWORK_PORT(&server->address, SOAP_HTTPS_PORT);
}
}
/* Retrieve path */
pathlength = length - port;
if (!pathlength) {
pathlength = 1;
}
server->path = capwap_alloc(pathlength + 1);
if (length == port) {
strcpy(server->path, "/");
} else {
strncpy(server->path, &url[port], pathlength);
server->path[pathlength] = 0;
}
return 1;
}
/* */
static int ac_soapclient_connect(struct ac_http_soap_request* httprequest) {
int result = 0;
if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) {
result = capwap_socket_connect(httprequest->sock, &httprequest->server->address, SOAP_PROTOCOL_CONNECT_TIMEOUT);
} else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) {
result = capwap_socket_connect(httprequest->sock, &httprequest->server->address, SOAP_PROTOCOL_CONNECT_TIMEOUT);
if (result) {
/* Establish SSL/TLS connection */
httprequest->sslsock = capwap_socket_ssl_connect(httprequest->sock, httprequest->server->sslcontext, SOAP_PROTOCOL_CONNECT_TIMEOUT);
if (!httprequest->sslsock) {
result = 0;
}
}
}
return result;
}
/* */
static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, char* soapaction, char* body, int length) {
time_t ts;
struct tm stm;
char datetime[32];
int headerlength;
int result;
char* buffer;
/* Retrieve datetime */
ts = time(NULL);
localtime_r(&ts, &stm);
strftime(datetime, 32, "%a, %d %b %Y %T %z", &stm);
/* Calculate header length */
headerlength = 150 + length + strlen(httprequest->server->path) + strlen(httprequest->server->host) + strlen(datetime) + strlen((soapaction ? soapaction : ""));
buffer = capwap_alloc(headerlength);
/* HTTP headers */
result = snprintf(buffer, headerlength,
"POST %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Date: %s\r\n"
"Content-Length: %d\r\n"
"Content-Type: text/xml\r\n"
"Connection: Close\r\n"
"SoapAction: %s\r\n"
"Expect: 100-continue\r\n"
"\r\n"
"%s",
httprequest->server->path,
httprequest->server->host,
datetime,
length,
(soapaction ? soapaction : ""),
body
);
/* Send headers */
if (result < 0) {
result = 0;
} else {
int sendlength = -1;
/* Send packet */
if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) {
sendlength = capwap_socket_send(httprequest->sock, buffer, result, httprequest->requesttimeout);
} else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) {
sendlength = capwap_socket_crypto_send(httprequest->sslsock, buffer, result, httprequest->requesttimeout);
}
/* Check result */
result = ((sendlength == result) ? 1 : 0);
}
/* */
capwap_free(buffer);
return result;
}
/* */
static int ac_soapclient_http_readline(struct ac_http_soap_request* httprequest, char* buffer, int length) {
int result = -1;
int bufferpos = 0;
for (;;) {
/* Receive packet into temporaly buffer */
if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) {
if (capwap_socket_recv(httprequest->sock, &buffer[bufferpos], 1, httprequest->responsetimeout) != 1) {
break; /* Connection error */
}
} else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) {
if (capwap_socket_crypto_recv(httprequest->sslsock, &buffer[bufferpos], 1, httprequest->responsetimeout) != 1) {
break; /* Connection error */
}
}
/* Update buffer size */
bufferpos += 1;
if (bufferpos >= length) {
break; /* Buffer overflow */
}
/* Search line */
if ((bufferpos > 1) && (buffer[bufferpos - 2] == '\r') && (buffer[bufferpos - 1] == '\n')) {
result = bufferpos - 2;
buffer[result] = 0;
break;
}
}
return result;
}
/* */
static int ac_soapclient_xml_io_read(void* ctx, char* buffer, int len) {
int result = -1;
char respbuffer[8192];
int respbufferlength = 0;
struct ac_http_soap_request* httprequest = (struct ac_http_soap_request*)ctx;
while ((httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) || (httprequest->httpstate == HTTP_RESPONSE_HEADER)) {
/* Receive packet into temporaly buffer */
respbufferlength = ac_soapclient_http_readline(httprequest, respbuffer, sizeof(respbuffer));
if (respbufferlength == -1) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
} else if (httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) {
int temp;
int descpos;
/* Parse response code */
temp = sscanf(respbuffer, "HTTP/1.1 %d %n", &httprequest->responsecode, &descpos);
if (temp != 1) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
/* Parsing headers */
httprequest->httpstate = HTTP_RESPONSE_HEADER;
} else if (httprequest->httpstate == HTTP_RESPONSE_HEADER) {
char* value;
if (!respbufferlength) {
if (httprequest->responsecode == HTTP_RESULT_CONTINUE) {
if (!httprequest->contentlength) {
httprequest->httpstate = HTTP_RESPONSE_STATUS_CODE;
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
}
} else if (httprequest->contentxml && (httprequest->contentlength > 0)) {
httprequest->httpstate = HTTP_RESPONSE_BODY; /* Retrieve body */
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
}
} else {
/* Separate key from value */
value = strchr(respbuffer, ':');
if (!value) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
} else {
*value = 0;
value++;
while (*value == ' ') {
value++;
}
/* */
if (!strcmp(respbuffer, "Content-Length")) {
httprequest->contentlength = atoi(value);
if (!httprequest->contentlength) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
}
} else if (!strcmp(respbuffer, "Content-Type")) {
char* param;
/* Remove param from value */
param = strchr(value, ';');
if (param) {
*param = 0;
}
if (!strcmp(value, "text/xml")) {
httprequest->contentxml = 1;
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
}
}
}
}
}
}
if (httprequest->httpstate == HTTP_RESPONSE_BODY) {
if (!httprequest->contentlength) {
return 0;
}
/* Receive body directly into XML buffer */
if (httprequest->server->protocol == SOAP_HTTP_PROTOCOL) {
result = capwap_socket_recv(httprequest->sock, buffer, len, httprequest->responsetimeout);
} else if (httprequest->server->protocol == SOAP_HTTPS_PROTOCOL) {
result = capwap_socket_crypto_recv(httprequest->sslsock, buffer, len, httprequest->responsetimeout);
}
if (result > 0) {
httprequest->contentlength -= result;
}
}
return result;
}
/* */
static int ac_soapclient_xml_io_close(void *ctx) {
struct ac_http_soap_request* httprequest = (struct ac_http_soap_request*)ctx;
if ((httprequest->httpstate != HTTP_RESPONSE_BODY) || httprequest->contentlength) {
return -1;
}
return 0;
}
/* */
static void ac_soapclient_parse_error(void* ctxt, const char* msg, ...) {
}
/* */
void ac_soapclient_init(void) {
xmlInitParser();
xmlSetGenericErrorFunc(NULL, ac_soapclient_parse_error);
xmlThrDefSetGenericErrorFunc(NULL, ac_soapclient_parse_error);
}
/* */
void ac_soapclient_free(void) {
xmlCleanupParser();
}
/* */
struct ac_http_soap_server* ac_soapclient_create_server(const char* url) {
struct ac_http_soap_server* server;
ASSERT(url != NULL);
/* */
server = (struct ac_http_soap_server*)capwap_alloc(sizeof(struct ac_http_soap_server));
memset(server, 0, sizeof(struct ac_http_soap_server));
/* */
if (!ac_soapclient_parsing_url(server, url)) {
ac_soapclient_free_server(server);
return NULL;
}
return server;
}
/* */
void ac_soapclient_free_server(struct ac_http_soap_server* server) {
ASSERT(server != NULL);
if (server->host) {
capwap_free(server->host);
}
if (server->path) {
capwap_free(server->path);
}
if (server->sslcontext) {
capwap_socket_crypto_freecontext(server->sslcontext);
}
capwap_free(server);
}
/* */
struct ac_soap_request* ac_soapclient_create_request(char* method, char* urinamespace) {
char* tagMethod;
struct ac_soap_request* request;
ASSERT(method != NULL);
ASSERT(urinamespace != NULL);
/* */
request = (struct ac_soap_request*)capwap_alloc(sizeof(struct ac_soap_request));
memset(request, 0, sizeof(struct ac_soap_request));
/* Build XML SOAP Request */
request->xmlDocument = xmlNewDoc(BAD_CAST "1.0");
request->xmlRoot = xmlNewNode(NULL, BAD_CAST "SOAP-ENV:Envelope");
xmlNewProp(request->xmlRoot, BAD_CAST "xmlns:xsd", BAD_CAST "http://www.w3.org/2001/XMLSchema");
xmlNewProp(request->xmlRoot, BAD_CAST "xmlns:xsi", BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
xmlNewProp(request->xmlRoot, BAD_CAST "xmlns:SOAP-ENC", BAD_CAST "http://schemas.xmlsoap.org/soap/encoding/");
xmlNewProp(request->xmlRoot, BAD_CAST "SOAP-ENV:encodingStyle", BAD_CAST "http://schemas.xmlsoap.org/soap/encoding/");
xmlNewProp(request->xmlRoot, BAD_CAST "xmlns:SOAP-ENV", BAD_CAST "http://schemas.xmlsoap.org/soap/envelope/");
xmlNewProp(request->xmlRoot, BAD_CAST "xmlns:tns", BAD_CAST urinamespace);
xmlDocSetRootElement(request->xmlDocument, request->xmlRoot);
xmlNewChild(request->xmlRoot, NULL, BAD_CAST "SOAP-ENV:Header", NULL);
request->xmlBody = xmlNewChild(request->xmlRoot, NULL, BAD_CAST "SOAP-ENV:Body", NULL);
/* */
request->method = capwap_duplicate_string(method);
/* Create request */
tagMethod = capwap_alloc(strlen(method) + 5);
sprintf(tagMethod, "tns:%s", method);
request->xmlRequest = xmlNewChild(request->xmlBody, NULL, BAD_CAST tagMethod, NULL);
capwap_free(tagMethod);
return request;
}
/* */
void ac_soapclient_free_request(struct ac_soap_request* request) {
ASSERT(request != NULL);
if (request->xmlDocument) {
xmlFreeDoc(request->xmlDocument);
}
if (request->method) {
capwap_free(request->method);
}
capwap_free(request);
}
/* */
int ac_soapclient_add_param(struct ac_soap_request* request, const char* type, const char* name, const char* value) {
xmlNodePtr xmlParam;
ASSERT(request != NULL);
ASSERT(name != NULL);
ASSERT(value != NULL);
/* */
xmlParam = xmlNewTextChild(request->xmlRequest, NULL, BAD_CAST name, BAD_CAST value);
if (!xmlParam) {
return 0;
}
if (type) {
if (!xmlNewProp(xmlParam, BAD_CAST "xsi:type", BAD_CAST type)) {
return 0;
}
}
return 1;
}
/* */
char* ac_soapclient_get_request(struct ac_soap_request* request) {
char* result;
size_t length;
xmlBufferPtr buffer;
ASSERT(request != NULL);
ASSERT(request->xmlDocument != NULL);
/* */
buffer = xmlBufferCreate();
length = xmlNodeDump(buffer, request->xmlDocument, request->xmlRoot, 1, 0);
/* Clone XML document string */
result = capwap_alloc(length + 1);
memcpy(result, (char*)xmlBufferContent(buffer), length);
result[length] = 0;
/* */
xmlBufferFree(buffer);
return result;
}
/* */
struct ac_http_soap_request* ac_soapclient_prepare_request(struct ac_soap_request* request, struct ac_http_soap_server* server) {
struct ac_http_soap_request* httprequest;
ASSERT(request != NULL);
ASSERT(request->xmlDocument != NULL);
ASSERT(request->xmlRoot != NULL);
ASSERT(server != NULL);
/* */
httprequest = (struct ac_http_soap_request*)capwap_alloc(sizeof(struct ac_http_soap_request));
memset(httprequest, 0, sizeof(struct ac_http_soap_request));
/* */
httprequest->request = request;
httprequest->server = server;
httprequest->requesttimeout = SOAP_PROTOCOL_REQUEST_TIMEOUT;
httprequest->responsetimeout = SOAP_PROTOCOL_RESPONSE_TIMEOUT;
/* Create socket */
httprequest->sock = socket(httprequest->server->address.ss.ss_family, SOCK_STREAM, 0);
if (httprequest->sock < 0) {
ac_soapclient_close_request(httprequest, 0);
return NULL;
}
return httprequest;
}
/* */
int ac_soapclient_send_request(struct ac_http_soap_request* httprequest, char* soapaction) {
char* buffer;
size_t length;
xmlBufferPtr xmlBuffer;
ASSERT(httprequest != NULL);
/* Retrieve XML SOAP Request */
xmlBuffer = xmlBufferCreate();
length = xmlNodeDump(xmlBuffer, httprequest->request->xmlDocument, httprequest->request->xmlRoot, 1, 0);
if (!length) {
return 0;
}
buffer = (char*)xmlBufferContent(xmlBuffer);
/* Connect to remote host */
if (!ac_soapclient_connect(httprequest)) {
xmlBufferFree(xmlBuffer);
return 0;
}
/* Send HTTP Header */
if (!ac_soapclient_send_http(httprequest, soapaction, buffer, (int)length)) {
xmlBufferFree(xmlBuffer);
return 0;
}
/* Sent SOAP Request */
xmlBufferFree(xmlBuffer);
return 1;
}
/* */
void ac_soapclient_shutdown_request(struct ac_http_soap_request* httprequest) {
ASSERT(httprequest != NULL);
if (httprequest->sslsock) {
capwap_socket_ssl_shutdown(httprequest->sslsock, SOAP_PROTOCOL_CLOSE_TIMEOUT);
}
if (httprequest->sock >= 0) {
capwap_socket_shutdown(httprequest->sock);
}
}
/* */
void ac_soapclient_close_request(struct ac_http_soap_request* httprequest, int closerequest) {
ASSERT(httprequest != NULL);
/* */
if (closerequest && httprequest->request) {
ac_soapclient_free_request(httprequest->request);
}
/* */
if (httprequest->sslsock) {
capwap_socket_ssl_shutdown(httprequest->sslsock, SOAP_PROTOCOL_CLOSE_TIMEOUT);
capwap_socket_ssl_close(httprequest->sslsock);
capwap_free(httprequest->sslsock);
}
/* Close socket */
if (httprequest->sock >= 0) {
capwap_socket_close(httprequest->sock);
}
capwap_free(httprequest);
}
/* */
struct ac_soap_response* ac_soapclient_recv_response(struct ac_http_soap_request* httprequest) {
struct ac_soap_response* response;
ASSERT(httprequest != NULL);
ASSERT(httprequest->sock >= 0);
/* */
response = (struct ac_soap_response*)capwap_alloc(sizeof(struct ac_soap_response));
memset(response, 0, sizeof(struct ac_soap_response));
/* Receive HTTP response into XML callback */
httprequest->httpstate = HTTP_RESPONSE_STATUS_CODE;
response->xmlDocument = xmlReadIO(ac_soapclient_xml_io_read, ac_soapclient_xml_io_close, (void*)httprequest, "", NULL, 0);
if (!response->xmlDocument) {
ac_soapclient_free_response(response);
return NULL;
}
/* Parsing response */
response->responsecode = httprequest->responsecode;
response->xmlRoot = xmlDocGetRootElement(response->xmlDocument);
if (!response->xmlRoot) {
ac_soapclient_free_response(response);
return NULL;
}
/* Retrieve Body */
response->xmlBody = ac_xml_search_child(response->xmlRoot, "SOAP-ENV", "Body");
if (!response->xmlBody) {
ac_soapclient_free_response(response);
return NULL;
}
/* Retrieve response */
if (response->responsecode == HTTP_RESULT_OK) {
char* tagMethod = capwap_alloc(strlen(httprequest->request->method) + 9);
sprintf(tagMethod, "%sResponse", httprequest->request->method);
response->xmlResponse = ac_xml_search_child(response->xmlBody, NULL, tagMethod);
capwap_free(tagMethod);
if (!response->xmlResponse) {
ac_soapclient_free_response(response);
return NULL;
}
/* Retrieve optional return response */
response->xmlResponseReturn = ac_xml_search_child(response->xmlResponse, NULL, "return");
} else {
/* Retrieve Fault */
response->xmlFault = ac_xml_search_child(response->xmlBody, "SOAP-ENV", "Fault");
if (!response->xmlFault) {
ac_soapclient_free_response(response);
return NULL;
}
/* Retrieve FaultCode */
response->xmlFaultCode = ac_xml_search_child(response->xmlFault, NULL, "faultcode");
if (!response->xmlFaultCode) {
ac_soapclient_free_response(response);
return NULL;
}
/* Retrieve FaultString */
response->xmlFaultString = ac_xml_search_child(response->xmlFault, NULL, "faultstring");
if (!response->xmlFaultString) {
ac_soapclient_free_response(response);
return NULL;
}
}
return response;
}
/* */
struct json_object* ac_soapclient_parse_json_response(struct ac_soap_response* response) {
int length;
char* json;
xmlChar* xmlResult;
struct json_object* jsonroot;
ASSERT(response != NULL);
/* */
if ((response->responsecode != HTTP_RESULT_OK) || !response->xmlResponseReturn) {
return NULL;
}
/* Decode base64 result */
xmlResult = xmlNodeGetContent(response->xmlResponseReturn);
if (!xmlResult) {
return NULL;
}
length = xmlStrlen(xmlResult);
if (!length) {
xmlFree(xmlResult);
return NULL;
}
json = (char*)capwap_alloc(AC_BASE64_DECODE_LENGTH(length));
ac_base64_string_decode((const char*)xmlResult, json);
xmlFree(xmlResult);
/* Parsing JSON result */
jsonroot = json_tokener_parse(json);
capwap_free(json);
return jsonroot;
}
/* */
void ac_soapclient_free_response(struct ac_soap_response* response) {
ASSERT(response != NULL);
if (response->xmlDocument) {
xmlFreeDoc(response->xmlDocument);
}
capwap_free(response);
}
/* */
int ac_base64_binary_encode(const char* plain, int length, char* encoded) {
int result = 0;
ASSERT(plain != NULL);
ASSERT(encoded != NULL);
while (length > 0) {
int len = ((length > 1) ? ((length > 2) ? 3 : 2) : 1);
/* Encode block */
encoded[0] = l_encodeblock[plain[0] >> 2];
encoded[1] = l_encodeblock[((plain[0] & 0x03) << 4) | ((plain[1] & 0xf0) >> 4)];
encoded[2] = (len > 1 ? l_encodeblock[((plain[1] & 0x0f) << 2) | ((plain[2] & 0xc0) >> 6)] : '=');
encoded[3] = (len > 2 ? l_encodeblock[plain[2] & 0x3f] : '=');
/* Next block */
plain += len;
length -= len;
encoded += 4;
result += 4;
}
return result;
}
/* */
void ac_base64_string_encode(const char* plain, char* encoded) {
int result;
ASSERT(plain != NULL);
ASSERT(encoded != NULL);
/* Encode base64 */
result = ac_base64_binary_encode(plain, strlen(plain), encoded);
/* Terminate string */
encoded[result] = 0;
}
/* */
int ac_base64_binary_decode(const char* encoded, int length, char* plain) {
int i;
char bufdec[3];
int result = 0;
ASSERT(encoded != NULL);
ASSERT(plain != NULL);
while (length > 0) {
int len = 0;
char bufenc[4] = { 0, 0, 0, 0 };
for (i = 0; i < 4 && (length > 0); i++) {
char element = 0;
while ((length > 0) && !element) {
element = *encoded++;
element = (((element < 43) || (element > 122)) ? 0 : l_decodeblock[element - 43]);
length--;
}
if (element) {
len++;
bufenc[i] = element - 1;
}
}
if (len) {
bufdec[0] = (bufenc[0] << 2 | bufenc[1] >> 4);
bufdec[1] = (bufenc[1] << 4 | bufenc[2] >> 2);
bufdec[2] = (((bufenc[2] << 6) & 0xc0) | bufenc[3]);
for (i = 0; i < len - 1; i++) {
*plain++ = bufdec[i];
result++;
}
}
}
/* Terminate string */
return result;
}
/* */
void ac_base64_string_decode(const char* encoded, char* plain) {
int result;
ASSERT(encoded != NULL);
ASSERT(plain != NULL);
/* Decode base64 */
result = ac_base64_binary_decode(encoded, strlen(encoded), plain);
/* Terminate string */
plain[result] = 0;
}

View File

@ -1,114 +0,0 @@
#ifndef __AC_SOAP_HEADER__
#define __AC_SOAP_HEADER__
#include <libxml/tree.h>
#include <libxml/parser.h>
/* */
#define SOAP_HTTP_PROTOCOL 1
#define SOAP_HTTPS_PROTOCOL 2
#define SOAP_HTTP_PORT 80
#define SOAP_HTTPS_PORT 443
#define HTTP_RESULT_CONTINUE 100
#define HTTP_RESULT_OK 200
#define SOAP_PROTOCOL_REQUEST_TIMEOUT 10000
#define SOAP_PROTOCOL_RESPONSE_TIMEOUT 10000
#define SOAP_PROTOCOL_CLOSE_TIMEOUT 10000
/* */
struct ac_http_soap_server {
int protocol;
union sockaddr_capwap address;
char* host;
char* path;
/* SSL/TLS context */
void* sslcontext;
};
/* */
struct ac_soap_request {
xmlDocPtr xmlDocument;
xmlNodePtr xmlRoot;
xmlNodePtr xmlBody;
xmlNodePtr xmlRequest;
char* method;
};
/* */
struct ac_http_soap_request {
struct ac_http_soap_server* server;
struct ac_soap_request* request;
int sock;
int requesttimeout;
int responsetimeout;
/* SSL info */
struct capwap_socket_ssl* sslsock;
/* Information for SOAP Response */
int httpstate;
int responsecode;
int contentlength;
int contentxml;
};
/* */
struct ac_soap_response {
int responsecode;
xmlDocPtr xmlDocument;
xmlNodePtr xmlRoot;
xmlNodePtr xmlBody;
/* Valid response */
xmlNodePtr xmlResponse;
xmlNodePtr xmlResponseReturn;
/* Fault response */
xmlNodePtr xmlFault;
xmlNodePtr xmlFaultCode;
xmlNodePtr xmlFaultString;
};
/* */
void ac_soapclient_init(void);
void ac_soapclient_free(void);
/* */
struct ac_http_soap_server* ac_soapclient_create_server(const char* url);
void ac_soapclient_free_server(struct ac_http_soap_server* server);
/* Request */
struct ac_soap_request* ac_soapclient_create_request(char* method, char* urinamespace);
int ac_soapclient_add_param(struct ac_soap_request* request, const char* type, const char* name, const char* value);
char* ac_soapclient_get_request(struct ac_soap_request* request);
void ac_soapclient_free_request(struct ac_soap_request* request);
/* Transport Request */
struct ac_http_soap_request* ac_soapclient_prepare_request(struct ac_soap_request* request, struct ac_http_soap_server* server);
int ac_soapclient_send_request(struct ac_http_soap_request* httprequest, char* soapaction);
struct ac_soap_response* ac_soapclient_recv_response(struct ac_http_soap_request* httprequest);
struct json_object* ac_soapclient_parse_json_response(struct ac_soap_response* response);
void ac_soapclient_shutdown_request(struct ac_http_soap_request* httprequest);
void ac_soapclient_close_request(struct ac_http_soap_request* httprequest, int closerequest);
/* Response */
void ac_soapclient_free_response(struct ac_soap_response* response);
/* Base64 */
#define AC_BASE64_ENCODE_LENGTH(x) ((((x) + 2) / 3) * 4 + 1)
#define AC_BASE64_DECODE_LENGTH(x) (((x) / 4) * 3 + 1)
void ac_base64_string_encode(const char* plain, char* encoded);
int ac_base64_binary_encode(const char* plain, int length, char* encoded);
void ac_base64_string_decode(const char* encoded, char* plain);
int ac_base64_binary_decode(const char* encoded, int length, char* plain);
#endif /* __AC_SOAP_HEADER__ */

View File

@ -1,487 +0,0 @@
#include "ac.h"
#include "ac_session.h"
#include "ac_wlans.h"
#include "ac_backend.h"
/* */
static void ac_stations_reset_station(struct ac_session_t* session, struct ac_station* station, struct ac_wlan* wlan) {
ASSERT(session != NULL);
ASSERT(station != NULL);
if (station->wlan) {
if (station->aid) {
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
ieee80211_aid_free(station->wlan->aidbitfield, station->aid);
}
station->aid = 0;
}
/* Remove reference from current WLAN */
capwap_itemlist_remove(station->wlan->stations, station->wlanitem);
}
/* Remove timers */
if (station->idtimeout != CAPWAP_TIMEOUT_INDEX_NO_SET) {
capwap_timeout_deletetimer(session->timeout, station->idtimeout);
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
}
/* */
station->flags = 0;
/* Set WLAN */
station->wlan = wlan;
if (station->wlan) {
capwap_itemlist_insert_after(wlan->stations, NULL, station->wlanitem);
}
}
/* */
static void ac_stations_destroy_station(struct ac_session_t* session, struct ac_station* station) {
struct ac_station* authoritativestation;
ASSERT(session != NULL);
ASSERT(station != NULL);
/* */
log_printf(LOG_INFO, "Destroy station: " MACSTR, MAC2STR(station->address));
/* Remove reference from Authoritative Stations List */
capwap_rwlock_wrlock(&g_ac.authstationslock);
/* Can delete global reference only if match session handler */
authoritativestation = (struct ac_station*)capwap_hash_search(g_ac.authstations, station->address);
if (authoritativestation && (authoritativestation->session == session)) {
capwap_hash_delete(g_ac.authstations, station->address);
}
capwap_rwlock_unlock(&g_ac.authstationslock);
/* Remove reference from WLAN */
ac_stations_reset_station(session, station, NULL);
/* */
capwap_hash_delete(session->wlans->stations, station->address);
/* Free station reference with itemlist */
capwap_itemlist_free(station->wlanitem);
}
/* */
static unsigned long ac_wlans_item_gethash(const void* key, unsigned long hashsize) {
uint8_t* macaddress = (uint8_t*)key;
return ((unsigned long)(macaddress[3] ^ macaddress[4] ^ macaddress[5]) % AC_WLANS_STATIONS_HASH_SIZE);
}
/* */
static const void* ac_wlans_item_getkey(const void* data) {
return (const void*)((struct ac_station*)data)->address;
}
/* */
static int ac_wlans_item_cmp(const void* key1, const void* key2) {
return memcmp(key1, key2, MACADDRESS_EUI48_LENGTH);
}
/* */
void ac_wlans_init(struct ac_session_t* session) {
int i;
ASSERT(session != NULL);
ASSERT(session->wlans == NULL);
/* */
session->wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans));
memset(session->wlans, 0, sizeof(struct ac_wlans));
/* */
session->wlans->stations = capwap_hash_create(AC_WLANS_STATIONS_HASH_SIZE);
session->wlans->stations->item_gethash = ac_wlans_item_gethash;
session->wlans->stations->item_getkey = ac_wlans_item_getkey;
session->wlans->stations->item_cmp = ac_wlans_item_cmp;
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
session->wlans->devices[i].radioid = i + 1;
}
}
/* */
void ac_wlans_destroy(struct ac_session_t* session) {
int i;
struct capwap_list* items;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
/* */
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
if (session->wlans->devices[i].wlans) {
items = session->wlans->devices[i].wlans;
/* Delete WLANS */
while (items->first) {
ac_wlans_delete_bssid(session, i + 1, ((struct ac_wlan*)items->first->item)->address);
}
/* */
capwap_list_free(items);
}
}
/* */
ASSERT(session->wlans->stations->count == 0);
/* */
capwap_hash_free(session->wlans->stations);
capwap_free(session->wlans);
}
/* */
int ac_wlans_assign_bssid(struct ac_session_t* session, struct ac_wlan* wlan)
{
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(wlan != NULL);
ASSERT(wlan->device != NULL);
ASSERT(IS_VALID_RADIOID(wlan->device->radioid));
ASSERT(IS_VALID_WLANID(wlan->wlanid));
/* */
if (ac_wlans_get_bssid(session, wlan->device->radioid, wlan->address)) {
return -1;
}
/* */
wlan->session = session;
/* Create WLAN list */
if (!session->wlans->devices[wlan->device->radioid - 1].wlans) {
session->wlans->devices[wlan->device->radioid - 1].wlans = capwap_list_create();
}
/* Append WLAN to list */
capwap_itemlist_insert_after(session->wlans->devices[wlan->device->radioid - 1].wlans, NULL, wlan->wlanitem);
/* */
log_printf(LOG_INFO, "Added new wlan with radioid: %d, wlanid: %d, bssid: " MACSTR,
(int)wlan->device->radioid, (int)wlan->wlanid, MAC2STR(wlan->address));
return 0;
}
/* */
struct ac_wlan* ac_wlans_create_bssid(struct ac_device* device, uint8_t wlanid, const uint8_t* bssid, struct capwap_80211_addwlan_element* addwlan) {
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
ASSERT(device != NULL);
ASSERT(IS_VALID_WLANID(wlanid));
ASSERT(bssid != NULL);
/* */
wlanitem = capwap_itemlist_create(sizeof(struct ac_wlan));
wlan = (struct ac_wlan*)wlanitem->item;
memset(wlan, 0, sizeof(struct ac_wlan));
/* Init WLAN */
wlan->wlanitem = wlanitem;
memcpy(wlan->address, bssid, MACADDRESS_EUI48_LENGTH);
wlan->device = device;
wlan->wlanid = wlanid;
wlan->stations = capwap_list_create();
/* Set capability */
wlan->capability = addwlan->capability;
wlan->keyindex = addwlan->keyindex;
wlan->keystatus = addwlan->keystatus;
wlan->keylength = addwlan->keylength;
if (addwlan->key && (addwlan->keylength > 0)) {
wlan->key = (uint8_t*)capwap_clone(addwlan->key, wlan->keylength);
}
memcpy(wlan->grouptsc, addwlan->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH);
wlan->qos = addwlan->qos;
wlan->authmode = addwlan->authmode;
wlan->macmode = addwlan->macmode;
wlan->tunnelmode = addwlan->tunnelmode;
wlan->suppressssid = addwlan->suppressssid;
strcpy(wlan->ssid, (const char*)addwlan->ssid);
return wlan;
}
/* */
struct ac_wlan* ac_wlans_get_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (session->wlans->devices[radioid - 1].wlans) {
for (search = session->wlans->devices[radioid - 1].wlans->first; search; search = search->next) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
if (!memcmp(bssid, item->address, MACADDRESS_EUI48_LENGTH)) {
wlan = item;
break;
}
}
}
return wlan;
}
/* */
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
/* */
if (session->wlans->devices[radioid - 1].wlans) {
for (search = session->wlans->devices[radioid - 1].wlans->first; search; search = search->next) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
if (wlanid == item->wlanid) {
wlan = item;
break;
}
}
}
return wlan;
}
/* */
void ac_wlans_free_bssid(struct ac_wlan* wlan) {
ASSERT(wlan != NULL);
/* Free capability */
if (wlan->key) {
capwap_free(wlan->key);
}
/* */
capwap_list_free(wlan->stations);
capwap_itemlist_free(wlan->wlanitem);
}
/* */
void ac_wlans_delete_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (session->wlans->devices[radioid - 1].wlans) {
for (search = session->wlans->devices[radioid - 1].wlans->first; search; search = search->next) {
struct ac_wlan* wlan = (struct ac_wlan*)search->item;
if (!memcmp(bssid, wlan->address, MACADDRESS_EUI48_LENGTH)) {
/* Remove stations */
while (wlan->stations->first) {
ac_stations_destroy_station(session, (struct ac_station*)wlan->stations->first->item);
}
/* */
capwap_itemlist_remove(session->wlans->devices[radioid - 1].wlans, search);
ac_wlans_free_bssid(wlan);
break;
}
}
}
}
/* */
struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) {
struct ac_station* station;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(address != NULL);
/* Get station */
station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address);
if (station && (station->flags & AC_STATION_FLAGS_ENABLED) && ((radioid == RADIOID_ANY) || (radioid == station->wlan->device->radioid)) && (!bssid || !memcmp(bssid, station->wlan->address, MACADDRESS_EUI48_LENGTH))) {
return station;
}
return NULL;
}
/* */
struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address)
{
struct ac_wlan* wlan;
struct ac_station* authoritativestation;
struct ac_station* station = NULL;
struct ac_session_t* authoritativesession = NULL;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
ASSERT(address != NULL);
/* */
log_printf(LOG_INFO, "Create station to radioid: %d, bssid: " MACSTR ", station address: " MACSTR,
(int)radioid, MAC2STR(bssid), MAC2STR(address));
/* */
wlan = ac_wlans_get_bssid(session, radioid, bssid);
if (wlan) {
station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address);
if (!station) {
struct capwap_list_item* stationitem = capwap_itemlist_create(sizeof(struct ac_station));
station = (struct ac_station*)stationitem->item;
memset(station, 0, sizeof(struct ac_station));
/* */
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
memcpy(station->address, address, MACADDRESS_EUI48_LENGTH);
station->wlanitem = stationitem;
station->session = session;
/* */
capwap_hash_add(session->wlans->stations, (void*)station);
}
/* Set station to WLAN */
ac_stations_reset_station(session, station, wlan);
station->flags |= AC_STATION_FLAGS_ENABLED;
/* Check Authoritative Stations List */
capwap_rwlock_rdlock(&g_ac.authstationslock);
authoritativestation = (struct ac_station*)capwap_hash_search(g_ac.authstations, address);
if (authoritativestation && authoritativestation->session) {
authoritativesession = authoritativestation->session;
}
capwap_rwlock_unlock(&g_ac.authstationslock);
/* Check Authoritative Session */
if (authoritativesession != session) {
/* Update Authoritative Stations List */
capwap_rwlock_wrlock(&g_ac.authstationslock);
capwap_hash_add(g_ac.authstations, (void*)station);
capwap_rwlock_unlock(&g_ac.authstationslock);
/* Release Station from old Authoritative Session */
if (authoritativesession) {
ac_session_send_action(authoritativesession, AC_SESSION_ACTION_STATION_ROAMING, 0, (void*)address, MACADDRESS_EUI48_LENGTH);
}
}
} else {
log_printf(LOG_WARNING, "Unable to find radioid: %d, bssid: " MACSTR,
(int)radioid, MAC2STR(bssid));
}
return station;
}
/* */
void ac_stations_delete_station(struct ac_session_t* session, struct ac_station* station) {
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(station != NULL);
/* Deauthorize station */
ac_stations_deauthorize_station(session, station);
/* Destroy station reference */
ac_stations_destroy_station(session, station);
}
/* */
void ac_stations_authorize_station(struct ac_session_t* session, struct ac_station* station) {
struct ac_notify_station_configuration_ieee8011_add_station notify;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(station != NULL);
/* Active Station only if Authenticated, Associated and not Authorizated */
if ((station->flags & AC_STATION_FLAGS_AUTHENTICATED) && (station->flags & AC_STATION_FLAGS_ASSOCIATE) && !(station->flags & AC_STATION_FLAGS_AUTHORIZED)) {
memset(&notify, 0, sizeof(struct ac_notify_station_configuration_ieee8011_add_station));
notify.radioid = station->wlan->device->radioid;
memcpy(notify.address, station->address, MACADDRESS_EUI48_LENGTH);
notify.wlanid = station->wlan->wlanid;
notify.associationid = station->aid;
notify.capabilities = station->capability;
notify.supportedratescount = station->supportedratescount;
memcpy(notify.supportedrates, station->supportedrates, station->supportedratescount);
ac_session_send_action(session, AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION, 0, &notify, sizeof(struct ac_notify_station_configuration_ieee8011_add_station));
}
}
/* */
void ac_stations_deauthorize_station(struct ac_session_t* session, struct ac_station* station) {
int responselength;
uint8_t buffer[IEEE80211_MTU];
struct ieee80211_deauthentication_params ieee80211_params;
struct ac_notify_station_configuration_ieee8011_delete_station notify;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(station != NULL);
if (station->flags & AC_STATION_FLAGS_AUTHORIZED) {
/* Deauthorize station */
memset(&notify, 0, sizeof(struct ac_notify_station_configuration_ieee8011_delete_station));
notify.radioid = station->wlan->device->radioid;
memcpy(notify.address, station->address, MACADDRESS_EUI48_LENGTH);
/* */
station->flags &= ~(AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE | AC_STATION_FLAGS_AUTHORIZED);
ac_session_send_action(session, AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION, 0, &notify, sizeof(struct ac_notify_station_configuration_ieee8011_delete_station));
} else if (station->flags & AC_STATION_FLAGS_AUTHENTICATED) {
/* Create deauthentication packet */
memset(&ieee80211_params, 0, sizeof(struct ieee80211_deauthentication_params));
memcpy(ieee80211_params.bssid, station->wlan->address, MACADDRESS_EUI48_LENGTH);
memcpy(ieee80211_params.station, station->address, MACADDRESS_EUI48_LENGTH);
ieee80211_params.reasoncode = IEEE80211_REASON_PREV_AUTH_NOT_VALID;
/* */
responselength = ieee80211_create_deauthentication(buffer, IEEE80211_MTU, &ieee80211_params);
if (responselength > 0) {
station->flags &= ~(AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE);
ac_kmod_send_data(&session->sessionid, station->wlan->device->radioid, session->binding, buffer, responselength);
}
}
}
/* */
void ac_stations_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
struct ac_station* station = (struct ac_station*)context;
ASSERT(station != NULL);
if (station->idtimeout == index) {
switch (station->timeoutaction) {
case AC_STATION_TIMEOUT_ACTION_DEAUTHENTICATE: {
log_printf(LOG_WARNING, "The " MACSTR " station has not completed "
"the association in time", MAC2STR(station->address));
ac_stations_delete_station((struct ac_session_t*)param, station);
break;
}
}
}
}

View File

@ -1,127 +0,0 @@
#ifndef __AC_WLANS_HEADER__
#define __AC_WLANS_HEADER__
#include "ieee80211.h"
/* */
#define RADIOID_ANY 0
/* */
#define AC_WLANS_STATIONS_HASH_SIZE 256
#define AC_WLANS_STATIONS_KEY_SIZE MACADDRESS_EUI48_LENGTH
/* AC WLAN */
struct ac_wlan {
struct capwap_list_item* wlanitem;
struct ac_device* device;
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint8_t wlanid;
/* CAPWAP Session */
struct ac_session_t* session;
uint32_t aidbitfield[IEEE80211_AID_BITFIELD_SIZE];
/* Stations reference */
struct capwap_list* stations;
/* Capability */
uint16_t capability;
uint8_t keyindex;
uint8_t keystatus;
uint16_t keylength;
uint8_t* key;
uint8_t grouptsc[CAPWAP_ADD_WLAN_GROUPTSC_LENGTH];
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t suppressssid;
char ssid[IEEE80211_SSID_MAX_LENGTH + 1];
};
/* */
struct ac_device {
uint8_t radioid;
struct capwap_list* wlans;
/* Rates */
unsigned long supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
};
/* */
struct ac_wlans {
struct ac_device devices[RADIOID_MAX_COUNT];
/* Stations */
struct capwap_hash* stations;
};
/* */
#define AC_STATION_TIMEOUT_ASSOCIATION_COMPLETE 30000
/* */
#define AC_STATION_TIMEOUT_ACTION_DEAUTHENTICATE 0x00000001
/* */
#define AC_STATION_FLAGS_ENABLED 0x00000001
#define AC_STATION_FLAGS_AUTHENTICATED 0x00000002
#define AC_STATION_FLAGS_ASSOCIATE 0x00000004
#define AC_STATION_FLAGS_AUTHORIZED 0x00000008
/* AC Station */
struct ac_station {
uint8_t address[MACADDRESS_EUI48_LENGTH];
/* */
unsigned long flags;
/* Reference of WLAN */
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
/* Reference of Session */
struct ac_session_t* session;
/* Timers */
int timeoutaction;
unsigned long idtimeout;
/* */
uint16_t capability;
uint16_t listeninterval;
uint16_t aid;
/* */
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
/* Authentication */
uint16_t authalgorithm;
};
/* Management WLANS */
void ac_wlans_init(struct ac_session_t* session);
void ac_wlans_destroy(struct ac_session_t* session);
/* */
struct ac_wlan* ac_wlans_create_bssid(struct ac_device* device, uint8_t wlanid, const uint8_t* bssid, struct capwap_80211_addwlan_element* addwlan);
int ac_wlans_assign_bssid(struct ac_session_t* session, struct ac_wlan* wlan);
struct ac_wlan* ac_wlans_get_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid);
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid);
void ac_wlans_delete_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid);
void ac_wlans_free_bssid(struct ac_wlan* wlan);
/* Management Stations */
struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address);
struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address);
void ac_stations_delete_station(struct ac_session_t* session, struct ac_station* station);
void ac_stations_authorize_station(struct ac_session_t* session, struct ac_station* station);
void ac_stations_deauthorize_station(struct ac_session_t* session, struct ac_station* station);
/* */
void ac_stations_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
#endif /* __AC_WLANS_HEADER__ */

View File

@ -1,18 +0,0 @@
KVERSION = $(shell uname -r)
obj-m += smartcapwap.o
smartcapwap-y := \
main.o \
netlinkapp.o \
capwap.o \
capwap_private.o \
station.o \
socket.o \
iface.o
all:
make -C /lib/modules/$(KVERSION)/build M="$(PWD)" modules
clean:
make -C /lib/modules/$(KVERSION)/build M="$(PWD)" clean

View File

@ -1,789 +0,0 @@
#include "config.h"
#include <linux/module.h>
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
#include "socket.h"
#include "capwap.h"
#include "nlsmartcapwap.h"
#include "netlinkapp.h"
/* */
union capwap_addr sc_localaddr;
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
static unsigned char sc_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
static unsigned char sc_bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
/* */
static void sc_capwap_fragment_free(struct sc_capwap_fragment* fragment) {
TRACEKMOD("### sc_capwap_fragment_free\n");
/* */
list_del(&fragment->lru_list);
fragment->flags = 0;
/* Free socket buffer */
while (fragment->fragments) {
struct sk_buff* next = fragment->fragments->next;
kfree_skb(fragment->fragments);
fragment->fragments = next;
}
}
/* */
static void sc_capwap_defrag_evictor(struct sc_capwap_session* session, ktime_t now) {
ktime_t delta;
struct sc_capwap_fragment* fragment;
struct list_head* list = &session->fragments.lru_list;
TRACEKMOD("### sc_capwap_defrag_evictor\n");
/* Light check without lock */
if (!list_empty(list)) {
spin_lock(&session->fragments.lock);
/* Remove last old fragment */
if (!list_empty(list)) {
fragment = list_first_entry(list, struct sc_capwap_fragment, lru_list);
delta = ktime_sub(now, fragment->tstamp);
if ((delta.tv64 < -NSEC_PER_SEC) || (delta.tv64 > NSEC_PER_SEC)) {
TRACEKMOD("*** Expired fragment %hu (%llu %llu)\n", fragment->fragmentid, now.tv64, fragment->tstamp.tv64);
sc_capwap_fragment_free(fragment);
}
}
spin_unlock(&session->fragments.lock);
}
}
/* */
static struct sk_buff* sc_capwap_reasm(struct sc_capwap_fragment* fragment) {
int len;
int offset;
struct sk_buff* skb;
struct sk_buff* skbfrag;
struct sc_capwap_header* header;
TRACEKMOD("### sc_capwap_reasm\n");
/* */
skbfrag = fragment->fragments;
len = GET_HLEN_HEADER((struct sc_capwap_header*)skbfrag->data) * 4;
/* Create new packet */
skb = alloc_skb(len + fragment->totallength, GFP_KERNEL);
if (!skb) {
return NULL;
}
/* The first capwap header is header of reassembled packet without fragment field */
header = (struct sc_capwap_header*)skb_put(skb, len);
memcpy(header, skbfrag->data, len);
SET_FLAG_F_HEADER(header, 0);
SET_FLAG_L_HEADER(header, 0);
header->frag_id = (__be16)0;
header->frag_off = (__be16)0;
/* Copy body */
while (skbfrag) {
offset = GET_HLEN_HEADER((struct sc_capwap_header*)skbfrag->data) * 4;
len = skbfrag->len - offset;
TRACEKMOD("*** Append fragment size %d\n", len);
/* */
memcpy(skb_put(skb, len), skbfrag->data + offset, len);
skbfrag = skbfrag->next;
}
TRACEKMOD("*** Assemblate capwap data packet with total size %d\n", skb->len);
return skb;
}
/* */
static struct sk_buff* sc_capwap_defrag(struct sc_capwap_session* session, struct sk_buff* skb) {
uint16_t headersize;
uint16_t frag_id;
struct sk_buff* prev;
struct sk_buff* next;
struct sc_capwap_fragment* fragment;
struct sc_skb_capwap_cb* cb;
struct sk_buff* skb_defrag = NULL;
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
TRACEKMOD("### sc_capwap_defrag\n");
/* */
headersize = GET_HLEN_HEADER(header) * 4;
if (skb->len < headersize) {
goto error;
}
/* */
frag_id = be16_to_cpu(header->frag_id);
/* */
cb = CAPWAP_SKB_CB(skb);
cb->flags |= SKB_CAPWAP_FLAG_FRAGMENT;
cb->frag_offset = be16_to_cpu(header->frag_off);
cb->frag_length = skb->len - headersize;
/* */
spin_lock(&session->fragments.lock);
TRACEKMOD("*** Fragment info: id %hu offset %hu length %hu\n", frag_id, cb->frag_offset, cb->frag_length);
/* Get fragment */
fragment = &session->fragments.queues[frag_id % CAPWAP_FRAGMENT_QUEUE];
if ((fragment->flags & CAPWAP_FRAGMENT_ENABLE) && (fragment->fragmentid != frag_id)) {
TRACEKMOD("*** Unable defrag, queue fragment busy\n");
goto error2; /* Queue fragment busy*/
}
/* Init fragment */
if (!(fragment->flags & CAPWAP_FRAGMENT_ENABLE)) {
fragment->flags = CAPWAP_FRAGMENT_ENABLE;
fragment->fragmentid = frag_id;
fragment->fragments = NULL;
fragment->lastfragment = NULL;
fragment->recvlength = 0;
fragment->totallength = 0;
list_add_tail(&fragment->lru_list, &session->fragments.lru_list);
}
/* Search fragment position */
prev = fragment->lastfragment;
if (!prev) {
next = NULL;
} else if (CAPWAP_SKB_CB(prev)->frag_offset < cb->frag_offset) {
if ((CAPWAP_SKB_CB(prev)->frag_offset + CAPWAP_SKB_CB(prev)->frag_length) <= cb->frag_offset) {
next = NULL;
} else {
sc_capwap_fragment_free(fragment);
TRACEKMOD("*** Unable defrag, overlap error\n");
goto error2; /* Overlap error */
}
} else {
prev = NULL;
for (next = fragment->fragments; next != NULL; next = next->next) {
struct sc_skb_capwap_cb* next_cb = CAPWAP_SKB_CB(next);
if (next_cb->frag_offset == cb->frag_offset) {
TRACEKMOD("*** Unable defrag, duplicate packet\n");
goto error2; /* Duplicate packet */
} else if (next_cb->frag_offset > cb->frag_offset) {
if ((cb->frag_offset + cb->frag_length) <= next_cb->frag_offset) {
break;
} else {
sc_capwap_fragment_free(fragment);
TRACEKMOD("*** Unable defrag, overlap error\n");
goto error2; /* Overlap error */
}
}
prev = next;
}
}
/* Insert fragment */
skb->prev = NULL;
skb->next = next;
if (!next) {
fragment->lastfragment = skb;
}
if (prev) {
prev->next = skb;
} else {
fragment->fragments = skb;
}
/* Update size */
fragment->recvlength += cb->frag_length;
if (IS_FLAG_L_HEADER(header)) {
fragment->totallength = cb->frag_offset + cb->frag_length;
fragment->flags |= CAPWAP_FRAGMENT_LAST;
}
/* Check if receive all fragment */
if ((fragment->flags & CAPWAP_FRAGMENT_LAST) && (fragment->recvlength == fragment->totallength)) {
skb_defrag = sc_capwap_reasm(fragment);
/* Free fragment complete */
sc_capwap_fragment_free(fragment);
} else {
/* Update timeout */
fragment->tstamp = skb->tstamp;
TRACEKMOD("*** Fragment id %hu expire at %llu\n", frag_id, fragment->tstamp.tv64);
/* Set LRU timeout */
if (!list_is_last(&fragment->lru_list, &session->fragments.lru_list)) {
list_move_tail(&fragment->lru_list, &session->fragments.lru_list);
}
}
spin_unlock(&session->fragments.lock);
return skb_defrag;
error2:
spin_unlock(&session->fragments.lock);
error:
kfree_skb(skb);
return NULL;
}
/* */
static unsigned int sc_capwap_80211_hdrlen(__le16 fc) {
unsigned int hdrlen = 24;
TRACEKMOD("### sc_capwap_80211_hdrlen\n");
if (ieee80211_is_data(fc)) {
if (ieee80211_has_a4(fc)) {
hdrlen = 30;
}
if (ieee80211_is_data_qos(fc)) {
hdrlen += IEEE80211_QOS_CTL_LEN;
if (ieee80211_has_order(fc)) {
hdrlen += IEEE80211_HT_CTL_LEN;
}
}
} else if (ieee80211_is_ctl(fc)) {
if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) {
hdrlen = 10;
} else {
hdrlen = 16;
}
}
return hdrlen;
}
/* */
int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid) {
uint16_t hdrlen;
int head_need;
struct ieee80211_hdr hdr;
int skip_header_bytes;
uint8_t* encaps_data;
int encaps_len;
struct ethhdr* eh = (struct ethhdr*)skb->data;
uint16_t ethertype = ntohs(eh->h_proto);
TRACEKMOD("### sc_capwap_8023_to_80211\n");
/* IEEE 802.11 header */
hdrlen = 24;
hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_FROMDS);
memcpy(hdr.addr1, eh->h_dest, ETH_ALEN);
memcpy(hdr.addr2, bssid, ETH_ALEN);
memcpy(hdr.addr3, eh->h_source, ETH_ALEN);
hdr.duration_id = 0;
hdr.seq_ctrl = 0;
/* */
skip_header_bytes = ETH_HLEN;
if ((ethertype == ETH_P_AARP) || (ethertype == ETH_P_IPX)) {
encaps_data = sc_bridge_tunnel_header;
encaps_len = sizeof(sc_bridge_tunnel_header);
skip_header_bytes -= 2;
} else if (ethertype >= ETH_P_802_3_MIN) {
encaps_data = sc_rfc1042_header;
encaps_len = sizeof(sc_rfc1042_header);
skip_header_bytes -= 2;
} else {
encaps_data = NULL;
encaps_len = 0;
}
/* Remove IEEE 802.3 header */
skb_pull(skb, skip_header_bytes);
/* Check headroom */
head_need = hdrlen + encaps_len - skb_headroom(skb);
if ((head_need > 0) || skb_cloned(skb)) {
head_need = max(head_need, 0);
if (head_need) {
skb_orphan(skb);
}
TRACEKMOD("*** Expand headroom skb of: %d\n", head_need);
if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) {
return -ENOMEM;
}
skb->truesize += head_need;
}
/* Add LLC header */
if (encaps_data) {
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
}
/* Add IEEE 802.11 header */
memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
skb_reset_mac_header(skb);
return 0;
}
/* */
int sc_capwap_80211_to_8023(struct sk_buff* skb) {
struct ieee80211_hdr* hdr = (struct ieee80211_hdr*)skb->data;
uint16_t hdrlen;
uint16_t ethertype;
uint8_t* payload;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN] __aligned(2);
TRACEKMOD("### sc_capwap_80211_to_8023\n");
/* */
hdrlen = sc_capwap_80211_hdrlen(hdr->frame_control);
memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
/* */
if (!pskb_may_pull(skb, hdrlen + 8)) {
return -1;
}
/* */
payload = skb->data + hdrlen;
ethertype = (payload[6] << 8) | payload[7];
if (likely((ether_addr_equal(payload, sc_rfc1042_header) && (ethertype != ETH_P_AARP) && (ethertype != ETH_P_IPX)) || ether_addr_equal(payload, sc_bridge_tunnel_header))) {
skb_pull(skb, hdrlen + 6);
memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
} else {
struct ethhdr *ehdr;
__be16 len;
skb_pull(skb, hdrlen);
len = htons(skb->len);
ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
memcpy(ehdr->h_dest, dst, ETH_ALEN);
memcpy(ehdr->h_source, src, ETH_ALEN);
ehdr->h_proto = len;
}
return 0;
}
/* */
int sc_capwap_bind(union capwap_addr* sockaddr) {
int ret;
TRACEKMOD("### sc_capwap_bind\n");
/* */
ret = sc_socket_bind(sockaddr);
if (ret) {
return ret;
}
memcpy(&sc_localaddr, sockaddr, sizeof(union capwap_addr));
return 0;
}
/* */
void sc_capwap_initsession(struct sc_capwap_session* session) {
TRACEKMOD("### sc_capwap_initsession\n");
spin_lock_init(&session->fragmentid_lock);
/* Defragment packets */
memset(&session->fragments, 0, sizeof(struct sc_capwap_fragment_queue));
INIT_LIST_HEAD(&session->fragments.lru_list);
spin_lock_init(&session->fragments.lock);
}
/* */
void sc_capwap_freesession(struct sc_capwap_session* session) {
struct sc_capwap_fragment* temp;
struct sc_capwap_fragment* fragment;
TRACEKMOD("### sc_capwap_freesession\n");
/* Free socket buffers */
list_for_each_entry_safe(fragment, temp, &session->fragments.lru_list, lru_list) {
sc_capwap_fragment_free(fragment);
}
}
/* */
uint16_t sc_capwap_newfragmentid(struct sc_capwap_session* session) {
uint16_t fragmentid;
TRACEKMOD("### sc_capwap_newfragmentid\n");
spin_lock(&session->fragmentid_lock);
fragmentid = session->fragmentid++;
spin_unlock(&session->fragmentid_lock);
return fragmentid;
}
/* */
int sc_capwap_createkeepalive(struct sc_capwap_sessionid_element* sessionid, uint8_t* buffer, int size) {
int length;
struct sc_capwap_header* header;
struct sc_capwap_data_message* dataheader;
struct sc_capwap_message_element* msgelement;
TRACEKMOD("### sc_capwap_createkeepalive\n");
/* */
if (size < CAPWAP_KEEP_ALIVE_MAX_SIZE) {
return -ENOMEM;
}
/* Preamble CAPWAP header */
header = (struct sc_capwap_header*)buffer;
length = sizeof(struct sc_capwap_header);
buffer += sizeof(struct sc_capwap_header);
memset(header, 0, sizeof(struct sc_capwap_header));
SET_VERSION_HEADER(header, CAPWAP_PROTOCOL_VERSION);
SET_TYPE_HEADER(header, CAPWAP_PREAMBLE_HEADER);
SET_HLEN_HEADER(header, sizeof(struct sc_capwap_header) / 4);
SET_WBID_HEADER(header, CAPWAP_WIRELESS_BINDING_IEEE80211);
SET_FLAG_K_HEADER(header, 1);
/* CAPWAP Data header */
dataheader = (struct sc_capwap_data_message*)buffer;
length += sizeof(struct sc_capwap_data_message);
buffer += sizeof(struct sc_capwap_data_message);
dataheader->length = cpu_to_be16(sizeof(struct sc_capwap_data_message) + sizeof(struct sc_capwap_message_element) + sizeof(struct sc_capwap_sessionid_element));
/* CAPWAP Keep-Alive Message Element */
msgelement = (struct sc_capwap_message_element*)buffer;
length += sizeof(struct sc_capwap_message_element);
buffer += sizeof(struct sc_capwap_message_element);
msgelement->type = cpu_to_be16(CAPWAP_ELEMENT_SESSIONID);
msgelement->length = cpu_to_be16(sizeof(struct sc_capwap_sessionid_element));
/* Session ID */
memcpy(buffer, sessionid, sizeof(struct sc_capwap_sessionid_element));
length += sizeof(struct sc_capwap_sessionid_element);
return length;
}
/* */
int sc_capwap_parsingpacket(struct sc_capwap_session* session, const union capwap_addr* sockaddr, struct sk_buff* skb) {
int length;
uint16_t headersize;
struct sc_capwap_data_message* dataheader;
struct sc_capwap_message_element* message;
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
TRACEKMOD("### sc_capwap_parsingpacket\n");
/* Linearize socket buffer */
if (skb_linearize(skb)) {
TRACEKMOD("*** Unable to linearize packet\n");
return -EINVAL;
}
/* Check header */
if (skb->len < sizeof(struct sc_capwap_header)) {
TRACEKMOD("*** Invalid capwap header length\n");
return -EINVAL;
} else if (GET_VERSION_HEADER(header) != CAPWAP_PROTOCOL_VERSION) {
TRACEKMOD("*** Invalid capwap header version\n");
return -EINVAL;
} else if (GET_TYPE_HEADER(header) != CAPWAP_PREAMBLE_HEADER) {
TRACEKMOD("*** Packet is encrypted\n");
return -EINVAL; /* Accept only plain packet */
}
/* */
if (IS_FLAG_K_HEADER(header)) {
/* Keep alive can not fragment */
if (IS_FLAG_F_HEADER(header)) {
TRACEKMOD("*** Keep alive can not fragment\n");
return -EINVAL;
}
/* */
length = skb->len;
headersize = GET_HLEN_HEADER(header) * 4;
if (length < (headersize + sizeof(struct sc_capwap_data_message))) {
TRACEKMOD("*** Invalid capwap data header length\n");
return -EINVAL;
}
/* Data message */
length -= headersize;
dataheader = (struct sc_capwap_data_message*)(((uint8_t*)header) + headersize);
headersize = ntohs(dataheader->length);
if (length < headersize) {
TRACEKMOD("*** Capwap data header length mismatch\n");
return -EINVAL;
}
/* Message elements */
headersize -= sizeof(struct sc_capwap_data_message);
message = (struct sc_capwap_message_element*)(((uint8_t*)dataheader) + sizeof(struct sc_capwap_data_message));
while (headersize > 0) {
uint16_t msglength = ntohs(message->length);
if (headersize < (msglength + sizeof(struct sc_capwap_message_element))) {
TRACEKMOD("*** Invalid capwap message element length\n");
return -EINVAL;
}
/* */
if ((ntohs(message->type) == CAPWAP_ELEMENT_SESSIONID) && (msglength == sizeof(struct sc_capwap_sessionid_element))) {
struct sc_capwap_sessionid_element* sessionid = (struct sc_capwap_sessionid_element*)(((uint8_t*)message) + sizeof(struct sc_capwap_message_element));
if (!session) {
session = sc_capwap_recvunknownkeepalive(sockaddr, sessionid);
if (!session) {
TRACEKMOD("*** Receive unknown keep alive without valid session\n");
return -EINVAL;
}
} else if (memcmp(&session->sessionid, sessionid, sizeof(struct sc_capwap_sessionid_element))) {
TRACEKMOD("*** Session id mismatch\n");
return -EINVAL;
}
/* Session found */
sc_netlink_notify_recv_keepalive(sockaddr, sessionid);
/* Parsing complete */
kfree_skb(skb);
return 0;
}
/* Next message element */
msglength += sizeof(struct sc_capwap_message_element);
message = (struct sc_capwap_message_element*)(((uint8_t*)message) + msglength);
headersize -= msglength;
}
} else if (session) {
if (!skb->tstamp.tv64) {
skb->tstamp = ktime_get();
}
/* Cleaning old fragments */
sc_capwap_defrag_evictor(session, skb->tstamp);
/* */
if (IS_FLAG_F_HEADER(header)) {
skb = sc_capwap_defrag(session, skb);
if (!skb) {
return 0;
}
/* Get new header info */
header = (struct sc_capwap_header*)skb->data;
}
/* Parsing data/management packet */
if (!IS_FLAG_T_HEADER(header)) {
sc_capwap_parsingdatapacket(session, skb);
} else if (GET_WBID_HEADER(header) == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct ieee80211_hdr* hdr = (struct ieee80211_hdr*)(skb->data + GET_HLEN_HEADER(header) * 4);
if (ieee80211_is_data_present(hdr->frame_control)) {
sc_capwap_parsingdatapacket(session, skb);
} else if (ieee80211_is_mgmt(hdr->frame_control) || ieee80211_is_ctl(hdr->frame_control)) {
sc_capwap_parsingmgmtpacket(session, skb);
}
}
return 0;
}
return -EINVAL;
}
/* */
int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, uint8_t binding, struct sk_buff* skb, uint32_t flags, struct sc_capwap_radio_addr* radioaddr, int radioaddrlength, struct sc_capwap_wireless_information* winfo, int winfolength) {
int err;
int size;
int length;
int reserve;
int headroom;
int requestfragment;
__be16 fragmentid = 0;
int fragmentoffset = 0;
struct sc_capwap_header* header;
struct sk_buff* clone = NULL;
int packetlength = skb->len;
TRACEKMOD("### sc_capwap_forwarddata\n");
/* Check headroom */
headroom = skb_headroom(skb);
reserve = sizeof(struct sc_capwap_header) + radioaddrlength + winfolength;
if (skb_is_nonlinear(skb) || (headroom < reserve)) {
TRACEKMOD("*** Copy socket buffer and expand headroom of: %d\n", (reserve - headroom));
clone = skb_copy_expand(skb, max(headroom, reserve), skb_tailroom(skb), GFP_KERNEL);
if (!clone) {
TRACEKMOD("*** Unable to copy socket buffer\n");
return -ENOMEM;
}
skb = clone;
}
/* Check MTU */
requestfragment = (((packetlength + reserve) > session->mtu) ? 1 : 0);
if (requestfragment) {
fragmentid = cpu_to_be16(sc_capwap_newfragmentid(session));
}
/* */
header = (struct sc_capwap_header*)skb_push(skb, sizeof(struct sc_capwap_header) + radioaddrlength + winfolength);
while (packetlength > 0) {
memset(header, 0, sizeof(struct sc_capwap_header));
SET_VERSION_HEADER(header, CAPWAP_PROTOCOL_VERSION);
SET_TYPE_HEADER(header, CAPWAP_PREAMBLE_HEADER);
SET_WBID_HEADER(header, binding);
SET_RID_HEADER(header, radioid);
SET_FLAG_T_HEADER(header, ((flags & NLSMARTCAPWAP_FLAGS_TUNNEL_8023) ? 0 : 1));
if (!fragmentoffset) {
uint8_t* headeroption = (uint8_t*)header + sizeof(struct sc_capwap_header);
if (radioaddr) {
SET_FLAG_M_HEADER(header, 1);
memcpy(headeroption, radioaddr, radioaddrlength);
headeroption += radioaddrlength;
}
if (winfo) {
SET_FLAG_W_HEADER(header, 1);
memcpy(headeroption, winfo, winfolength);
headeroption += winfolength;
}
size = sizeof(struct sc_capwap_header) + radioaddrlength + winfolength;
SET_HLEN_HEADER(header, size / 4);
} else {
size = sizeof(struct sc_capwap_header);
SET_HLEN_HEADER(header, size / 4);
}
/* Calculate body size */
length = session->mtu - size;
if (packetlength <= length) {
length = packetlength;
} else if (requestfragment) {
length -= length % 8; /* Capwap fragment size is module 8 */
} else {
break;
}
/* Fragment options */
if (requestfragment) {
SET_FLAG_F_HEADER(header, 1);
if (packetlength == length) {
SET_FLAG_L_HEADER(header, 1);
}
header->frag_id = fragmentid;
header->frag_off = cpu_to_be16(fragmentoffset);
}
/* Send packet */
err = sc_socket_send(SOCKET_UDP, (uint8_t*)header, (size + length), &session->peeraddr);
TRACEKMOD("*** Send packet result: %d\n", err);
if (err < 0) {
break;
}
/* */
header = (struct sc_capwap_header*)(((uint8_t*)header + size + length) - sizeof(struct sc_capwap_header));
fragmentoffset += length;
packetlength -= length;
}
if (clone) {
kfree_skb(clone);
}
return (!packetlength ? 0 : -EIO);
}
/* */
void sc_capwap_sessionid_printf(const struct sc_capwap_sessionid_element* sessionid, char* string) {
int i;
char* pos = string;
for (i = 0; i < 16; i++) {
snprintf(pos, 3, "%02x", sessionid->id[i]);
pos += 2;
}
*pos = 0;
}
/* */
struct sc_capwap_radio_addr* sc_capwap_setradiomacaddress(uint8_t* buffer, int size, uint8_t* bssid) {
struct sc_capwap_radio_addr* radioaddr;
struct sc_capwap_macaddress_eui48* addr;
TRACEKMOD("### sc_capwap_setwirelessinformation\n");
memset(buffer, 0, size);
radioaddr = (struct sc_capwap_radio_addr*)buffer;
radioaddr->length = MACADDRESS_EUI48_LENGTH;
addr = (struct sc_capwap_macaddress_eui48*)radioaddr->addr;
memcpy(addr->addr, bssid, MACADDRESS_EUI48_LENGTH);
return radioaddr;
}
/* */
struct sc_capwap_wireless_information* sc_capwap_setwinfo_frameinfo(uint8_t* buffer, int size, uint8_t rssi, uint8_t snr, uint16_t rate) {
struct sc_capwap_wireless_information* winfo;
struct sc_capwap_ieee80211_frame_info* frameinfo;
TRACEKMOD("### sc_capwap_setwinfo_frameinfo\n");
memset(buffer, 0, size);
winfo = (struct sc_capwap_wireless_information*)buffer;
winfo->length = sizeof(struct sc_capwap_ieee80211_frame_info);
frameinfo = (struct sc_capwap_ieee80211_frame_info*)(buffer + sizeof(struct sc_capwap_wireless_information));
frameinfo->rssi = rssi;
frameinfo->snr = snr;
frameinfo->rate = cpu_to_be16(rate);
return winfo;
}
/* */
struct sc_capwap_wireless_information* sc_capwap_setwinfo_destwlans(uint8_t* buffer, int size, uint16_t wlanidbitmap) {
struct sc_capwap_wireless_information* winfo;
struct sc_capwap_destination_wlans* destwlans;
TRACEKMOD("### sc_capwap_setwinfo_destwlans\n");
memset(buffer, 0, size);
winfo = (struct sc_capwap_wireless_information*)buffer;
winfo->length = sizeof(struct sc_capwap_destination_wlans);
destwlans = (struct sc_capwap_destination_wlans*)(buffer + sizeof(struct sc_capwap_wireless_information));
destwlans->wlanidbitmap = cpu_to_be16(wlanidbitmap);
return winfo;
}

View File

@ -1,124 +0,0 @@
#ifndef __KMOD_CAPWAP_HEADER__
#define __KMOD_CAPWAP_HEADER__
#include "capwap_rfc.h"
#include "socket.h"
/* */
#define MAX_MTU 9000
#define DEFAULT_MTU 1450
#define MIN_MTU 500
#define IEEE80211_MTU 7981
/* */
#define CAPWAP_FRAGMENT_QUEUE 16
/* */
#define CAPWAP_FRAGMENT_ENABLE 0x0001
#define CAPWAP_FRAGMENT_LRUQUEUE 0x0002
#define CAPWAP_FRAGMENT_LAST 0x0004
/* */
#define SKB_CAPWAP_FLAG_FROM_DATA_CHANNEL 0x0001
#define SKB_CAPWAP_FLAG_FROM_USER_SPACE 0x0002
#define SKB_CAPWAP_FLAG_FROM_AC_TAP 0x0004
#define SKB_CAPWAP_FLAG_FROM_IEEE80211 0x0008
#define SKB_CAPWAP_FLAG_SESSIONID 0x0100
#define SKB_CAPWAP_FLAG_RADIOID 0x0200
#define SKB_CAPWAP_FLAG_BINDING 0x0400
#define SKB_CAPWAP_FLAG_WIRELESSINFORMATION 0x0800
#define SKB_CAPWAP_FLAG_FRAGMENT 0x1000
struct sc_skb_capwap_cb {
uint16_t flags;
/* Session ID */
struct sc_capwap_sessionid_element sessionid;
/* Capwap information */
uint8_t radioid;
uint8_t binding;
/* Wireless Information */
uint8_t winfo_rssi;
uint8_t winfo_snr;
uint16_t winfo_rate;
/* Fragment */
uint16_t frag_offset;
uint16_t frag_length;
};
#define CAPWAP_SKB_CB(skb) ((struct sc_skb_capwap_cb*)((skb)->cb))
/* */
struct sc_capwap_fragment {
struct list_head lru_list;
uint8_t flags;
ktime_t tstamp;
uint16_t fragmentid;
struct sk_buff* fragments;
struct sk_buff* lastfragment;
int recvlength;
int totallength;
};
/* */
struct sc_capwap_fragment_queue {
spinlock_t lock;
struct list_head lru_list;
struct sc_capwap_fragment queues[CAPWAP_FRAGMENT_QUEUE];
};
/* */
struct sc_capwap_session {
uint16_t mtu;
union capwap_addr peeraddr;
struct sc_capwap_sessionid_element sessionid;
uint16_t fragmentid;
spinlock_t fragmentid_lock;
struct sc_capwap_fragment_queue fragments;
};
/* */
extern union capwap_addr sc_localaddr;
/* Dipendent implementation function */
void sc_capwap_recvpacket(struct sk_buff* skb);
struct sc_capwap_session* sc_capwap_recvunknownkeepalive(const union capwap_addr* sockaddr, const struct sc_capwap_sessionid_element* sessionid);
void sc_capwap_parsingdatapacket(struct sc_capwap_session* session, struct sk_buff* skb);
void sc_capwap_parsingmgmtpacket(struct sc_capwap_session* session, struct sk_buff* skb);
/* Indipendent implementation function */
int sc_capwap_bind(union capwap_addr* sockaddr);
void sc_capwap_initsession(struct sc_capwap_session* session);
void sc_capwap_freesession(struct sc_capwap_session* session);
uint16_t sc_capwap_newfragmentid(struct sc_capwap_session* session);
int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid);
int sc_capwap_80211_to_8023(struct sk_buff* skb);
void sc_capwap_sessionid_printf(const struct sc_capwap_sessionid_element* sessionid, char* string);
int sc_capwap_createkeepalive(struct sc_capwap_sessionid_element* sessionid, uint8_t* buffer, int size);
int sc_capwap_parsingpacket(struct sc_capwap_session* session, const union capwap_addr* sockaddr, struct sk_buff* skb);
struct sc_capwap_radio_addr* sc_capwap_setradiomacaddress(uint8_t* buffer, int size, uint8_t* bssid);
struct sc_capwap_wireless_information* sc_capwap_setwinfo_frameinfo(uint8_t* buffer, int size, uint8_t rssi, uint8_t snr, uint16_t rate);
struct sc_capwap_wireless_information* sc_capwap_setwinfo_destwlans(uint8_t* buffer, int size, uint16_t wlanidbitmap);
int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, uint8_t binding, struct sk_buff* skb, uint32_t flags, struct sc_capwap_radio_addr* radioaddr, int radioaddrlength, struct sc_capwap_wireless_information* winfo, int winfolength);
/* Private funciotn */
#include "capwap_private.h"
#endif /* __KMOD_CAPWAP_HEADER__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +0,0 @@
#ifndef __KMOD_CAPWAP_PRIVATE_HEADER__
#define __KMOD_CAPWAP_PRIVATE_HEADER__
/* */
struct sc_capwap_wlan {
int used;
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint8_t macmode;
uint8_t tunnelmode;
};
/* */
struct sc_capwap_session_priv {
struct sc_capwap_session session;
struct list_head list;
struct sc_capwap_session_priv* __rcu next_ipaddr;
struct sc_capwap_session_priv* __rcu next_sessionid;
struct list_head list_stations;
struct list_head list_connections;
/* */
int isolation;
uint8_t binding;
struct sc_capwap_wlan wlans[CAPWAP_RADIOID_MAX_COUNT][CAPWAP_WLANID_MAX_COUNT];
};
/* */
struct sc_capwap_workthread {
struct task_struct* thread;
struct sk_buff_head queue;
wait_queue_head_t waitevent;
};
/* */
int sc_capwap_init(void);
void sc_capwap_close(void);
/* */
void sc_capwap_update_lock(void);
void sc_capwap_update_unlock(void);
#ifdef CONFIG_PROVE_LOCKING
int sc_capwap_update_lock_is_locked(void);
#else
static inline int sc_capwap_update_lock_is_locked(void) { return 1; }
#endif
/* */
int sc_capwap_sendkeepalive(const struct sc_capwap_sessionid_element* sessionid);
/* */
int sc_capwap_newsession(const struct sc_capwap_sessionid_element* sessionid, uint8_t binding, uint16_t mtu);
int sc_capwap_deletesession(const struct sc_capwap_sessionid_element* sessionid);
/* */
int sc_capwap_addwlan(const struct sc_capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, uint8_t macmode, uint8_t tunnelmode);
int sc_capwap_removewlan(const struct sc_capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t wlanid);
/* */
int sc_capwap_authstation(const struct sc_capwap_sessionid_element* sessionid, const uint8_t* address, uint32_t ifindex, uint8_t radioid, uint8_t wlanid, uint16_t vlan);
int sc_capwap_deauthstation(const struct sc_capwap_sessionid_element* sessionid, const uint8_t* address);
#endif /* __KMOD_CAPWAP_PRIVATE_HEADER__ */

View File

@ -1,13 +0,0 @@
#ifndef __KMOD_CONFIG_HEADER__
#define __KMOD_CONFIG_HEADER__
#define DEBUGKMOD 1
#ifdef DEBUGKMOD
#define TRACEKMOD(s, args...) printk("(%d) " s, smp_processor_id(), ##args)
#else
#define TRACEKMOD(s, args...)
#endif
#endif /* __KMOD_CONFIG_HEADER__ */

View File

@ -1,300 +0,0 @@
#include "config.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/smp.h>
#include "iface.h"
#include "station.h"
#include "capwap.h"
/* */
#define CAPWAP_IFACE_COUNT 8
#define CAPWAP_IFACE_HASH(x) ((x) % CAPWAP_IFACE_COUNT)
static LIST_HEAD(sc_iface_list);
static struct sc_netdev_priv* __rcu sc_iface_hash[CAPWAP_IFACE_COUNT];
/* */
static void sc_iface_netdev_uninit(struct net_device* dev) {
struct sc_netdev_priv* search;
struct sc_capwap_station* temp;
struct sc_capwap_station* station;
int hash = CAPWAP_IFACE_HASH(dev->ifindex);
struct sc_netdev_priv* priv = (struct sc_netdev_priv*)netdev_priv(dev);
TRACEKMOD("### sc_iface_netdev_uninit\n");
sc_capwap_update_lock();
/* Close stations */
list_for_each_entry_safe(station, temp, &priv->list_stations, list_dev) {
sc_stations_releaseconnection(station);
sc_stations_free(station);
}
/* */
if (!list_empty(&priv->list_stations)) {
TRACEKMOD("*** Bug: the list stations of interface is not empty\n");
}
if (!list_empty(&priv->list_connections)) {
TRACEKMOD("*** Bug: the list connections of interface is not empty\n");
}
/* Remove interface from hash */
search = rcu_dereference_protected(sc_iface_hash[hash], sc_capwap_update_lock_is_locked());
if (search) {
if (priv == search) {
netif_tx_lock_bh(dev);
netif_carrier_off(dev);
netif_tx_unlock_bh(dev);
rcu_assign_pointer(sc_iface_hash[hash], priv->next);
list_del_rcu(&priv->list);
synchronize_net();
dev_put(dev);
} else {
while (rcu_access_pointer(search->next) && (rcu_access_pointer(search->next) != priv)) {
search = rcu_dereference_protected(search->next, sc_capwap_update_lock_is_locked());
}
if (rcu_access_pointer(search->next)) {
netif_tx_lock_bh(dev);
netif_carrier_off(dev);
netif_tx_unlock_bh(dev);
rcu_assign_pointer(search->next, priv->next);
list_del_rcu(&priv->list);
synchronize_net();
dev_put(dev);
}
}
}
sc_capwap_update_unlock();
}
/* */
static int sc_iface_netdev_open(struct net_device* dev) {
TRACEKMOD("### sc_iface_netdev_open\n");
netif_start_queue(dev);
return 0;
}
/* */
static int sc_iface_netdev_stop(struct net_device* dev) {
TRACEKMOD("### sc_iface_netdev_stop\n");
netif_stop_queue(dev);
return 0;
}
/* */
static int sc_iface_netdev_tx(struct sk_buff* skb, struct net_device* dev) {
struct sc_netdev_priv* priv = (struct sc_netdev_priv*)netdev_priv(dev);
TRACEKMOD("### sc_iface_netdev_tx %d\n", smp_processor_id());
if (dev->flags & IFF_UP) {
/* Ignore 802.1ad */
if (skb->vlan_proto == htons(ETH_P_8021AD) || (eth_hdr(skb)->h_proto == htons(ETH_P_8021AD))) {
goto drop;
}
/* */
spin_lock(&priv->lock);
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
spin_unlock(&priv->lock);
/* */
CAPWAP_SKB_CB(skb)->flags = SKB_CAPWAP_FLAG_FROM_AC_TAP;
sc_capwap_recvpacket(skb);
} else {
goto drop;
}
return 0;
drop:
/* Drop packet */
kfree_skb(skb);
/* */
spin_lock(&priv->lock);
dev->stats.rx_dropped++;
spin_unlock(&priv->lock);
return 0;
}
/* */
static int sc_iface_netdev_change_mtu(struct net_device* dev, int new_mtu) {
TRACEKMOD("### sc_iface_netdev_change_mtu\n");
/* TODO */
return 0;
}
/* */
static void sc_iface_netdev_setup(struct net_device* dev) {
struct sc_netdev_priv* devpriv = (struct sc_netdev_priv*)netdev_priv(dev);
TRACEKMOD("### sc_iface_netdev_setup\n");
/* */
memset(devpriv, 0, sizeof(struct sc_netdev_priv));
devpriv->dev = dev;
spin_lock_init(&devpriv->lock);
INIT_LIST_HEAD(&devpriv->list_stations);
INIT_LIST_HEAD(&devpriv->list_connections);
}
/* */
static const struct net_device_ops capwap_netdev_ops = {
.ndo_uninit = sc_iface_netdev_uninit,
.ndo_open = sc_iface_netdev_open,
.ndo_stop = sc_iface_netdev_stop,
.ndo_start_xmit = sc_iface_netdev_tx,
.ndo_change_mtu = sc_iface_netdev_change_mtu,
};
/* */
int sc_iface_create(const char* ifname, uint16_t mtu) {
int err;
int hash;
struct net_device* dev;
struct sc_netdev_priv* priv;
TRACEKMOD("### sc_iface_create\n");
/* Create interface */
dev = alloc_netdev(sizeof(struct sc_netdev_priv), ifname, sc_iface_netdev_setup);
if (!dev) {
return -ENOMEM;
}
/* */
priv = (struct sc_netdev_priv*)netdev_priv(dev);
dev->netdev_ops = &capwap_netdev_ops;
ether_setup(dev);
eth_hw_addr_random(dev);
dev->mtu = mtu;
dev->hw_features = NETIF_F_HW_CSUM;
dev->features = dev->hw_features;
/* */
err = register_netdev(dev);
if (err) {
free_netdev(dev);
return err;
}
/* */
hash = CAPWAP_IFACE_HASH(dev->ifindex);
/* */
sc_capwap_update_lock();
list_add_rcu(&priv->list, &sc_iface_list);
priv->next = rcu_dereference_protected(sc_iface_hash[hash], sc_capwap_update_lock_is_locked());
rcu_assign_pointer(sc_iface_hash[hash], priv);
dev_hold(dev);
sc_capwap_update_unlock();
/* Enable carrier */
netif_tx_lock_bh(dev);
netif_carrier_on(dev);
netif_tx_unlock_bh(dev);
return dev->ifindex;
}
/* */
int sc_iface_delete(uint32_t ifindex) {
struct sc_netdev_priv* priv;
struct net_device* dev = NULL;
TRACEKMOD("### sc_iface_delete\n");
rcu_read_lock();
/* Search device */
priv = sc_iface_search(ifindex);
if (priv) {
dev = priv->dev;
}
rcu_read_unlock();
/* */
if (!dev) {
return -ENOENT;
}
/* Unregister device */
unregister_netdev(dev);
free_netdev(dev);
return 0;
}
/* */
struct sc_netdev_priv* sc_iface_search(uint32_t ifindex) {
struct sc_netdev_priv* priv;
TRACEKMOD("### sc_iface_search\n");
priv = rcu_dereference_check(sc_iface_hash[CAPWAP_IFACE_HASH(ifindex)], lockdep_is_held(&sc_iface_mutex));
while (priv) {
if (priv->dev->ifindex == ifindex) {
break;
}
/* */
priv = rcu_dereference_check(priv->next, lockdep_is_held(&sc_iface_mutex));
}
return priv;
}
/* */
void sc_iface_closeall(void) {
struct sc_netdev_priv* priv;
TRACEKMOD("### sc_iface_closeall\n");
for (;;) {
struct net_device* dev = NULL;
rcu_read_lock();
/* Get device */
priv = list_first_or_null_rcu(&sc_iface_list, struct sc_netdev_priv, list);
if (priv) {
dev = priv->dev;
}
rcu_read_unlock();
/* */
if (!dev) {
break;
}
/* Unregister device */
unregister_netdev(dev);
free_netdev(dev);
}
}

View File

@ -1,27 +0,0 @@
#ifndef __KMOD_AC_IFACE_HEADER__
#define __KMOD_AC_IFACE_HEADER__
/* */
struct sc_netdev_priv {
struct list_head list;
struct net_device* dev;
spinlock_t lock;
struct list_head list_stations;
struct list_head list_connections;
struct sc_netdev_priv* __rcu next;
};
/* */
int sc_iface_create(const char* ifname, uint16_t mtu);
int sc_iface_delete(uint32_t ifindex);
/* */
struct sc_netdev_priv* sc_iface_search(uint32_t ifindex);
/* */
void sc_iface_closeall(void);
#endif /* __KMOD_AC_IFACE_HEADER__ */

View File

@ -1,32 +0,0 @@
#include "config.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include "netlinkapp.h"
/* */
static int __init smartcapwap_ac_init(void) {
int ret;
TRACEKMOD("### smartcapwap_ac_init\n");
/* Initialize netlink */
ret = sc_netlink_init();
if (ret) {
return ret;
}
return ret;
}
module_init(smartcapwap_ac_init);
/* */
static void __exit smartcapwap_ac_exit(void) {
TRACEKMOD("### smartcapwap_ac_exit\n");
sc_netlink_exit();
}
module_exit(smartcapwap_ac_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Massimo Vellucci <vemax78@gmail.com>");
MODULE_DESCRIPTION("SmartCAPWAP AC Data Channel Module");

View File

@ -1,611 +0,0 @@
#include "config.h"
#include <linux/module.h>
#include <linux/version.h>
#include <linux/version.h>
#include <linux/socket.h>
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
#include <net/genetlink.h>
#include <linux/rcupdate.h>
#include <linux/err.h>
#include <net/mac80211.h>
#include <linux/ieee80211.h>
#include "nlsmartcapwap.h"
#include "netlinkapp.h"
#include "capwap.h"
#include "iface.h"
/* */
static u32 sc_netlink_usermodeid;
/* */
static int sc_netlink_pre_doit(struct genl_ops* ops, struct sk_buff* skb, struct genl_info* info);
static void sc_netlink_post_doit(struct genl_ops* ops, struct sk_buff* skb, struct genl_info* info);
/* Netlink Family */
static struct genl_family sc_netlink_family = {
.id = GENL_ID_GENERATE,
.name = NLSMARTCAPWAP_GENL_NAME,
.hdrsize = 0,
.version = 1,
.maxattr = NLSMARTCAPWAP_ATTR_MAX,
.netnsok = true,
.pre_doit = sc_netlink_pre_doit,
.post_doit = sc_netlink_post_doit,
};
/* */
static int sc_netlink_pre_doit(struct genl_ops* ops, struct sk_buff* skb, struct genl_info* info) {
TRACEKMOD("### sc_netlink_pre_doit: %d\n", (int)ops->cmd);
return 0;
}
/* */
static void sc_netlink_post_doit(struct genl_ops* ops, struct sk_buff* skb, struct genl_info* info) {
TRACEKMOD("### sc_netlink_post_doit: %d\n", (int)ops->cmd);
}
/* */
static int sc_netlink_bind(struct sk_buff* skb, struct genl_info* info) {
union capwap_addr sockaddr;
TRACEKMOD("### sc_netlink_bind\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Get bind address */
if (!info->attrs[NLSMARTCAPWAP_ATTR_ADDRESS]) {
return -EINVAL;
}
memcpy(&sockaddr.ss, nla_data(info->attrs[NLSMARTCAPWAP_ATTR_ADDRESS]), sizeof(struct sockaddr_storage));
if ((sockaddr.ss.ss_family != AF_INET) && (sockaddr.ss.ss_family != AF_INET6)) {
return -EINVAL;
}
/* Bind socket */
return sc_capwap_bind(&sockaddr);
}
/* */
static int sc_netlink_send_keepalive(struct sk_buff* skb, struct genl_info* info) {
TRACEKMOD("### sc_netlink_send_keepalive\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check Session ID */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]) {
return -EINVAL;
}
/* Send keep-alive packet */
return sc_capwap_sendkeepalive((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]));
}
/* */
static int sc_netlink_send_data(struct sk_buff* skb, struct genl_info* info) {
int length;
struct sk_buff* skbdata;
struct sc_skb_capwap_cb* cb;
TRACEKMOD("### sc_netlink_send_data\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID] || !info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] || !info->attrs[NLSMARTCAPWAP_ATTR_BINDING] || !info->attrs[NLSMARTCAPWAP_ATTR_DATA_FRAME]) {
return -EINVAL;
}
/* Create socket buffer */
length = nla_len(info->attrs[NLSMARTCAPWAP_ATTR_DATA_FRAME]);
skbdata = alloc_skb(length + CAPWAP_HEADER_MAX_LENGTH, GFP_KERNEL);
if (!skbdata) {
return -ENOMEM;
}
/* Reserve space for Capwap Header */
skb_reserve(skbdata, CAPWAP_HEADER_MAX_LENGTH);
/* Copy data into socket buffer */
memcpy(skb_put(skbdata, length), nla_data(info->attrs[NLSMARTCAPWAP_ATTR_DATA_FRAME]), length);
/* */
cb = CAPWAP_SKB_CB(skbdata);
cb->flags = SKB_CAPWAP_FLAG_FROM_USER_SPACE | SKB_CAPWAP_FLAG_SESSIONID | SKB_CAPWAP_FLAG_RADIOID | SKB_CAPWAP_FLAG_BINDING;
memcpy(&cb->sessionid, nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]), sizeof(struct sc_capwap_sessionid_element));
cb->radioid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_RADIOID]);
cb->binding = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_BINDING]);
/* */
sc_capwap_recvpacket(skbdata);
return 0;
}
/* */
static int sc_netlink_new_session(struct sk_buff* skb, struct genl_info* info) {
uint16_t mtu = DEFAULT_MTU;
TRACEKMOD("### sc_netlink_new_session\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check Session ID & Binding */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID] || !info->attrs[NLSMARTCAPWAP_ATTR_BINDING]) {
return -EINVAL;
}
/* Get MTU */
if (info->attrs[NLSMARTCAPWAP_ATTR_MTU]) {
mtu = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_MTU]);
if ((mtu < MIN_MTU) || (mtu > MAX_MTU)) {
return -EINVAL;
}
}
/* New session */
return sc_capwap_newsession((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]), nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_BINDING]), mtu);
}
/* */
static int sc_netlink_delete_session(struct sk_buff* skb, struct genl_info* info) {
TRACEKMOD("### sc_netlink_delete_session\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check Session ID */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]) {
return -EINVAL;
}
/* Delete session */
return sc_capwap_deletesession((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]));
}
/* */
static int sc_netlink_add_wlan(struct sk_buff* skb, struct genl_info* info) {
uint8_t radioid;
uint8_t wlanid;
TRACEKMOD("### sc_netlink_add_wlan\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check params */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID] || !info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] || !info->attrs[NLSMARTCAPWAP_ATTR_WLANID] || !info->attrs[NLSMARTCAPWAP_ATTR_MACADDRESS] || !info->attrs[NLSMARTCAPWAP_ATTR_MACMODE] || !info->attrs[NLSMARTCAPWAP_ATTR_TUNNELMODE]) {
return -EINVAL;
}
/* */
radioid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_RADIOID]);
wlanid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]);
if (!IS_VALID_RADIOID(radioid) || !IS_VALID_WLANID(wlanid)) {
return -EINVAL;
}
/* */
return sc_capwap_addwlan((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]), radioid, wlanid, (uint8_t*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_MACADDRESS]), nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_MACMODE]), nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_TUNNELMODE]));
}
/* */
static int sc_netlink_remove_wlan(struct sk_buff* skb, struct genl_info* info) {
uint8_t radioid;
uint8_t wlanid;
TRACEKMOD("### sc_netlink_remove_wlan\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check Session ID */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID] || !info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] || !info->attrs[NLSMARTCAPWAP_ATTR_WLANID]) {
return -EINVAL;
}
/* */
radioid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_RADIOID]);
wlanid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]);
if (!IS_VALID_RADIOID(radioid) || !IS_VALID_WLANID(wlanid)) {
return -EINVAL;
}
return sc_capwap_removewlan((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]), radioid, wlanid);
}
/* */
static int sc_netlink_auth_station(struct sk_buff* skb, struct genl_info* info) {
uint8_t radioid;
uint8_t wlanid;
uint16_t vlan = 0;
TRACEKMOD("### sc_netlink_auth_station\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check params */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID] || !info->attrs[NLSMARTCAPWAP_ATTR_MACADDRESS] || !info->attrs[NLSMARTCAPWAP_ATTR_IFPHY_INDEX] || !info->attrs[NLSMARTCAPWAP_ATTR_RADIOID] || !info->attrs[NLSMARTCAPWAP_ATTR_WLANID]) {
return -EINVAL;
}
/* */
radioid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_RADIOID]);
wlanid = nla_get_u8(info->attrs[NLSMARTCAPWAP_ATTR_WLANID]);
if (!IS_VALID_RADIOID(radioid) || !IS_VALID_WLANID(wlanid)) {
return -EINVAL;
}
/* VLAN */
if (info->attrs[NLSMARTCAPWAP_ATTR_VLAN]) {
vlan = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_VLAN]);
}
/* */
return sc_capwap_authstation((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]), (uint8_t*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_MACADDRESS]), nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]), radioid, wlanid, vlan);
}
/* */
static int sc_netlink_deauth_station(struct sk_buff* skb, struct genl_info* info) {
TRACEKMOD("### sc_netlink_deauth_station\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* Check params */
if (!info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID] || !info->attrs[NLSMARTCAPWAP_ATTR_MACADDRESS]) {
return -EINVAL;
}
/* */
return sc_capwap_deauthstation((struct sc_capwap_sessionid_element*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_SESSION_ID]), (uint8_t*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_MACADDRESS]));
}
/* */
static int sc_netlink_link(struct sk_buff* skb, struct genl_info* info) {
int ret;
TRACEKMOD("### sc_netlink_link\n");
/* */
if (sc_netlink_usermodeid) {
TRACEKMOD("*** Busy kernel link\n");
return -EBUSY;
}
/* Initialize library */
ret = sc_capwap_init();
if (ret) {
return ret;
}
/* Deny unload module */
try_module_get(THIS_MODULE);
sc_netlink_usermodeid = info->snd_portid;
return 0;
}
/* */
static int sc_netlink_add_iface(struct sk_buff* skb, struct genl_info* info) {
int err;
void* hdr;
uint16_t mtu;
int ifindex;
struct sk_buff *msg;
TRACEKMOD("### sc_netlink_add_iface\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* */
if (!info->attrs[NLSMARTCAPWAP_ATTR_IFPHY_NAME] || !info->attrs[NLSMARTCAPWAP_ATTR_MTU]) {
return -EINVAL;
}
/* */
mtu = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_MTU]);
if ((mtu < MIN_MTU) || (mtu > MAX_MTU)) {
return -EINVAL;
}
/* */
ifindex = sc_iface_create((char*)nla_data(info->attrs[NLSMARTCAPWAP_ATTR_IFPHY_NAME]), mtu);
if (ifindex < 0) {
return ifindex;
}
/* Send response */
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto error;
}
hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &sc_netlink_family, 0, NLSMARTCAPWAP_CMD_ADD_IFACE);
if (IS_ERR(hdr)) {
err = PTR_ERR(hdr);
goto error2;
}
if (nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFPHY_INDEX, (uint32_t)ifindex)) {
err = -ENOBUFS;
goto error2;
}
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
error2:
nlmsg_free(msg);
error:
sc_iface_delete((uint32_t)ifindex);
return err;
}
/* */
static int sc_netlink_delete_iface(struct sk_buff* skb, struct genl_info* info) {
TRACEKMOD("### sc_netlink_delete_iface\n");
/* Check Link */
if (!sc_netlink_usermodeid) {
return -ENOLINK;
}
/* */
if (!info->attrs[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]) {
return -EINVAL;
}
return sc_iface_delete(nla_get_u32(info->attrs[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]));
}
/* */
static int sc_netlink_notify(struct notifier_block* nb, unsigned long state, void* _notify) {
struct netlink_notify* notify = (struct netlink_notify*)_notify;
/* */
if ((state == NETLINK_URELEASE) && (sc_netlink_usermodeid == notify->portid)) {
/* Close capwap engine */
sc_capwap_close();
/* Allow unload module */
module_put(THIS_MODULE);
sc_netlink_usermodeid = 0;
}
return NOTIFY_DONE;
}
/* */
static const struct nla_policy sc_netlink_policy[NLSMARTCAPWAP_ATTR_MAX + 1] = {
[NLSMARTCAPWAP_ATTR_FLAGS] = { .type = NLA_U32 },
[NLSMARTCAPWAP_ATTR_SESSION_ID] = { .type = NLA_BINARY, .len = sizeof(struct sc_capwap_sessionid_element) },
[NLSMARTCAPWAP_ATTR_RADIOID] = { .type = NLA_U8 },
[NLSMARTCAPWAP_ATTR_WLANID] = { .type = NLA_U8 },
[NLSMARTCAPWAP_ATTR_BINDING] = { .type = NLA_U8 },
[NLSMARTCAPWAP_ATTR_MACMODE] = { .type = NLA_U8 },
[NLSMARTCAPWAP_ATTR_TUNNELMODE] = { .type = NLA_U8 },
[NLSMARTCAPWAP_ATTR_ADDRESS] = { .type = NLA_BINARY, .len = sizeof(struct sockaddr_storage) },
[NLSMARTCAPWAP_ATTR_DATA_FRAME] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN + CAPWAP_HEADER_MAX_LENGTH },
[NLSMARTCAPWAP_ATTR_MTU] = { .type = NLA_U16 },
[NLSMARTCAPWAP_ATTR_IFPHY_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ },
[NLSMARTCAPWAP_ATTR_IFPHY_INDEX] = { .type = NLA_U32 },
[NLSMARTCAPWAP_ATTR_MACADDRESS] = { .type = NLA_BINARY, .len = MACADDRESS_EUI48_LENGTH },
[NLSMARTCAPWAP_ATTR_BSSID] = { .type = NLA_BINARY, .len = MACADDRESS_EUI48_LENGTH },
[NLSMARTCAPWAP_ATTR_VLAN] = { .type = NLA_U16 },
};
/* Netlink Ops */
static struct genl_ops sc_netlink_ops[] = {
{
.cmd = NLSMARTCAPWAP_CMD_LINK,
.doit = sc_netlink_link,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_ADD_IFACE,
.doit = sc_netlink_add_iface,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_DELETE_IFACE,
.doit = sc_netlink_delete_iface,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_BIND,
.doit = sc_netlink_bind,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_SEND_KEEPALIVE,
.doit = sc_netlink_send_keepalive,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_SEND_DATA,
.doit = sc_netlink_send_data,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_NEW_SESSION,
.doit = sc_netlink_new_session,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_DELETE_SESSION,
.doit = sc_netlink_delete_session,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_ADD_WLAN,
.doit = sc_netlink_add_wlan,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_REMOVE_WLAN,
.doit = sc_netlink_remove_wlan,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_AUTH_STATION,
.doit = sc_netlink_auth_station,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = NLSMARTCAPWAP_CMD_DEAUTH_STATION,
.doit = sc_netlink_deauth_station,
.policy = sc_netlink_policy,
.flags = GENL_ADMIN_PERM,
},
};
/* Netlink notify */
static struct notifier_block sc_netlink_notifier = {
.notifier_call = sc_netlink_notify,
};
/* */
int sc_netlink_notify_recv_keepalive(const union capwap_addr* sockaddr, struct sc_capwap_sessionid_element* sessionid) {
void* msg;
struct sk_buff* sk_msg;
TRACEKMOD("### sc_netlink_notify_recv_keepalive\n");
/* Alloc message */
sk_msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
if (!sk_msg) {
return -ENOMEM;
}
/* Set command */
msg = genlmsg_put(sk_msg, 0, 0, &sc_netlink_family, 0, NLSMARTCAPWAP_CMD_RECV_KEEPALIVE);
if (!msg) {
goto error;
}
/* */
if (nla_put(sk_msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct sc_capwap_sessionid_element), sessionid)) {
goto error2;
}
/* Send message */
genlmsg_end(sk_msg, msg);
return genlmsg_unicast(&init_net, sk_msg, sc_netlink_usermodeid);
error2:
genlmsg_cancel(sk_msg, msg);
error:
nlmsg_free(sk_msg);
return -ENOMEM;
}
/* */
int sc_netlink_notify_recv_data(struct sc_capwap_sessionid_element* sessionid, uint8_t* packet, int length) {
void* msg;
struct sk_buff* sk_msg;
TRACEKMOD("### sc_netlink_notify_recv_data\n");
/* Alloc message */
sk_msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
if (!sk_msg) {
return -ENOMEM;
}
/* Set command */
msg = genlmsg_put(sk_msg, 0, 0, &sc_netlink_family, 0, NLSMARTCAPWAP_CMD_RECV_DATA);
if (!msg) {
goto error;
}
/* */
if (nla_put(sk_msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct sc_capwap_sessionid_element), sessionid) ||
nla_put(sk_msg, NLSMARTCAPWAP_ATTR_DATA_FRAME, length, packet)) {
goto error2;
}
/* Send message */
genlmsg_end(sk_msg, msg);
return genlmsg_unicast(&init_net, sk_msg, sc_netlink_usermodeid);
error2:
genlmsg_cancel(sk_msg, msg);
error:
nlmsg_free(sk_msg);
return -ENOMEM;
}
/* */
int sc_netlink_init(void) {
int ret;
TRACEKMOD("### sc_netlink_init\n");
/* Register netlink family */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
ret = genl_register_family_with_ops(&sc_netlink_family, sc_netlink_ops, sizeof(sc_netlink_ops) / sizeof(sc_netlink_ops[0]));
#else
ret = genl_register_family_with_ops(&sc_netlink_family, sc_netlink_ops);
#endif
if (ret) {
return ret;
}
/* Register netlink notifier */
ret = netlink_register_notifier(&sc_netlink_notifier);
if (ret) {
genl_unregister_family(&sc_netlink_family);
return ret;
}
return 0;
}
/* */
void sc_netlink_exit(void) {
TRACEKMOD("### sc_netlink_exit\n");
netlink_unregister_notifier(&sc_netlink_notifier);
genl_unregister_family(&sc_netlink_family);
}

View File

@ -1,15 +0,0 @@
#ifndef __KMOD_AC_NETLINKAPP_HEADER__
#define __KMOD_AC_NETLINKAPP_HEADER__
#include "capwap_rfc.h"
#include "socket.h"
/* */
int sc_netlink_init(void);
void sc_netlink_exit(void);
/* */
int sc_netlink_notify_recv_keepalive(const union capwap_addr* sockaddr, struct sc_capwap_sessionid_element* sessionid);
int sc_netlink_notify_recv_data(struct sc_capwap_sessionid_element* sessionid, uint8_t* packet, int length);
#endif /* __KMOD_AC_NETLINKAPP_HEADER__ */

View File

@ -1,73 +0,0 @@
#ifndef __AC_NLSMARTCAPWAP_HEADER__
#define __AC_NLSMARTCAPWAP_HEADER__
/* */
#define NLSMARTCAPWAP_GENL_NAME "smartcapwap_ac"
/* */
#define NLSMARTCAPWAP_FLAGS_TUNNEL_8023 0x00000001
/* */
enum sc_netlink_attrs {
NLSMARTCAPWAP_ATTR_UNSPEC,
NLSMARTCAPWAP_ATTR_FLAGS,
NLSMARTCAPWAP_ATTR_SESSION_ID,
NLSMARTCAPWAP_ATTR_RADIOID,
NLSMARTCAPWAP_ATTR_WLANID,
NLSMARTCAPWAP_ATTR_BINDING,
NLSMARTCAPWAP_ATTR_MACMODE,
NLSMARTCAPWAP_ATTR_TUNNELMODE,
NLSMARTCAPWAP_ATTR_ADDRESS,
NLSMARTCAPWAP_ATTR_MTU,
NLSMARTCAPWAP_ATTR_DATA_FRAME,
NLSMARTCAPWAP_ATTR_IFPHY_NAME,
NLSMARTCAPWAP_ATTR_IFPHY_INDEX,
NLSMARTCAPWAP_ATTR_MACADDRESS,
NLSMARTCAPWAP_ATTR_BSSID,
NLSMARTCAPWAP_ATTR_VLAN,
/* Last attribute */
__NLSMARTCAPWAP_ATTR_AFTER_LAST,
NLSMARTCAPWAP_ATTR_MAX = __NLSMARTCAPWAP_ATTR_AFTER_LAST - 1
};
/* */
enum sc_netlink_commands {
NLSMARTCAPWAP_CMD_UNSPEC,
NLSMARTCAPWAP_CMD_LINK,
NLSMARTCAPWAP_CMD_ADD_IFACE,
NLSMARTCAPWAP_CMD_DELETE_IFACE,
NLSMARTCAPWAP_CMD_BIND,
NLSMARTCAPWAP_CMD_SEND_KEEPALIVE,
NLSMARTCAPWAP_CMD_RECV_KEEPALIVE,
NLSMARTCAPWAP_CMD_NEW_SESSION,
NLSMARTCAPWAP_CMD_DELETE_SESSION,
NLSMARTCAPWAP_CMD_ADD_WLAN,
NLSMARTCAPWAP_CMD_REMOVE_WLAN,
NLSMARTCAPWAP_CMD_SEND_DATA,
NLSMARTCAPWAP_CMD_RECV_DATA,
NLSMARTCAPWAP_CMD_AUTH_STATION,
NLSMARTCAPWAP_CMD_DEAUTH_STATION,
/* Last command */
__NLSMARTCAPWAP_CMD_AFTER_LAST,
NLSMARTCAPWAP_CMD_MAX = __NLSMARTCAPWAP_CMD_AFTER_LAST - 1
};
#endif /* __AC_NLSMARTCAPWAP_HEADER__ */

View File

@ -1,227 +0,0 @@
#include "config.h"
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/socket.h>
#include <linux/kthread.h>
#include <linux/net.h>
#include <linux/if_ether.h>
#include <linux/udp.h>
#include <net/ipv6.h>
#include <net/sock.h>
#include <net/udp.h>
#include "socket.h"
#include "capwap.h"
/* Socket */
#define SOCKET_COUNT 2
static struct socket* sc_sockets[SOCKET_COUNT];
/* */
int sc_socket_recvpacket(struct sock* sk, struct sk_buff* skb) {
TRACEKMOD("### sc_socket_recvpacket\n");
/* */
CAPWAP_SKB_CB(skb)->flags = SKB_CAPWAP_FLAG_FROM_DATA_CHANNEL;
/* */
sc_capwap_recvpacket(skb);
return 0;
}
/* */
static int sc_socket_create(int type, union capwap_addr* sockaddr, uint16_t protocol) {
int ret;
TRACEKMOD("### sc_socket_create\n");
/* Create socket */
ret = sock_create_kern(sockaddr->ss.ss_family, SOCK_DGRAM, protocol, &sc_sockets[type]);
if (ret) {
return ret;
}
/* Bind to interface */
ret = kernel_bind(sc_sockets[type], &sockaddr->sa, sizeof(union capwap_addr));
if (ret) {
goto failure;
}
/* Set callback */
udp_sk(sc_sockets[type]->sk)->encap_type = 1;
udp_sk(sc_sockets[type]->sk)->encap_rcv = sc_socket_recvpacket;
/* */
if (!((sockaddr->ss.ss_family == AF_INET) ? sockaddr->sin.sin_port : sockaddr->sin6.sin6_port)) {
union capwap_addr localaddr;
int localaddrsize = sizeof(union capwap_addr);
/* Retrieve port */
ret = kernel_getsockname(sc_sockets[type], &localaddr.sa, &localaddrsize);
if (ret) {
goto failure;
}
/* */
if ((sockaddr->ss.ss_family == AF_INET) && (localaddr.ss.ss_family == AF_INET)) {
sockaddr->sin.sin_port = localaddr.sin.sin_port;
} else if ((sockaddr->ss.ss_family == AF_INET6) && (localaddr.ss.ss_family == AF_INET6)) {
sockaddr->sin6.sin6_port = localaddr.sin6.sin6_port;
} else {
ret = -EFAULT;
goto failure;
}
}
return 0;
failure:
sock_release(sc_sockets[type]);
sc_sockets[type] = 0;
return ret;
}
/* */
int sc_socket_getpeeraddr(struct sk_buff* skb, union capwap_addr* peeraddr) {
unsigned char* nethdr;
TRACEKMOD("### sc_socket_getpeeraddr\n");
/* */
nethdr = skb_network_header(skb);
if (!nethdr) {
return -EINVAL;
}
/* */
switch (ntohs(skb->protocol)) {
case ETH_P_IP: {
/* Validate IPv4 header */
if ((nethdr[0] & 0xf0) != 0x40) {
return -EINVAL;
}
/* Retrieve address */
peeraddr->sin.sin_family = AF_INET;
peeraddr->sin.sin_addr.s_addr = ((struct iphdr*)nethdr)->saddr;
peeraddr->sin.sin_port = udp_hdr(skb)->source;
break;
}
case ETH_P_IPV6: {
/* Validate IPv6 header */
if ((nethdr[0] & 0xf0) != 0x60) {
return -EINVAL;
}
/* Retrieve address */
peeraddr->sin6.sin6_family = AF_INET6;
memcpy(&peeraddr->sin6.sin6_addr, &((struct ipv6hdr*)nethdr)->saddr, sizeof(struct in6_addr));
peeraddr->sin6.sin6_port = udp_hdr(skb)->source;
break;
}
default: {
return -EINVAL;
}
}
return 0;
}
/* */
int sc_socket_send(int type, uint8_t* buffer, int length, union capwap_addr* sockaddr) {
struct kvec vec;
struct msghdr msg;
TRACEKMOD("### sc_socket_send\n");
/* */
vec.iov_base = buffer;
vec.iov_len = length;
/* */
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = sockaddr;
msg.msg_namelen = sizeof(union capwap_addr);
msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT;
/* */
return kernel_sendmsg(sc_sockets[type], &msg, &vec, 1, length);
}
/* */
int sc_socket_init(void) {
TRACEKMOD("### sc_socket_init\n");
memset(sc_sockets, 0, sizeof(sc_sockets));
return 0;
}
/* */
int sc_socket_bind(union capwap_addr* sockaddr) {
int ret;
TRACEKMOD("### sc_socket_bind\n");
/* */
if (sc_sockets[SOCKET_UDP] || sc_sockets[SOCKET_UDPLITE]) {
return -EBUSY;
}
/* UDP socket */
ret = sc_socket_create(SOCKET_UDP, sockaddr, IPPROTO_UDP);
if (ret) {
goto failure;
}
/* UDPLite socket */
ret = sc_socket_create(SOCKET_UDPLITE, sockaddr, IPPROTO_UDPLITE);
if (ret) {
goto failure;
}
/* */
udp_encap_enable();
if (sockaddr->ss.ss_family == AF_INET6) {
udpv6_encap_enable();
}
return 0;
failure:
sc_socket_close();
return ret;
}
/* */
void sc_socket_close(void) {
TRACEKMOD("### sc_socket_close\n");
/* Close sockets */
if (sc_sockets[SOCKET_UDP]) {
kernel_sock_shutdown(sc_sockets[SOCKET_UDP], SHUT_RDWR);
sock_release(sc_sockets[SOCKET_UDP]);
}
if (sc_sockets[SOCKET_UDPLITE]) {
kernel_sock_shutdown(sc_sockets[SOCKET_UDPLITE], SHUT_RDWR);
sock_release(sc_sockets[SOCKET_UDPLITE]);
}
memset(sc_sockets, 0, sizeof(sc_sockets));
}
/* */
int sc_addr_compare(const union capwap_addr* addr1, const union capwap_addr* addr2) {
TRACEKMOD("### sc_addr_compare\n");
if (addr1->ss.ss_family == addr2->ss.ss_family) {
if (addr1->ss.ss_family == AF_INET) {
return (((addr1->sin.sin_addr.s_addr == addr2->sin.sin_addr.s_addr) && (addr1->sin.sin_port == addr2->sin.sin_port)) ? 0 : -1);
} else if (addr1->ss.ss_family == AF_INET6) {
return ((!memcmp(&addr1->sin6.sin6_addr, &addr2->sin6.sin6_addr, sizeof(struct in6_addr)) && (addr1->sin6.sin6_port == addr2->sin6.sin6_port)) ? 0 : -1);
}
}
return -1;
}

View File

@ -1,35 +0,0 @@
#ifndef __KMOD_SOCKET_HEADER__
#define __KMOD_SOCKET_HEADER__
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/skbuff.h>
/* */
#define SOCKET_UDP 0
#define SOCKET_UDPLITE 1
/* Universal socket address */
union capwap_addr {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
struct sockaddr_storage ss;
};
/* */
int sc_socket_init(void);
void sc_socket_close(void);
/* */
int sc_socket_bind(union capwap_addr* sockaddr);
int sc_socket_send(int type, uint8_t* buffer, int length, union capwap_addr* sockaddr);
/* */
int sc_socket_getpeeraddr(struct sk_buff* skb, union capwap_addr* peeraddr);
/* */
int sc_addr_compare(const union capwap_addr* addr1, const union capwap_addr* addr2);
#endif /* __KMOD_SOCKET_HEADER__ */

View File

@ -1,157 +0,0 @@
#include "config.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include "station.h"
#include "capwap.h"
#include "iface.h"
/* */
#define STATION_HASH_SIZE 65536
/* */
static LIST_HEAD(sc_station_list);
static struct sc_capwap_station* __rcu sc_station_hash_addr[STATION_HASH_SIZE];
/* */
static uint32_t sc_stations_hash_addr(const uint8_t* macaddress) {
TRACEKMOD("### sc_stations_hash_addr\n");
return (((((uint32_t)macaddress[4] << 8) | (uint32_t)macaddress[5]) ^ ((uint32_t)macaddress[3] << 4)) % STATION_HASH_SIZE);
}
/* */
static struct sc_capwap_connection* sc_stations_searchconnection(struct sc_capwap_station* station) {
struct sc_capwap_connection* connection;
struct sc_capwap_session_priv* sessionpriv = rcu_access_pointer(station->sessionpriv);
struct sc_netdev_priv* devpriv = rcu_access_pointer(station->devpriv);
TRACEKMOD("### sc_stations_searchconnection\n");
list_for_each_entry(connection, &sessionpriv->list_connections, list_session) {
if ((connection->devpriv == devpriv) && (connection->radioid == station->radioid) && (connection->vlan == station->vlan)) {
return connection;
}
}
return NULL;
}
/* */
void sc_stations_add(struct sc_capwap_station* station) {
uint32_t hash;
TRACEKMOD("### sc_stations_add\n");
/* */
list_add_rcu(&station->list, &sc_station_list);
hash = sc_stations_hash_addr(station->address);
station->next_addr = rcu_dereference_protected(sc_station_hash_addr[hash], sc_capwap_update_lock_is_locked());
rcu_assign_pointer(sc_station_hash_addr[hash], station);
}
/* */
struct sc_capwap_station* sc_stations_search(const uint8_t* macaddress) {
struct sc_capwap_station* station;
TRACEKMOD("### sc_stations_search\n");
/* */
station = rcu_dereference_check(sc_station_hash_addr[sc_stations_hash_addr(macaddress)], sc_capwap_update_lock_is_locked());
while (station) {
if (!memcmp(&station->address, macaddress, MACADDRESS_EUI48_LENGTH)) {
break;
}
/* */
station = rcu_dereference_check(station->next_addr, sc_capwap_update_lock_is_locked());
}
return station;
}
/* */
void sc_stations_free(struct sc_capwap_station* station) {
uint32_t hash;
struct sc_capwap_station* search;
TRACEKMOD("### sc_stations_free\n");
/* */
hash = sc_stations_hash_addr(station->address);
search = rcu_dereference_protected(sc_station_hash_addr[hash], sc_capwap_update_lock_is_locked());
if (search) {
if (search == station) {
rcu_assign_pointer(sc_station_hash_addr[hash], station->next_addr);
} else {
while (rcu_access_pointer(search->next_addr) && (rcu_access_pointer(search->next_addr) != station)) {
search = rcu_dereference_protected(search->next_addr, sc_capwap_update_lock_is_locked());
}
if (rcu_access_pointer(search->next_addr)) {
rcu_assign_pointer(search->next_addr, station->next_addr);
}
}
}
/* */
list_del_rcu(&station->list_dev);
list_del_rcu(&station->list_session);
synchronize_net();
kfree(station);
}
/* */
int sc_stations_setconnection(struct sc_capwap_station* station) {
struct sc_capwap_connection* connection;
TRACEKMOD("### sc_stations_setconnection\n");
/* */
connection = sc_stations_searchconnection(station);
if (!connection) {
connection = (struct sc_capwap_connection*)kzalloc(sizeof(struct sc_capwap_connection), GFP_KERNEL);
if (!connection) {
TRACEKMOD("*** Unable to create connection\n");
return -ENOMEM;
}
/* */
connection->sessionpriv = rcu_access_pointer(station->sessionpriv);
list_add_rcu(&connection->list_session, &connection->sessionpriv->list_connections);
connection->devpriv = rcu_access_pointer(station->devpriv);
list_add_rcu(&connection->list_dev, &connection->devpriv->list_connections);
connection->radioid = station->radioid;
connection->vlan = station->vlan;
}
/* */
connection->count++;
connection->wlanidmask |= 1 << (station->wlanid - 1);
return 0;
}
/* */
void sc_stations_releaseconnection(struct sc_capwap_station* station) {
struct sc_capwap_connection* connection;
TRACEKMOD("### sc_stations_releaseconnection\n");
connection = sc_stations_searchconnection(station);
if (connection) {
TRACEKMOD("*** Release connection reference %d\n", connection->count);
connection->count--;
if (!connection->count) {
list_del_rcu(&connection->list_session);
list_del_rcu(&connection->list_dev);
synchronize_net();
kfree(connection);
}
}
}

View File

@ -1,58 +0,0 @@
#ifndef __KMOD_AC_STATION_HEADER__
#define __KMOD_AC_STATION_HEADER__
#include "capwap_rfc.h"
/* */
struct sc_capwap_connection {
int count;
/* Session */
struct sc_capwap_session_priv* sessionpriv;
struct list_head list_session;
/* Interface */
struct sc_netdev_priv* devpriv;
struct list_head list_dev;
/* */
uint16_t vlan;
uint8_t radioid;
uint8_t wlanidmask;
};
/* */
struct sc_capwap_station {
struct list_head list;
/* */
uint8_t address[MACADDRESS_EUI48_LENGTH];
struct sc_capwap_station* __rcu next_addr;
/* Session */
struct sc_capwap_session_priv* __rcu sessionpriv;
struct list_head list_session;
/* Interface */
struct sc_netdev_priv* __rcu devpriv;
struct list_head list_dev;
/* */
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint16_t vlan;
uint8_t radioid;
uint8_t wlanid;
};
/* */
void sc_stations_add(struct sc_capwap_station* station);
void sc_stations_free(struct sc_capwap_station* station);
/* */
struct sc_capwap_station* sc_stations_search(const uint8_t* macaddress);
/* */
int sc_stations_setconnection(struct sc_capwap_station* station);
void sc_stations_releaseconnection(struct sc_capwap_station* station);
#endif /* __KMOD_AC_STATION_HEADER__ */

View File

@ -1,5 +1,5 @@
#include "capwap.h"
#include "capwap_network.h"
#include "network.h"
#include <linux/socket.h>
#include "wifi_drivers.h"
#include "netlink_link.h"

View File

@ -1,9 +1,10 @@
#include "wtp.h"
#include "capwap_list.h"
#include "capwap_element.h"
#include "list.h"
#include "hash.h"
#include "element.h"
#include "wifi_drivers.h"
#include "wtp_radio.h"
#include "wtp_kmod.h"
#include "radio.h"
#include "kmod.h"
/* Declare enable wifi driver */
#ifdef ENABLE_WIFI_DRIVERS_NL80211

View File

@ -1,13 +1,13 @@
#include "wtp.h"
#include "capwap_array.h"
#include "capwap_list.h"
#include "capwap_element.h"
#include "capwap_element_80211_ie.h"
#include "array.h"
#include "list.h"
#include "element.h"
#include "element_80211_ie.h"
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include "wtp_kmod.h"
#include "kmod.h"
/* Local version of nl80211 with all feature to remove the problem of frag version of nl80211 */
#include "nl80211_v3_10.h"

View File

@ -3,7 +3,7 @@
#include <ev.h>
#include "capwap_hash.h"
#include "hash.h"
#include "netlink_link.h"
/* Compatibility functions */

View File

@ -1,790 +0,0 @@
#include "capwap.h"
#include "ieee80211.h"
/* */
static int ieee80211_ie_set_ssid(uint8_t* buffer, const char* ssid, int hidessid) {
struct ieee80211_ie_ssid* iessid = (struct ieee80211_ie_ssid*)buffer;
ASSERT(buffer != NULL);
ASSERT(ssid != NULL);
iessid->id = IEEE80211_IE_SSID;
if (hidessid) {
iessid->len = 0;
} else {
iessid->len = strlen(ssid);
if (iessid->len > IEEE80211_IE_SSID_MAX_LENGTH) {
return -1;
}
strncpy((char*)iessid->ssid, ssid, iessid->len);
}
return sizeof(struct ieee80211_ie_ssid) + iessid->len;
}
/* */
static int ieee80211_ie_set_supportedrates(uint8_t* buffer, uint8_t* supportedrates, int supportedratescount) {
int i;
int count;
struct ieee80211_ie_supported_rates* iesupportedrates = (struct ieee80211_ie_supported_rates*)buffer;
ASSERT(buffer != NULL);
ASSERT(supportedrates != NULL);
ASSERT(supportedratescount > 0);
/* IE accept max only 8 rate */
count = supportedratescount;
if (count > 8) {
count = 8;
}
/* */
iesupportedrates->id = IEEE80211_IE_SUPPORTED_RATES;
iesupportedrates->len = count;
for (i = 0; i < count; i++) {
iesupportedrates->rates[i] = supportedrates[i];
}
return sizeof(struct ieee80211_ie_supported_rates) + iesupportedrates->len;
}
/* */
static int ieee80211_ie_set_extendedsupportedrates(uint8_t* buffer, uint8_t* supportedrates, int supportedratescount) {
int i, j;
struct ieee80211_ie_extended_supported_rates* ieextendedsupportedrates = (struct ieee80211_ie_extended_supported_rates*)buffer;
ASSERT(buffer != NULL);
ASSERT(supportedrates != NULL);
/* IE accept only > 8 rate */
if (supportedratescount <= IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH) {
return 0;
}
/* */
ieextendedsupportedrates->id = IEEE80211_IE_EXTENDED_SUPPORTED_RATES;
ieextendedsupportedrates->len = supportedratescount - IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH;
for (i = IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH, j = 0; i < supportedratescount; i++, j++) {
ieextendedsupportedrates->rates[j] = supportedrates[i];
}
return sizeof(struct ieee80211_ie_extended_supported_rates) + ieextendedsupportedrates->len;
}
/* */
static int ieee80211_ie_set_dsss(uint8_t* buffer, uint8_t channel) {
struct ieee80211_ie_dsss* iedsss = (struct ieee80211_ie_dsss*)buffer;
ASSERT(buffer != NULL);
iedsss->id = IEEE80211_IE_DSSS;
iedsss->len = IEEE80211_IE_DSSS_LENGTH;
iedsss->channel = channel;
return sizeof(struct ieee80211_ie_dsss);
}
/* */
static int ieee80211_ie_set_erp(uint8_t* buffer, uint32_t mode, uint8_t erpinfo) {
struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer;
ASSERT(buffer != NULL);
if (!(mode & IEEE80211_RADIO_TYPE_80211G)) {
return 0;
}
ieerp->id = IEEE80211_IE_ERP;
ieerp->len = IEEE80211_IE_ERP_LENGTH;
ieerp->params = erpinfo;
return sizeof(struct ieee80211_ie_erp);
}
/* */
int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length) {
ASSERT(items != NULL);
ASSERT(data != NULL);
/* */
memset(items, 0, sizeof(struct ieee80211_ie_items));
/* Parsing */
while (length >= 2) {
struct ieee80211_ie *ie = (struct ieee80211_ie *)data;
/* Parsing Information Element */
switch (ie->id) {
case IEEE80211_IE_SSID:
if (ie->len > IEEE80211_IE_SSID_MAX_LENGTH)
return -1;
items->ssid = (struct ieee80211_ie_ssid *)data;
break;
case IEEE80211_IE_SUPPORTED_RATES:
if ((ie->len < IEEE80211_IE_SUPPORTED_RATES_MIN_LENGTH) ||
(ie->len > IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH))
return -1;
items->supported_rates = (struct ieee80211_ie_supported_rates *)data;
break;
case IEEE80211_IE_DSSS:
if (ie->len != IEEE80211_IE_DSSS_LENGTH)
return -1;
items->dsss = (struct ieee80211_ie_dsss *)data;
break;
case IEEE80211_IE_COUNTRY:
if (ie->len < IEEE80211_IE_COUNTRY_MIN_LENGTH)
return -1;
items->country = (struct ieee80211_ie_country *)data;
break;
case IEEE80211_IE_CHALLENGE_TEXT:
if (ie->len < IEEE80211_IE_CHALLENGE_TEXT_MIN_LENGTH)
return -1;
items->challenge_text = (struct ieee80211_ie_challenge_text *)data;
break;
case IEEE80211_IE_ERP:
if (ie->len != IEEE80211_IE_ERP_LENGTH)
return -1;
items->erp = (struct ieee80211_ie_erp *)data;
break;
case IEEE80211_IE_EXTENDED_SUPPORTED_RATES:
if (ie->len < IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH)
return -1;
items->extended_supported_rates =
(struct ieee80211_ie_extended_supported_rates *)data;
break;
case IEEE80211_IE_EDCA_PARAMETER_SET:
if (ie->len != IEEE80211_IE_EDCA_PARAMETER_SET_LENGTH)
return -1;
items->edca_parameter_set = (struct ieee80211_ie_edca_parameter_set *)data;
break;
case IEEE80211_IE_QOS_CAPABILITY:
if (ie->len != IEEE80211_IE_QOS_CAPABILITY_LENGTH)
return -1;
items->qos_capability = (struct ieee80211_ie_qos_capability *)data;
break;
case IEEE80211_IE_POWER_CONSTRAINT:
if (ie->len != IEEE80211_IE_POWER_CONSTRAINT_LENGTH)
return -1;
items->power_constraint = (struct ieee80211_ie_power_constraint *)data;
break;
case IEEE80211_IE_SSID_LIST:
items->ssid_list = (struct ieee80211_ie_ssid_list *)data;
break;
case IEEE80211_IE_VENDOR_SPECIFIC: {
struct ieee80211_ie_vendor_specific *vs =
(struct ieee80211_ie_vendor_specific *)data;
uint32_t oui = vs->oui[0] << 16 | vs->oui[1] << 8 | vs->oui[2];
if (oui == MICROSOFT_OUI &&
vs->oui_type == WMM_TYPE &&
vs->oui_subtype == WMM_INFORMATION_ELEMENT) {
items->wmm_ie = (struct ieee80211_ie_wmm_information_element *)data;
break;
}
}
}
/* Next Information Element */
data += sizeof(struct ieee80211_ie) + ie->len;
length -= sizeof(struct ieee80211_ie) + ie->len;
}
return (!length ? 0 : -1);
}
/* */
int ieee80211_aid_create(uint32_t* aidbitfield, uint16_t* aid) {
int i, j;
ASSERT(aidbitfield != NULL);
ASSERT(aid != NULL);
/* Search free aid bitfield */
for (i = 0; i < IEEE80211_AID_BITFIELD_SIZE; i++) {
if (aidbitfield[i] != 0xffffffff) {
uint32_t bitfield = aidbitfield[i];
/* Search free bit */
for (j = 0; j < 32; j++) {
if (!(bitfield & (1 << j))) {
*aid = i * 32 + j + 1;
if (*aid <= IEEE80211_AID_MAX_VALUE) {
aidbitfield[i] |= (1 << j);
return 0;
}
break;
}
}
break;
}
}
*aid = 0;
return -1;
}
/* */
void ieee80211_aid_free(uint32_t* aidbitfield, uint16_t aid) {
ASSERT(aidbitfield != NULL);
ASSERT((aid > 0) && (aid <= IEEE80211_AID_MAX_VALUE));
aidbitfield[(aid - 1) / 32] &= ~(1 << ((aid - 1) % 32));
}
/* */
unsigned long ieee80211_frequency_to_channel(uint32_t freq) {
if ((freq >= 2412) && (freq <= 2472)) {
return (freq - 2407) / 5;
} else if (freq == 2484) {
return 14;
} else if ((freq >= 4915) && (freq <= 4980)) {
return (freq - 4000) / 5;
} else if ((freq >= 5035) && (freq <= 5825)) {
return (freq - 5000) / 5;
}
return 0;
}
/* */
int ieee80211_is_broadcast_addr(const uint8_t* addr) {
return (((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)) ? 1 : 0);
}
/* */
const uint8_t* ieee80211_get_sa_addr(const struct ieee80211_header* header) {
uint16_t framecontrol;
uint16_t framecontrol_type;
ASSERT(header);
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
return header->address2;
} else if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_DATA) {
switch (framecontrol & (IEEE80211_FRAME_CONTROL_MASK_TODS | IEEE80211_FRAME_CONTROL_MASK_FROMDS)) {
case 0: {
return header->address2;
}
case IEEE80211_FRAME_CONTROL_MASK_TODS: {
return header->address2;
}
case IEEE80211_FRAME_CONTROL_MASK_FROMDS: {
return header->address3;
}
}
}
return NULL;
}
const uint8_t* ieee80211_get_da_addr(const struct ieee80211_header* header) {
uint16_t framecontrol;
uint16_t framecontrol_type;
ASSERT(header);
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
return header->address1;
} else if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_DATA) {
switch (framecontrol & (IEEE80211_FRAME_CONTROL_MASK_TODS | IEEE80211_FRAME_CONTROL_MASK_FROMDS)) {
case 0: {
return header->address1;
}
case IEEE80211_FRAME_CONTROL_MASK_TODS: {
return header->address3;
}
case IEEE80211_FRAME_CONTROL_MASK_FROMDS: {
return header->address1;
}
}
}
return NULL;
}
/* */
const uint8_t* ieee80211_get_bssid_addr(const struct ieee80211_header* header) {
uint16_t framecontrol;
uint16_t framecontrol_type;
ASSERT(header);
/* Get type frame */
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
return header->address3;
} else if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_DATA) {
switch (framecontrol & (IEEE80211_FRAME_CONTROL_MASK_TODS | IEEE80211_FRAME_CONTROL_MASK_FROMDS)) {
case 0: {
return header->address3;
}
case IEEE80211_FRAME_CONTROL_MASK_TODS: {
return header->address1;
}
case IEEE80211_FRAME_CONTROL_MASK_FROMDS: {
return header->address2;
}
}
}
return NULL;
}
/* */
int ieee80211_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist) {
int ssidlength;
ASSERT(ssid != NULL);
if (!iessid) {
return IEEE80211_WRONG_SSID;
}
/* Check SSID */
ssidlength = strlen((char*)ssid);
if ((ssidlength == iessid->len) && !memcmp(ssid, iessid->ssid, ssidlength)) {
return IEEE80211_VALID_SSID;
}
/* Check SSID list */
if (isssidlist) {
int length = isssidlist->len;
uint8_t* pos = isssidlist->lists;
while (length >= sizeof(struct ieee80211_ie)) {
struct ieee80211_ie_ssid* ssiditem = (struct ieee80211_ie_ssid*)pos;
/* Check buffer */
length -= sizeof(struct ieee80211_ie);
if ((ssiditem->id != IEEE80211_IE_SSID) || !ssiditem->len || (length < ssiditem->len)) {
break;
} else if ((ssidlength == ssiditem->len) && !memcmp(ssid, ssiditem->ssid, ssidlength)) {
return IEEE80211_VALID_SSID;
}
/* Next */
length -= ssiditem->len;
pos += sizeof(struct ieee80211_ie) + ssiditem->len;
}
}
return (!iessid->len ? IEEE80211_WILDCARD_SSID : IEEE80211_WRONG_SSID);
}
/* */
uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble) {
uint8_t result = 0;
/* Erp mode is valid only in IEEE 802.11 g*/
if (mode & IEEE80211_RADIO_TYPE_80211G) {
if (olbc) {
result |= IEEE80211_ERP_INFO_USE_PROTECTION;
}
if (stationnonerpcount > 0) {
result |= (IEEE80211_ERP_INFO_NON_ERP_PRESENT | IEEE80211_ERP_INFO_USE_PROTECTION);
}
if (!shortpreamble || (stationnoshortpreamblecount > 0)) {
result |= IEEE80211_ERP_INFO_BARKER_PREAMBLE_MODE;
}
}
return result;
}
/* */
int ieee80211_create_beacon(uint8_t* buffer, int length, struct ieee80211_beacon_params* params) {
int result;
uint8_t* pos;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
params->headbeacon = buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT,
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_BEACON);
header->durationid = __cpu_to_le16(0);
memset(header->da, 0xff, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
memset(header->beacon.timestamp, 0, sizeof(header->beacon.timestamp));
header->beacon.beaconinterval = __cpu_to_le16(params->beaconperiod);
header->beacon.capability = __cpu_to_le16(params->capability);
/* Header frame size */
params->headbeaconlength = (int)((uint8_t*)&header->beacon.ie[0] - (uint8_t*)header);
pos = buffer + params->headbeaconlength;
/* Information Element: SSID */
result = ieee80211_ie_set_ssid(pos, params->ssid, (params->ssid_hidden ? 1 : 0));
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Information Element: DSSS */
result = ieee80211_ie_set_dsss(pos, params->channel);
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Separate Information Elements into two block between IE TIM */
params->tailbeacon = pos;
params->tailbeaconlength = 0;
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->mode, params->erpinfo);
if (result < 0) {
return -1;
}
pos += result;
params->tailbeaconlength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
params->tailbeaconlength += result;
log_printf(LOG_DEBUG, "IEEE80211: Beacon IE length: %d", params->beacon_ies_len);
if (params->beacon_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Beacon IEs",
params->beacon_ies, params->beacon_ies_len);
memcpy(pos, params->beacon_ies, params->beacon_ies_len);
pos += params->beacon_ies_len;
params->tailbeaconlength += params->beacon_ies_len;
}
/* Probe Response offload */
if (params->flags & IEEE80221_CREATE_BEACON_FLAGS_PROBE_RESPONSE_OFFLOAD) {
struct ieee80211_probe_response_params proberesponseparams;
/* */
memset(&proberesponseparams, 0, sizeof(struct ieee80211_probe_response_params));
memcpy(proberesponseparams.bssid, params->bssid, ETH_ALEN);
proberesponseparams.beaconperiod = params->beaconperiod;
proberesponseparams.capability = params->capability;
proberesponseparams.ssid = params->ssid;
memcpy(proberesponseparams.supportedrates, params->supportedrates, params->supportedratescount);
proberesponseparams.supportedratescount = params->supportedratescount;
proberesponseparams.mode = params->mode;
proberesponseparams.erpinfo = params->erpinfo;
proberesponseparams.channel = params->channel;
/* */
params->proberesponseoffload = pos;
params->proberesponseoffloadlength = ieee80211_create_probe_response(pos, (int)(pos - buffer), &proberesponseparams);
if (params->proberesponseoffloadlength < 0) {
return -1;
}
/* */
pos += params->proberesponseoffloadlength;
log_printf(LOG_DEBUG, "IEEE80211: Probe Response IE length: %d", params->response_ies_len);
if (params->response_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Probe Response IEs",
params->response_ies, params->response_ies_len);
memcpy(pos, params->response_ies, params->response_ies_len);
pos += params->response_ies_len;
params->proberesponseoffloadlength += params->response_ies_len;
}
}
return (int)(pos - buffer);
}
/* */
int ieee80211_create_probe_response(uint8_t* buffer, int length, struct ieee80211_probe_response_params* params) {
int result;
uint8_t* pos;
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_RESPONSE);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
memset(header->proberesponse.timestamp, 0, sizeof(header->proberesponse.timestamp));
header->proberesponse.beaconinterval = __cpu_to_le16(params->beaconperiod);
header->proberesponse.capability = __cpu_to_le16(params->capability);
/* Header frame size */
responselength = (int)((uint8_t*)&header->proberesponse.ie[0] - (uint8_t*)header);
pos = buffer + responselength;
/* Information Element: SSID */
result = ieee80211_ie_set_ssid(pos, params->ssid, 0);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: DSSS */
result = ieee80211_ie_set_dsss(pos, params->channel);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->mode, params->erpinfo);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
log_printf(LOG_DEBUG, "IEEE80211: Probe Response IE length: %d", params->response_ies_len);
if (params->response_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Response IEs",
params->response_ies, params->response_ies_len);
memcpy(pos, params->response_ies, params->response_ies_len);
/* pos += params->response_ies_len; */ /* Comment for disable Dead inscrement Clang Analyzer warning */
responselength += params->response_ies_len;
}
return responselength;
}
/* */
int ieee80211_create_authentication_response(uint8_t* buffer, int length, struct ieee80211_authentication_params* params) {
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->authetication.algorithm = __cpu_to_le16(params->algorithm);
header->authetication.transactionseqnumber = __cpu_to_le16(params->transactionseqnumber);
header->authetication.statuscode = __cpu_to_le16(params->statuscode);
/* Header frame size */
responselength = (int)((uint8_t*)&header->authetication.ie[0] - (uint8_t*)header);
/* TODO: add custon IE */
return responselength;
}
/* */
int ieee80211_create_associationresponse_response(uint8_t* buffer, int length, struct ieee80211_associationresponse_params* params) {
uint8_t* pos;
int result;
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT,
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->associationresponse.capability = __cpu_to_le16(params->capability);
header->associationresponse.statuscode = __cpu_to_le16(params->statuscode);
header->associationresponse.aid = __cpu_to_le16(params->aid);
/* Header frame size */
responselength = (int)((uint8_t*)&header->associationresponse.ie[0] - (uint8_t*)header);
pos = buffer + responselength;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
log_printf(LOG_DEBUG, "IEEE80211: Association Response IE length: %d", params->response_ies_len);
if (params->response_ies_len) {
log_hexdump(LOG_DEBUG, "IEEE80211: Response IEs",
params->response_ies, params->response_ies_len);
memcpy(pos, params->response_ies, params->response_ies_len);
/* pos += params->response_ies_len; */ /* Comment for disable Dead inscrement Clang Analyzer warning */
responselength += params->response_ies_len;
}
return responselength;
}
/* */
int ieee80211_create_deauthentication(uint8_t* buffer, int length, struct ieee80211_deauthentication_params* params) {
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->deauthetication.reasoncode = __cpu_to_le16(params->reasoncode);
return (int)((uint8_t*)&header->deauthetication.ie[0] - (uint8_t*)header);
}
/* */
int ieee80211_create_disassociation(uint8_t* buffer, int length,
struct ieee80211_disassociation_params* params)
{
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
/* */
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT,
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, params->station, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->disassociation.reasoncode = __cpu_to_le16(params->reasoncode);
return (int)((uint8_t*)&header->disassociation.ie[0] - (uint8_t*)header);
}

View File

@ -1,751 +0,0 @@
#ifndef __CAPWAP_IEEE802_11_HEADER__
#define __CAPWAP_IEEE802_11_HEADER__
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/if_ether.h>
#ifndef STRUCT_PACKED
#define STRUCT_PACKED __attribute__((__packed__))
#endif
/* Global values */
#define IEEE80211_MTU 7981
#define IEEE80211_SUPPORTEDRATE_MAX_COUNT 16
#define IEEE80211_MAX_STATIONS 2007
#define IEEE80211_SSID_MAX_LENGTH 32
/* Radio type with value same of IEEE802.11 Radio Information Message Element */
#define IEEE80211_RADIO_TYPE_80211B 0x00000001
#define IEEE80211_RADIO_TYPE_80211A 0x00000002
#define IEEE80211_RADIO_TYPE_80211G 0x00000004
#define IEEE80211_RADIO_TYPE_80211N 0x00000008
/* */
#define IS_IEEE80211_FREQ_BG(x) (((x >= 2412) && (x <= 2484)) ? 1 : 0)
#define IS_IEEE80211_FREQ_A(x) ((((x >= 4915) && (x <= 4980)) || ((x >= 5035) && (x <= 5825))) ? 1 : 0)
/* Rate into multiple of 500Kbps */
#define IEEE80211_RATE_1M 2
#define IEEE80211_RATE_2M 4
#define IEEE80211_RATE_5_5M 11
#define IEEE80211_RATE_11M 22
#define IEEE80211_RATE_6M 12
#define IEEE80211_RATE_9M 18
#define IEEE80211_RATE_12M 24
#define IEEE80211_RATE_18M 36
#define IEEE80211_RATE_24M 48
#define IEEE80211_RATE_36M 72
#define IEEE80211_RATE_48M 96
#define IEEE80211_RATE_54M 108
#define IEEE80211_RATE_80211N 127
#define IS_IEEE80211_RATE_B(x) (((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M) || (x == IEEE80211_RATE_5_5M) || (x == IEEE80211_RATE_11M)) ? 1 : 0)
#define IS_IEEE80211_RATE_G(x) (((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M) || (x == IEEE80211_RATE_24M) || (x == IEEE80211_RATE_36M) || (x == IEEE80211_RATE_48M) || (x == IEEE80211_RATE_54M)) ? 1 : 0)
#define IS_IEEE80211_RATE_A(x) (((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M) || (x == IEEE80211_RATE_24M) || (x == IEEE80211_RATE_36M) || (x == IEEE80211_RATE_48M) || (x == IEEE80211_RATE_54M)) ? 1 : 0)
#define IS_IEEE80211_RATE_N(x) ((x == IEEE80211_RATE_80211N) ? 1 : 0)
#define IEEE80211_BASICRATE 128
#define IS_IEEE80211_BASICRATE_B(x) ((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M))
#define IS_IEEE80211_BASICRATE_G(x) ((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M))
#define IS_IEEE80211_BASICRATE_BG(x) ((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M) || (x == IEEE80211_RATE_5_5M) || (x == IEEE80211_RATE_11M))
#define IS_IEEE80211_BASICRATE_A(x) ((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_24M))
/* Frame control type */
#define IEEE80211_FRAMECONTROL_TYPE_MGMT 0
#define IEEE80211_FRAMECONTROL_TYPE_CTRL 1
#define IEEE80211_FRAMECONTROL_TYPE_DATA 2
/* Frame control Management subtype */
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST 0
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE 1
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST 2
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_RESPONSE 3
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST 4
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_RESPONSE 5
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_TIMING_ADV 6
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_BEACON 8
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ATIM 9
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION 10
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION 11
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION 12
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION 13
#define IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION_NOACK 14
/* Frame control Control subtype */
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CTRLWRAPPER 7
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_BLOCKACK_REQ 8
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_BLOCKACK 9
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_PSPOLL 10
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_RTS 11
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CTS 12
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_ACK 13
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CFEND 14
#define IEEE80211_FRAMECONTROL_CTRL_SUBTYPE_CFEND_CFACK 15
/* Frame control Data subtype */
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA 0
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA_CFACK 1
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA_CFPOLL 2
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_DATA_CFACK_CFPOLL 3
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_NULL 4
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_CFACK 5
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_CFPOLL 6
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_CFACK_CFPOLL 7
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA 8
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA_CFACK 9
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA_CFPOLL 10
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSDATA_CFACK_CFPOLL 11
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSNULL 12
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSCFPOLL 14
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSCFACK_CFPOLL 15
/* */
#define IEEE80211_FRAME_CONTROL_MASK_PROTOCOL_VERSION 0x0003
#define IEEE80211_FRAME_CONTROL_MASK_TYPE 0x000c
#define IEEE80211_FRAME_CONTROL_MASK_SUBTYPE 0x00f0
#define IEEE80211_FRAME_CONTROL_MASK_TODS 0x0100
#define IEEE80211_FRAME_CONTROL_MASK_FROMDS 0x0200
#define IEEE80211_FRAME_CONTROL_MASK_MORE_FRAGMENT 0x0400
#define IEEE80211_FRAME_CONTROL_MASK_RETRY 0x0800
#define IEEE80211_FRAME_CONTROL_MASK_POWER_MANAGEMENT 0x1000
#define IEEE80211_FRAME_CONTROL_MASK_MORE_DATA 0x2000
#define IEEE80211_FRAME_CONTROL_MASK_PROTECTED_FRAME 0x4000
#define IEEE80211_FRAME_CONTROL_MASK_ORDER 0x8000
#define IEEE80211_FRAME_CONTROL(type, stype) __cpu_to_le16((type << 2) | (stype << 4))
#define IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol) (((framecontrol) & IEEE80211_FRAME_CONTROL_MASK_TYPE) >> 2)
#define IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol) (((framecontrol) & IEEE80211_FRAME_CONTROL_MASK_SUBTYPE) >> 4)
/* IEEE802.11 Status Code */
#define IEEE80211_STATUS_SUCCESS 0
#define IEEE80211_STATUS_UNSPECIFIED_FAILURE 1
#define IEEE80211_STATUS_TDLS_WAKEUP_ALTERNATE 2
#define IEEE80211_STATUS_TDLS_WAKEUP_REJECT 3
#define IEEE80211_STATUS_SECURITY_DISABLED 5
#define IEEE80211_STATUS_UNACCEPTABLE_LIFETIME 6
#define IEEE80211_STATUS_NOT_IN_SAME_BSS 7
#define IEEE80211_STATUS_CAPS_UNSUPPORTED 10
#define IEEE80211_STATUS_REASSOCIATION_NO_ASSOCIATE 11
#define IEEE80211_STATUS_ASSOCIATION_DENIED_UNSPEC 12
#define IEEE80211_STATUS_NOT_SUPPORTED_AUTHENTICATION_ALGORITHM 13
#define IEEE80211_STATUS_UNKNOWN_AUTHENTICATION_TRANSACTION 14
#define IEEE80211_STATUS_CHALLENGE_FAIL 15
#define IEEE80211_STATUS_AUTHENTICATION_TIMEOUT 16
#define IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
#define IEEE80211_STATUS_ASSOCIATION_DENIED_RATES 18
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NOSHORT 19
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NOPBCC 20
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NOAGILITY 21
#define IEEE80211_STATUS_SPEC_MGMT_REQUIRED 22
#define IEEE80211_STATUS_PWR_CAPABILITY_NOT_VALID 23
#define IEEE80211_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_SHORT_SLOT_TIME 25
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_DSSS_OFDM 26
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_HT 27
#define IEEE80211_STATUS_R0KH_UNREACHABLE 28
#define IEEE80211_STATUS_ASSOCIATION_DENIED_NO_PCO 29
#define IEEE80211_STATUS_ASSOCIATION_REJECTED_TEMPORARILY 30
#define IEEE80211_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
#define IEEE80211_STATUS_UNSPECIFIED_QOS_FAILURE 32
#define IEEE80211_STATUS_QOS_INSUFFICIENT_BANDWIDTH 33
#define IEEE80211_STATUS_EXCESSIVE_FRAME_LOST 34
#define IEEE80211_STATUS_STA_NOT_SUPPORT_QOS_FACILITY 35
#define IEEE80211_STATUS_REQUEST_DECLINED 37
#define IEEE80211_STATUS_INVALID_PARAMETERS 38
#define IEEE80211_STATUS_REJECTED_WITH_SUGGESTED_CHANGES 39
#define IEEE80211_STATUS_INVALID_IE 40
#define IEEE80211_STATUS_GROUP_CIPHER_NOT_VALID 41
#define IEEE80211_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
#define IEEE80211_STATUS_AKMP_NOT_VALID 43
#define IEEE80211_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
#define IEEE80211_STATUS_INVALID_RSN_IE_CAPAB 45
#define IEEE80211_STATUS_CIPHER_REJECTED_PER_POLICY 46
#define IEEE80211_STATUS_TS_NOT_CREATED 47
#define IEEE80211_STATUS_DIRECT_LINK_NOT_ALLOWED 48
#define IEEE80211_STATUS_DEST_STA_NOT_PRESENT 49
#define IEEE80211_STATUS_DEST_STA_NOT_QOS_STA 50
#define IEEE80211_STATUS_ASSOCIATION_DENIED_LISTEN_INT_TOO_LARGE 51
#define IEEE80211_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
#define IEEE80211_STATUS_INVALID_PMKID 53
#define IEEE80211_STATUS_INVALID_MDIE 54
#define IEEE80211_STATUS_INVALID_FTIE 55
#define IEEE80211_STATUS_REQUEST_TCLAS_NOT_SUPPORTED 56
#define IEEE80211_STATUS_INSUFFICIENT_TCLAS 57
#define IEEE80211_STATUS_TS_NOT_BEEN_CREATED 58
#define IEEE80211_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59
#define IEEE80211_STATUS_NO_OUTSTANDING_GAS_REQ 60
#define IEEE80211_STATUS_GAS_RESP_NOT_RECEIVED 61
#define IEEE80211_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62
#define IEEE80211_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63
#define IEEE80211_STATUS_REQ_REFUSED_HOME 64
#define IEEE80211_STATUS_ADV_SRV_UNREACHABLE 65
#define IEEE80211_STATUS_REQ_REFUSED_SSPN 67
#define IEEE80211_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
#define IEEE80211_STATUS_INVALID_RSNIE 72
#define IEEE80211_STATUS_UAPSD_COEXISTENCE_NOT_SUPPORTED 73
#define IEEE80211_STATUS_REQUEST_UAPSD_COEXISTENCE_NOT_SUPPORTED 74
#define IEEE80211_STATUS_REQUEST_INTERVAL_NOT SUPPORTED 75
#define IEEE80211_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
#define IEEE80211_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
#define IEEE80211_STATUS_CANNOT_FIND_ALTERNATIVE_TBTT 78
#define IEEE80211_STATUS_TRANSMISSION_FAILURE 79
#define IEEE80211_STATUS_REQUYESTED_TCLAS_NOT_SUPPORTED 80
#define IEEE80211_STATUS_TCLAS_RESOURCES_EXHAUSTED 81
#define IEEE80211_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82
#define IEEE80211_STATUS_REFUSED_EXTERNAL_REASON 92
#define IEEE80211_STATUS_REFUSED_AP_OUT_OF_MEMORY 93
#define IEEE80211_STATUS_REJECTED_EMERGENCY_SERVICES_NOT_SUPPORTED 94
#define IEEE80211_STATUS_QUERY_RESPONSE_OUTSTANDING 95
#define IEEE80211_STATUS_MCCAOP_RESERVATION_CONFLICT 100
#define IEEE80211_STATUS_MAF_LIMIT_EXCEEDED 101
#define IEEE80211_STATUS_MCCA_TRACK_LIMIT_EXCEEDED 102
/* IEEE802.11 Reason code */
#define IEEE80211_REASON_UNSPECIFIED 1
#define IEEE80211_REASON_PREV_AUTH_NOT_VALID 2
#define IEEE80211_REASON_DEAUTH_LEAVING 3
#define IEEE80211_REASON_DISASSOC_DUE_TO_INACTIVITY 4
#define IEEE80211_REASON_DISASSOC_AP_BUSY 5
#define IEEE80211_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
#define IEEE80211_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
#define IEEE80211_REASON_DISASSOC_STA_HAS_LEFT 8
#define IEEE80211_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
#define IEEE80211_REASON_PWR_CAPABILITY_NOT_VALID 10
#define IEEE80211_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
#define IEEE80211_REASON_INVALID_IE 13
#define IEEE80211_REASON_MICHAEL_MIC_FAILURE 14
#define IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT 15
#define IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
#define IEEE80211_REASON_IE_IN_4WAY_DIFFERS 17
#define IEEE80211_REASON_GROUP_CIPHER_NOT_VALID 18
#define IEEE80211_REASON_PAIRWISE_CIPHER_NOT_VALID 19
#define IEEE80211_REASON_AKMP_NOT_VALID 20
#define IEEE80211_REASON_UNSUPPORTED_RSN_IE_VERSION 21
#define IEEE80211_REASON_INVALID_RSN_IE_CAPAB 22
#define IEEE80211_REASON_IEEE_802_1X_AUTH_FAILED 23
#define IEEE80211_REASON_CIPHER_SUITE_REJECTED 24
#define IEEE80211_REASON_TDLS_TEARDOWN_UNREACHABLE 25
#define IEEE80211_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
#define IEEE80211_REASON_DISASSOC_LOW_ACK 34
/* IEEE802.11 Authentication Algorithm */
#define IEEE80211_AUTHENTICATION_ALGORITHM_OPEN 0
#define IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY 1
#define IEEE80211_AUTHENTICATION_ALGORITHM_FAST_BSS 2
#define IEEE80211_AUTHENTICATION_ALGORITHM_SAE 3
/* */
#define IEEE80211_AID_FIELD 0xC000
#define IEEE80211_AID_MAX_VALUE 2007
/* */
#define IEEE80211_ERP_INFO_NON_ERP_PRESENT 0x01
#define IEEE80211_ERP_INFO_USE_PROTECTION 0x02
#define IEEE80211_ERP_INFO_BARKER_PREAMBLE_MODE 0x04
/* */
#define IEEE80211_CAPABILITY_ESS 0x0001
#define IEEE80211_CAPABILITY_IBSS 0x0002
#define IEEE80211_CAPABILITY_CFPOLLABLE 0x0004
#define IEEE80211_CAPABILITY_CFPOLLREQUEST 0x0008
#define IEEE80211_CAPABILITY_PRIVACY 0x0010
#define IEEE80211_CAPABILITY_SHORTPREAMBLE 0x0020
#define IEEE80211_CAPABILITY_PBCC 0x0040
#define IEEE80211_CAPABILITY_CHANNELAGILITY 0x0080
#define IEEE80211_CAPABILITY_SPECTRUMMAN 0x0100
#define IEEE80211_CAPABILITY_QOS 0x0200
#define IEEE80211_CAPABILITY_SHORTSLOTTIME 0x0400
#define IEEE80211_CAPABILITY_APSD 0x0800
#define IEEE80211_CAPABILITY_DSSS_OFDM 0x2000
#define IEEE80211_CAPABILITY_DELAYEDACK 0x4000
#define IEEE80211_CAPABILITY_IMMEDIATEACK 0x8000
/* 802.11 Packet - IEEE802.11 is a little-endian protocol */
struct ieee80211_header {
__le16 framecontrol;
__le16 durationid;
uint8_t address1[ETH_ALEN];
uint8_t address2[ETH_ALEN];
uint8_t address3[ETH_ALEN];
__le16 sequencecontrol;
} STRUCT_PACKED;
/* */
struct ieee80211_header_mgmt {
__le16 framecontrol;
__le16 durationid;
uint8_t da[ETH_ALEN];
uint8_t sa[ETH_ALEN];
uint8_t bssid[ETH_ALEN];
__le16 sequencecontrol;
union {
struct {
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
uint8_t ie[0];
} STRUCT_PACKED beacon;
struct {
uint8_t ie[0];
} STRUCT_PACKED proberequest;
struct {
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
uint8_t ie[0];
} STRUCT_PACKED proberesponse;
struct {
__le16 algorithm;
__le16 transactionseqnumber;
__le16 statuscode;
uint8_t ie[0];
} STRUCT_PACKED authetication;
struct {
__le16 capability;
__le16 listeninterval;
uint8_t ie[0];
} STRUCT_PACKED associationrequest;
struct {
__le16 capability;
__le16 statuscode;
__le16 aid;
uint8_t ie[0];
} STRUCT_PACKED associationresponse;
struct {
__le16 capability;
__le16 listeninterval;
uint8_t currentap[6];
uint8_t ie[0];
} STRUCT_PACKED reassociationrequest;
struct {
__le16 capability;
__le16 statuscode;
__le16 aid;
uint8_t ie[0];
} STRUCT_PACKED reassociationresponse;
struct {
__le16 reasoncode;
uint8_t ie[0];
} STRUCT_PACKED deauthetication;
struct {
__le16 reasoncode;
uint8_t ie[0];
} STRUCT_PACKED disassociation;
};
} STRUCT_PACKED;
/* 802.11 Generic information element */
struct ieee80211_ie {
uint8_t id;
uint8_t len;
} STRUCT_PACKED;
/* 802.11 SSID information element */
#define IEEE80211_IE_SSID 0
#define IEEE80211_IE_SSID_MAX_LENGTH 32
struct ieee80211_ie_ssid {
uint8_t id;
uint8_t len;
uint8_t ssid[0];
} STRUCT_PACKED;
/* 802.11 Supported Rates information element */
#define IEEE80211_IE_SUPPORTED_RATES 1
#define IEEE80211_IE_SUPPORTED_RATES_MIN_LENGTH 1
#define IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH 8
struct ieee80211_ie_supported_rates {
uint8_t id;
uint8_t len;
uint8_t rates[0];
} STRUCT_PACKED;
/* 802.11 DSSS information element */
#define IEEE80211_IE_DSSS 3
#define IEEE80211_IE_DSSS_LENGTH 1
struct ieee80211_ie_dsss {
uint8_t id;
uint8_t len;
uint8_t channel;
} STRUCT_PACKED;
/* 802.11 Country information element */
#define IEEE80211_IE_COUNTRY 7
#define IEEE80211_IE_COUNTRY_MIN_LENGTH 6
struct ieee80211_ie_country_channelgroup {
uint8_t firstchannel;
uint8_t numberchannels;
uint8_t maxtxpower;
} STRUCT_PACKED;
struct ieee80211_ie_country {
uint8_t id;
uint8_t len;
uint8_t country[3];
uint8_t channelgroup[0];
} STRUCT_PACKED;
/* 802.11 Challenge text information element */
#define IEEE80211_IE_CHALLENGE_TEXT 16
#define IEEE80211_IE_CHALLENGE_TEXT_MIN_LENGTH 3
struct ieee80211_ie_challenge_text {
uint8_t id;
uint8_t len;
uint8_t challengetext[0];
} STRUCT_PACKED;
/* 802.11 ERP information element */
#define IEEE80211_IE_ERP 42
#define IEEE80211_IE_ERP_LENGTH 1
struct ieee80211_ie_erp {
uint8_t id;
uint8_t len;
uint8_t params;
} STRUCT_PACKED;
/* 802.11 RSN information element */
#define IEEE80211_IE_RSN_INFORMATION 48
/* cipher suite selectors */
#define IEEE80211_CIPHER_SUITE_USE_GROUP 0x000FAC00
#define IEEE80211_CIPHER_SUITE_WEP40 0x000FAC01
#define IEEE80211_CIPHER_SUITE_TKIP 0x000FAC02
/* reserved: 0x000FAC03 */
#define IEEE80211_CIPHER_SUITE_CCMP 0x000FAC04
#define IEEE80211_CIPHER_SUITE_WEP104 0x000FAC05
#define IEEE80211_CIPHER_SUITE_AES_CMAC 0x000FAC06
#define IEEE80211_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
#define IEEE80211_CIPHER_SUITE_GCMP 0x000FAC08
#define IEEE80211_CIPHER_SUITE_GCMP_256 0x000FAC09
#define IEEE80211_CIPHER_SUITE_CCMP_256 0x000FAC0A
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
#define IEEE80211_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
/* 802.11 Extended Supported Rates information element */
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1
struct ieee80211_ie_extended_supported_rates {
uint8_t id;
uint8_t len;
uint8_t rates[0];
} STRUCT_PACKED;
/* 802.11 EDCA Parameter Set information element */
#define IEEE80211_IE_EDCA_PARAMETER_SET 12
#define IEEE80211_IE_EDCA_PARAMETER_SET_LENGTH 18
#define EDCA_PARAMETER_RECORD_AC_BE_FIELD 0
#define EDCA_PARAMETER_RECORD_AC_BK_FIELD 1
#define EDCA_PARAMETER_RECORD_AC_VI_FIELD 2
#define EDCA_PARAMETER_RECORD_AC_VO_FIELD 3
struct ieee80211_ie_edca_parameter_set {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 QoS Capability information element */
#define IEEE80211_IE_QOS_CAPABILITY 46
#define IEEE80211_IE_QOS_CAPABILITY_LENGTH 1
struct ieee80211_ie_qos_capability {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 Power Constraint information element */
#define IEEE80211_IE_POWER_CONSTRAINT 32
#define IEEE80211_IE_POWER_CONSTRAINT_LENGTH 1
struct ieee80211_ie_power_constraint {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 SSID List */
#define IEEE80211_IE_SSID_LIST 84
struct ieee80211_ie_ssid_list {
uint8_t id;
uint8_t len;
uint8_t lists[0];
} STRUCT_PACKED;
/* 802.11 Vendor Specific */
#define IEEE80211_IE_VENDOR_SPECIFIC 221
#define MICROSOFT_OUI 0x0050F2
struct ieee80211_ie_vendor_specific {
uint8_t id;
uint8_t len;
uint8_t oui[3];
uint8_t oui_type;
int8_t oui_subtype;
} STRUCT_PACKED;
#define WMM_TYPE 2
#define WMM_INFORMATION_ELEMENT 0
#define WMM_PARAMETER_ELEMENT 1
struct ieee80211_ie_wmm_information_element {
uint8_t id;
uint8_t len;
uint8_t oui[3];
uint8_t oui_type;
uint8_t oui_subtype;
uint8_t version;
uint8_t qos_info;
} STRUCT_PACKED;
#define IEEE80211_HT_MCS_MASK_LEN 10
struct ieee80211_mcs_info {
uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN];
uint16_t rx_highest;
uint8_t tx_params;
uint8_t reserved[3];
} STRUCT_PACKED;
/**
* struct ieee80211_ht_cap - HT capabilities
*
* This structure is the "HT capabilities element" as
* described in 802.11n D5.0 7.3.2.57
*/
#define IEEE80211_IE_HT_CAPABILITY 45
struct ieee80211_ht_cap {
uint16_t cap_info;
uint8_t ampdu_params_info;
/* 16 bytes MCS information */
struct ieee80211_mcs_info mcs;
uint16_t extended_ht_cap_info;
uint32_t tx_BF_cap_info;
uint8_t antenna_selection_info;
} STRUCT_PACKED;
struct ieee80211_ie_ht_cap {
uint8_t id;
uint8_t len;
struct ieee80211_ht_cap ht_cap;
} STRUCT_PACKED;
/* 802.11n HT capabilities masks (for cap_info) */
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
#define IEEE80211_HT_CAP_SGI_20 0x0020
#define IEEE80211_HT_CAP_SGI_40 0x0040
#define IEEE80211_HT_CAP_TX_STBC 0x0080
#define IEEE80211_HT_CAP_RX_STBC 0x0300
#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
#define IEEE80211_HT_CAP_RESERVED 0x2000
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
/**
* struct ieee80211_ht_operation - HT operation IE
*
* This structure is the "HT operation element" as
* described in 802.11n-2009 7.3.2.57
*/
#define IEEE80211_IE_HT_OPERATION 61
struct ieee80211_ht_operation {
uint8_t id;
uint8_t len;
uint8_t primary_chan;
uint8_t ht_param;
uint16_t operation_mode;
uint16_t stbc_param;
uint8_t basic_set[16];
} STRUCT_PACKED;
/* 802.11 All information elements */
struct ieee80211_ie_items {
struct ieee80211_ie_ssid *ssid;
struct ieee80211_ie_supported_rates *supported_rates;
struct ieee80211_ie_dsss *dsss;
struct ieee80211_ie_country *country;
struct ieee80211_ie_challenge_text *challenge_text;
struct ieee80211_ie_erp *erp;
struct ieee80211_ie_extended_supported_rates *extended_supported_rates;
struct ieee80211_ie_edca_parameter_set *edca_parameter_set;
struct ieee80211_ie_qos_capability *qos_capability;
struct ieee80211_ie_power_constraint *power_constraint;
struct ieee80211_ie_ssid_list *ssid_list;
struct ieee80211_ie_wmm_information_element *wmm_ie;
struct ieee80211_ie_ht_cap *ht_cap;
struct ieee80211_ht_operation *ht_oper;
};
/* IEEE 802.11 functions */
uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble);
/* Management Beacon */
#define IEEE80221_CREATE_BEACON_FLAGS_PROBE_RESPONSE_OFFLOAD 0x00000001
struct ieee80211_beacon_params {
unsigned long flags;
uint8_t* headbeacon;
int headbeaconlength;
uint8_t* tailbeacon;
int tailbeaconlength;
uint8_t bssid[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
const char* ssid;
int ssid_hidden;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
uint8_t channel;
uint32_t mode;
uint8_t erpinfo;
int beacon_ies_len;
uint8_t *beacon_ies;
int response_ies_len;
uint8_t *response_ies;
uint8_t* proberesponseoffload;
int proberesponseoffloadlength;
};
int ieee80211_create_beacon(uint8_t* buffer, int length, struct ieee80211_beacon_params* params);
/* Management Probe Response */
struct ieee80211_probe_response_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
const char* ssid;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
uint8_t channel;
uint32_t mode;
uint8_t erpinfo;
int response_ies_len;
uint8_t *response_ies;
};
int ieee80211_create_probe_response(uint8_t* buffer, int length, struct ieee80211_probe_response_params* params);
/* Management Authentication */
struct ieee80211_authentication_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t algorithm;
uint16_t transactionseqnumber;
uint16_t statuscode;
};
int ieee80211_create_authentication_response(uint8_t* buffer, int length, struct ieee80211_authentication_params* params);
/* Management Association Response */
struct ieee80211_associationresponse_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t capability;
uint16_t statuscode;
uint16_t aid;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
int response_ies_len;
uint8_t *response_ies;
};
int ieee80211_create_associationresponse_response(uint8_t* buffer, int length, struct ieee80211_associationresponse_params* params);
/* Management Deauthentication */
struct ieee80211_deauthentication_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t reasoncode;
};
int ieee80211_create_deauthentication(uint8_t* buffer, int length, struct ieee80211_deauthentication_params* params);
/* Management Disassociation */
struct ieee80211_disassociation_params {
uint8_t bssid[ETH_ALEN];
uint8_t station[ETH_ALEN];
uint16_t reasoncode;
};
int ieee80211_create_disassociation(uint8_t* buffer, int length, struct ieee80211_disassociation_params* params);
/* Utils */
int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length);
unsigned long ieee80211_frequency_to_channel(uint32_t freq);
int ieee80211_is_broadcast_addr(const uint8_t* addr);
/* */
const uint8_t* ieee80211_get_sa_addr(const struct ieee80211_header* header);
const uint8_t* ieee80211_get_da_addr(const struct ieee80211_header* header);
const uint8_t* ieee80211_get_bssid_addr(const struct ieee80211_header* header);
/* */
#define IEEE80211_VALID_SSID 1
#define IEEE80211_WILDCARD_SSID 0
#define IEEE80211_WRONG_SSID -1
int ieee80211_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist);
/* IEEE802.11 Aid management */
#define IEEE80211_AID_BITFIELD_SIZE 63
int ieee80211_aid_create(uint32_t* aidbitfield, uint16_t* aid);
void ieee80211_aid_free(uint32_t* aidbitfield, uint16_t aid);
#endif /* __CAPWAP_IEEE802_11_HEADER__ */

View File

@ -1,93 +0,0 @@
#include "capwap.h"
/* Helper exit */
void capwap_exit(int errorcode) {
exit(errorcode);
}
/* 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(strlen(source) + 1);
strcpy(clone, source);
return clone;
}
/* Buffer clone */
void* capwap_clone(const void* buffer, int buffersize) {
void* bufferclone;
ASSERT(buffer != NULL);
ASSERT(buffersize > 0);
bufferclone = capwap_alloc(buffersize);
return memcpy(bufferclone, buffer, buffersize);
}
/* */
void capwap_daemon(void) {
int fd;
pid_t pid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
capwap_exit(CAPWAP_DAEMON_ERROR);
} else if (pid > 0) {
capwap_exit(CAPWAP_SUCCESSFUL);
}
/* Change the file mode mask */
umask(0);
/* Create a new SID for the child process */
if (setsid() < 0) {
capwap_exit(CAPWAP_DAEMON_ERROR);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
capwap_exit(CAPWAP_DAEMON_ERROR);
}
/* Redirect the standard file descriptors to /dev/null */
fd = open("/dev/null", 0);
if (fd == -1) {
capwap_exit(CAPWAP_DAEMON_ERROR);
}
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);
}
/* */
char* capwap_itoa(int input, char* output) {
sprintf(output, "%d", input);
return output;
}
/* */
char* capwap_ltoa(long input, char* output) {
sprintf(output, "%ld", input);
return output;
}

View File

@ -1,91 +0,0 @@
#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 <sys/ioctl.h>
#include <netdb.h>
#include <sys/time.h>
#include <net/if.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Endian */
#if __BYTE_ORDER == __BIG_ENDIAN
#define CAPWAP_BIG_ENDIAN
#else
#define CAPWAP_LITTLE_ENDIAN
#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
/* Opaque type */
#define DECLARE_OPAQUE_TYPE(name) struct name##__opaque__ { int unused; }; typedef struct name##__opaque__* name
/* UDPLite */
#ifdef HAVE_NETINET_UDPLITE_H
#include <netinet/udplite.h>
#else
#ifndef IPPROTO_UDPLITE
#define IPPROTO_UDPLITE 136
#endif
#ifndef SOL_UDPLITE
#define SOL_UDPLITE 136
#endif
#ifndef UDPLITE_SEND_CSCOV
#define UDPLITE_SEND_CSCOV 10
#endif
#endif
/* standard include */
#include "capwap_rfc.h"
#include "capwap_logging.h"
#include "capwap_debug.h"
#include "capwap_error.h"
#include "capwap_timeout.h"
/* Helper exit */
void capwap_exit(int errorcode);
/* Random generator */
void capwap_init_rand(void);
int capwap_get_rand(int max);
/* */
void capwap_daemon(void);
/* */
#define capwap_outofmemory() do { \
log_printf(LOG_EMERG, "Out of memory %s(%d)", __FILE__, __LINE__); \
capwap_exit(CAPWAP_OUT_OF_MEMORY); \
} while(0)
/* Helper buffer copy */
char* capwap_duplicate_string(const char* source);
void* capwap_clone(const void* buffer, int buffersize);
/* */
char* capwap_itoa(int input, char* output);
char* capwap_ltoa(long input, char* output);
#endif /* __CAPWAP_HEADER__ */

View File

@ -1,91 +0,0 @@
#include "capwap.h"
#include "capwap_array.h"
/* */
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount, int zeroed) {
struct capwap_array* array;
ASSERT(itemsize > 0);
array = (struct capwap_array*)capwap_alloc(sizeof(struct capwap_array));
memset(array, 0, sizeof(struct capwap_array));
array->itemsize = itemsize;
array->zeroed = zeroed;
if (initcount > 0) {
capwap_array_resize(array, initcount);
}
return array;
}
/* */
struct capwap_array* capwap_array_clone(struct capwap_array* array) {
struct capwap_array* clone;
ASSERT (array != NULL);
/* Clone array e items */
clone = capwap_array_create(array->itemsize, array->count, array->zeroed);
memcpy(clone->buffer, array->buffer, array->itemsize * array->count);
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) {
int newcount;
void* newbuffer = NULL;
ASSERT(array != NULL);
ASSERT(array->itemsize > 0);
if (array->count == count) {
return;
}
newcount = min(array->count, count);
if (count > 0) {
newbuffer = capwap_alloc(array->itemsize * count);
/* Zeroed new items */
if (array->zeroed && (count > newcount)) {
memset(newbuffer + array->itemsize * newcount, 0, array->itemsize * (count - newcount));
}
}
if (array->buffer) {
if ((newbuffer != NULL) && (newcount > 0)) {
memcpy(newbuffer, array->buffer, array->itemsize * newcount);
}
capwap_free(array->buffer);
}
array->buffer = newbuffer;
array->count = count;
}

View File

@ -1,17 +0,0 @@
#ifndef __CAPWAP_ARRAY_HEADER__
#define __CAPWAP_ARRAY_HEADER__
struct capwap_array {
void* buffer;
unsigned short itemsize;
unsigned long count;
int zeroed;
};
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount, int zeroed);
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);
#endif /* __CAPWAP_ARRAY_HEADER__ */

View File

@ -1,178 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef USE_DEBUG_BACKTRACE
#include <execinfo.h>
#endif
#include "capwap_logging.h"
#include "capwap_error.h"
#define BACKTRACE_BUFFER 256
/* Memory block */
struct capwap_memory_block {
void* item;
size_t size;
const char* file;
int line;
#ifdef USE_DEBUG_BACKTRACE
void* backtrace[BACKTRACE_BUFFER];
int backtrace_count;
#endif
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) {
log_printf(LOG_DEBUG, "%s(%d): Invalid memory size %zu", file, line, size);
exit(CAPWAP_ASSERT_CONDITION);
}
/* Alloc block with memory block */
block = (struct capwap_memory_block*)malloc(sizeof(struct capwap_memory_block) + size);
if (!block) {
log_printf(LOG_DEBUG, "Out of memory %s(%d)", file, line);
exit(CAPWAP_OUT_OF_MEMORY);
}
/* Info memory block */
block->item = (void*)(((char*)block) + sizeof(struct capwap_memory_block));
block->size = size;
block->file = file;
block->line = line;
#ifdef USE_DEBUG_BACKTRACE
block->backtrace_count = backtrace(block->backtrace, BACKTRACE_BUFFER);
#endif
block->next = g_memoryblocks;
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) {
log_printf(LOG_DEBUG, "%s(%d): Free NULL pointer", file, line);
exit(CAPWAP_ASSERT_CONDITION);
}
/* Memory block */
if ((size_t)p <= sizeof(struct capwap_memory_block)) {
log_printf(LOG_DEBUG, "%s(%d): Invalid pointer", file, line);
exit(CAPWAP_ASSERT_CONDITION);
}
block = (struct capwap_memory_block*)((char*)p - sizeof(struct capwap_memory_block));
if (block->item != p) {
log_printf(LOG_DEBUG, "%s(%d): Invalid pointer", file, line);
exit(CAPWAP_ASSERT_CONDITION);
}
/* 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;
}
log_printf(LOG_DEBUG, "%s(%d): Unable to find memory block", file, line);
}
/* Dump memory alloced */
void capwap_dump_memory(void) {
#ifdef USE_DEBUG_BACKTRACE
char** backtrace_functions;
#endif
struct capwap_memory_block* findblock;
findblock = g_memoryblocks;
while (findblock != NULL) {
log_printf(LOG_DEBUG, "%s(%d): block at %p, %zu bytes long",
findblock->file, findblock->line, findblock->item, findblock->size);
#ifdef USE_DEBUG_BACKTRACE
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++) {
log_printf(LOG_DEBUG, "\t%s", backtrace_functions[j]);
}
free(backtrace_functions);
}
#endif
/* Next */
findblock = findblock->next;
}
}
/* Check if all memory is free */
int capwap_check_memory_leak(int verbose) {
if ((g_memoryblocks != NULL) && (verbose != 0)) {
log_printf(LOG_DEBUG, "*** Detected memory leaks ! ***");
capwap_dump_memory();
log_printf(LOG_DEBUG, "*******************************");
}
return ((g_memoryblocks != NULL) ? 1 : 0);
}
/* Backtrace call stack */
#ifdef USE_DEBUG_BACKTRACE
void capwap_backtrace_callstack(void) {
int i;
int count;
char** functions;
void* buffer[BACKTRACE_BUFFER];
/* */
count = backtrace(buffer, BACKTRACE_BUFFER);
if (count) {
functions = backtrace_symbols(buffer, count);
if (functions) {
/* Skipping capwap_backtrace_callstack function print out */
for (i = 1; i < count; i++) {
log_printf(LOG_DEBUG, "\t%s", functions[i]);
}
free(functions);
}
}
}
#endif

View File

@ -1,39 +0,0 @@
#ifndef __CAPWAP_DEBUG_HEADER__
#define __CAPWAP_DEBUG_HEADER__
#ifdef DEBUG
#define ASSERT(expr) if (!(expr)) { log_printf(LOG_EMERG, "Assertion failed \'%s\': %s(%d)", #expr, __FILE__, __LINE__); capwap_exit(CAPWAP_ASSERT_CONDITION); }
/* 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);
#ifdef USE_DEBUG_BACKTRACE
void capwap_backtrace_callstack(void);
#else
#define capwap_backtrace_callstack()
#endif
#else
#define DEBUG_BREAKPOINT()
#define ASSERT(expr)
/* Standard memory management */
#define capwap_alloc(l) ({ void* __x = malloc(l); if (!__x) capwap_outofmemory(); __x; })
#define capwap_free(x) free(x)
#define capwap_check_memory_leak(x) (0)
#define capwap_dump_memory()
#define capwap_backtrace_callstack()
#endif
#endif /* __CAPWAP_DEBUG_HEADER__ */

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