diff --git a/conf/wtp.conf b/conf/wtp.conf index c7bfa8c..b10e971 100755 --- a/conf/wtp.conf +++ b/conf/wtp.conf @@ -1,110 +1,110 @@ -# WTP configuration file - -version = "1.0"; - -application: { - name = "wtp 1"; - - location = "Ufficio"; - - binding = "802.11"; - - tunnelmode: { - nativeframe = false; - ethframe = false; - localbridging = false; - }; - - mactype = "localmac"; - - boardinfo: { - idvendor = 123456; - - element = ( - { name = "model"; value = "1.0"; }, - { name = "serial"; value = "2.0"; }, - { name = "id"; value = "3.0"; }, - { name = "revision"; value = "4.0"; }, - { name = "macaddress"; type = "interface"; value = "eth1"; } - ); - }; - - descriptor: { - radio = ( - { device = "wifi0"; type = "bg"; status = "enabled"; } - ); - - encryption = [ - "802.11_AES", - "802.11_TKIP" - ]; - - info = ( - { idvendor = 23456; type = "hardware"; value = "abcde"; }, - { idvendor = 33457; type = "software"; value = "fghil"; }, - { idvendor = 43458; type = "boot"; value = "mnopq"; }, - { idvendor = 53459; type = "other"; value = "qwert"; } - ); - }; - - ecn = "limited"; - - timer: { - statistics = 120; - }; - - dtls: { - enable = true; - - dtlspolicy: { - cleardatachannel = true; - dtlsdatachannel = true; - }; - - type = "x509"; - - presharedkey: { - # TODO - }; - - x509: { - calist = "/etc/capwap/ca.crt"; - certificate = "/etc/capwap/wtp.crt"; - privatekey = "/etc/capwap/wtp.key"; - privatekeypassword = ""; - }; - }; - - network: { - #binding = "eth1"; - mtu = 1500; - - port = 10000; - transport = "udp"; - - ipv4 = true; - ipv6 = false; - ipdualstack = true; - }; - - acdiscovery: { - search = false; - host = [ - "127.0.0.1" - ]; - }; - - acprefered: { - host = [ - "127.0.0.1" - ]; - }; -}; - -logging: { - enable = true; - level = "debug"; - output = ( - { mode = "stdout"; } - ); -}; +# WTP configuration file + +version = "1.0"; + +application: { + name = "wtp 1"; + + location = "Ufficio"; + + binding = "802.11"; + + tunnelmode: { + nativeframe = false; + ethframe = false; + localbridging = false; + }; + + mactype = "localmac"; + + boardinfo: { + idvendor = 123456; + + element = ( + { name = "model"; value = "1.0"; }, + { name = "serial"; value = "2.0"; }, + { name = "id"; value = "3.0"; }, + { name = "revision"; value = "4.0"; }, + { name = "macaddress"; type = "interface"; value = "eth1"; } + ); + }; + + descriptor: { + radio = ( + { device = "phy0"; driver = "nl80211"; type = "bg"; status = "enabled"; } + ); + + encryption = [ + "802.11_AES", + "802.11_TKIP" + ]; + + info = ( + { idvendor = 23456; type = "hardware"; value = "abcde"; }, + { idvendor = 33457; type = "software"; value = "fghil"; }, + { idvendor = 43458; type = "boot"; value = "mnopq"; }, + { idvendor = 53459; type = "other"; value = "qwert"; } + ); + }; + + ecn = "limited"; + + timer: { + statistics = 120; + }; + + dtls: { + enable = true; + + dtlspolicy: { + cleardatachannel = true; + dtlsdatachannel = true; + }; + + type = "x509"; + + presharedkey: { + # TODO + }; + + x509: { + calist = "/etc/capwap/ca.crt"; + certificate = "/etc/capwap/wtp.crt"; + privatekey = "/etc/capwap/wtp.key"; + privatekeypassword = ""; + }; + }; + + network: { + #binding = "eth1"; + mtu = 1500; + + port = 10000; + transport = "udp"; + + ipv4 = true; + ipv6 = false; + ipdualstack = true; + }; + + acdiscovery: { + search = false; + host = [ + "127.0.0.1" + ]; + }; + + acprefered: { + host = [ + "127.0.0.1" + ]; + }; +}; + +logging: { + enable = true; + level = "debug"; + output = ( + { mode = "stdout"; } + ); +}; diff --git a/configure.ac b/configure.ac index 58d138d..0ae4529 100644 --- a/configure.ac +++ b/configure.ac @@ -96,7 +96,7 @@ AC_ARG_WITH( # WTP drivers wifi binding AC_ARG_ENABLE( [wifi-drivers-nl80211], - [AS_HELP_STRING([--wifi-drivers-nl80211], [disable WTP support for nl80211 wifi binding @<:@default=yes@:>@])], + [AS_HELP_STRING([--disable-wifi-drivers-nl80211], [disable WTP support for nl80211 wifi binding @<:@default=yes@:>@])], , [enable_wifi_drivers_nl80211="yes"] ) @@ -115,6 +115,7 @@ if test "${enable_debug}" = "yes"; then CFLAGS="${CFLAGS} -DDEBUG -Wall -Werror -g -O0" else CFLAGS="${CFLAGS} -O2" + AC_DEFINE([DISABLE_LOGGING_DEBUG], [1], [Disable logging debug]) fi # @@ -231,7 +232,6 @@ PKG_CHECK_MODULES( )] )] ) -test "$has_libnl_ver" -gt 1 && if test "${enable_wifi_drivers_nl80211}" = "yes"; then AC_CHECK_HEADERS([netlink/genl/genl.h netlink/genl/family.h netlink/genl/ctrl.h], [], [AC_MSG_ERROR(You need the netlink header)]) diff --git a/src/binding/wifi/drivers/wifi_drivers.c b/src/binding/wifi/drivers/wifi_drivers.c index b0dc6a7..966e10e 100644 --- a/src/binding/wifi/drivers/wifi_drivers.c +++ b/src/binding/wifi/drivers/wifi_drivers.c @@ -1,11 +1,5 @@ #include "wifi_drivers.h" - -/* */ -struct wifi_driver_instance { - struct wifi_driver_ops* ops; /* Driver functions */ - - wifi_global_handle handle; /* Global instance handle */ -}; +#include "capwap_array.h" /* Declare enable wifi driver */ #ifdef ENABLE_WIFI_DRIVERS_NL80211 @@ -19,30 +13,93 @@ static struct wifi_driver_instance wifi_driver[] = { { NULL } }; +/* Radio instance */ +static struct capwap_array* wifi_device = NULL; + /* */ int wifi_init_driver(void) { int i; for (i = 0; wifi_driver[i].ops != NULL; i++) { - if (!wifi_driver[i].ops->global_init) { - return -1; - } - /* Initialize driver */ + ASSERT(wifi_driver[i].ops->global_init != NULL); wifi_driver[i].handle = wifi_driver[i].ops->global_init(); } + /* Device handler */ + wifi_device = capwap_array_create(sizeof(struct wifi_device), 0); + wifi_device->zeroed = 1; + return 0; } /* */ void wifi_free_driver(void) { - int i; + unsigned long i; + /* Free device */ + if (wifi_device) { + for (i = 0; i < wifi_device->count; i++) { + struct wifi_device* device = (struct wifi_device*)capwap_array_get_item_pointer(wifi_device, i); + if (device->instance->ops->device_deinit) { + device->instance->ops->device_deinit(device->handle); + } + } + + capwap_array_free(wifi_device); + } + + /* Free driver */ for (i = 0; wifi_driver[i].ops != NULL; i++) { - /* Free driver */ if (wifi_driver[i].ops->global_deinit) { wifi_driver[i].ops->global_deinit(wifi_driver[i].handle); } } } + +/* */ +int wifi_create_device(int radioid, char* ifname, char* driver) { + int i; + int length; + int result = -1; + + ASSERT(radioid > 0); + ASSERT(ifname != NULL); + ASSERT(driver != NULL); + + /* Check */ + length = strlen(ifname); + if ((length <= 0) || (length >= IFNAMSIZ)) { + capwap_logging_warning("Wifi device name error: %s", ifname); + return -1; + } else if (wifi_device->count >= radioid) { + capwap_logging_warning("Wifi device RadioID already used: %d", radioid); + return -1; + } + + /* Search driver */ + for (i = 0; wifi_driver[i].ops != NULL; i++) { + if (!strcmp(driver, wifi_driver[i].ops->name)) { + wifi_device_handle devicehandle; + struct device_init_params params = { + .ifname = ifname + }; + + /* Device init */ + ASSERT(wifi_driver[i].ops->device_init); + devicehandle = wifi_driver[i].ops->device_init(wifi_driver[i].handle, ¶ms); + if (devicehandle) { + /* Register new device */ + struct wifi_device* device = (struct wifi_device*)capwap_array_get_item_pointer(wifi_device, radioid); + device->handle = devicehandle; + device->instance = &wifi_driver[i]; + + result = 0; + } + + break; + } + } + + return result; +} diff --git a/src/binding/wifi/drivers/wifi_drivers.h b/src/binding/wifi/drivers/wifi_drivers.h index 9d55140..67281b3 100644 --- a/src/binding/wifi/drivers/wifi_drivers.h +++ b/src/binding/wifi/drivers/wifi_drivers.h @@ -8,10 +8,14 @@ #include #include #include +#include #include "capwap_debug.h" #include "capwap_logging.h" +/* */ +#define WIFI_DRIVER_NAME_SIZE 16 + /* */ typedef void* wifi_global_handle; typedef void* wifi_device_handle; @@ -35,8 +39,23 @@ struct wifi_driver_ops { void (*device_deinit)(wifi_device_handle handle); }; +/* */ +struct wifi_driver_instance { + struct wifi_driver_ops* ops; /* Driver functions */ + wifi_global_handle handle; /* Global instance handle */ +}; + +/* */ +struct wifi_device { + wifi_device_handle handle; /* Device handle */ + struct wifi_driver_instance* instance; /* Driver instance */ +}; + /* Initialize wifi driver engine */ int wifi_init_driver(void); void wifi_free_driver(void); +/* */ +int wifi_create_device(int radioid, char* ifname, char* driver); + #endif /* __WIFI_DRIVERS_HEADER__ */ diff --git a/src/binding/wifi/drivers/wifi_nl80211.c b/src/binding/wifi/drivers/wifi_nl80211.c index 9d0649a..9b8950b 100644 --- a/src/binding/wifi/drivers/wifi_nl80211.c +++ b/src/binding/wifi/drivers/wifi_nl80211.c @@ -1,14 +1,17 @@ #include "wifi_drivers.h" #include #include +#include #include #include #include #include +#include "capwap_list.h" +#include "wifi_nl80211.h" + /* Compatibility functions */ #if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30) -#define nl_sock nl_handle static uint32_t port_bitmap[32] = { 0 }; static struct nl_sock* nl_socket_alloc_cb(void* cb) { @@ -42,21 +45,275 @@ static void nl_socket_free(struct nl_sock* handle) { #endif /* */ -wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) { - return NULL; +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; } /* */ -void nl80211_device_deinit(wifi_device_handle handle) { +static int nl80211_no_seq_check(struct nl_msg* msg, void* arg) { + return NL_OK; +} + +/* */ +static int nl80211_error_handler(struct sockaddr_nl* nla, struct nlmsgerr* err, void* arg) { + *((int*)arg) = err->error; + return NL_STOP; +} + +/* */ +static int nl80211_finish_handler(struct nl_msg* msg, void* arg) { + *((int*)arg) = 0; + return NL_SKIP; +} + +/* */ +static int nl80211_ack_handler(struct nl_msg* msg, void* arg) { + *((int*)arg) = 0; + return NL_STOP; +} + +/* */ +static int nl80211_send_and_recv(struct nl_sock* nl, struct nl_cb* nl_cb, struct nl_msg* msg, nl_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; + } + + /* Complete send message */ + result = nl_send_auto_complete(nl, msg); + if (result < 0) { + nl_cb_put(cb); + return -1; + } + + /* Customize message callback */ + nl_cb_err(cb, NL_CB_CUSTOM, nl80211_error_handler, &result); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_finish_handler, &result); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl80211_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); + } + + nl_cb_put(cb); + return result; +} + +/* */ +static int nl80211_send_and_recv_msg(struct nl80211_global_handle* globalhandle, struct nl_msg* msg, nl_valid_cb valid_cb, void* data) { + return nl80211_send_and_recv(globalhandle->nl, globalhandle->nl_cb, msg, valid_cb, data); +} + +/* */ +static int cb_get_phydevice_list(struct nl_msg* msg, void* data) { + struct nlattr* tb_msg[NL80211_ATTR_MAX + 1]; + struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct capwap_list* list = (struct capwap_list*)data; + + nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + + if (tb_msg[NL80211_ATTR_WIPHY_NAME] && tb_msg[NL80211_ATTR_WIPHY]) { + struct capwap_list_item* item = capwap_itemlist_create(sizeof(struct nl80211_phydevice_item)); + struct nl80211_phydevice_item* phyitem = (struct nl80211_phydevice_item*)item->item; + + /* Add physical device info */ + phyitem->index = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]); + strcpy(phyitem->name, nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME])); + capwap_itemlist_insert_after(list, NULL, item); + } + + return NL_SKIP; +} + +/* */ +static int nl80211_get_phydevice_list(struct nl80211_global_handle* globalhandle, struct capwap_list* list) { + int result; + struct nl_msg* msg; + + ASSERT(globalhandle != NULL); + ASSERT(list != NULL); + + /* */ + msg = nlmsg_alloc(); + if (!msg) { + return -1; + } + + /* Retrieve list of physical device */ + genlmsg_put(msg, 0, 0, globalhandle->nl80211_id, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0); + + /* Retrieve all physical interface */ + result = nl80211_send_and_recv_msg(globalhandle, msg, cb_get_phydevice_list, list); + + /* */ + nlmsg_free(msg); + return result; +} + +/* */ +static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) { + int result; + struct capwap_list* list; + struct capwap_list_item* item; + struct nl80211_device_handle* devicehandle = NULL; + struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle; + + ASSERT(params != NULL); + + if (!handle) { + return NULL; + } + + /* Retrieve physical device info */ + list = capwap_list_create(); + result = nl80211_get_phydevice_list(globalhandle, list); + if (!result) { + item = list->first; + while (item) { + struct nl80211_phydevice_item* phyitem = (struct nl80211_phydevice_item*)item->item; + + if (!strcmp(phyitem->name, params->ifname)) { + /* Create device */ + devicehandle = (struct nl80211_device_handle*)capwap_alloc(sizeof(struct nl80211_device_handle)); + memset(devicehandle, 0, sizeof(struct nl80211_device_handle)); + + /* */ + strcpy(devicehandle->phyname, phyitem->name); + devicehandle->phyindex = phyitem->index; + + break; + } + + /* Next */ + item = item->next; + } + } else { + /* Error get physical devices */ + capwap_logging_error("Unable retrieve physical device info, error code: %d", result); + } + + /* */ + capwap_list_free(list); + if (!devicehandle) { + return NULL; + } + + /* */ + devicehandle->globalhandle = globalhandle; + + /* Save device handle into global handle */ + item = capwap_itemlist_create_with_item(devicehandle, sizeof(struct nl80211_device_handle)); + capwap_itemlist_insert_after(globalhandle->devicelist, NULL, item); + + return devicehandle; +} + +/* */ +static void nl80211_device_deinit(wifi_device_handle handle) { + struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle; + + if (devicehandle) { + struct capwap_list_item* search; + + /* Remove device handle from global handle*/ + search = devicehandle->globalhandle->devicelist->first; + while (search) { + /* Remove item from list without destroy */ + if ((struct nl80211_device_handle*)search->item == devicehandle) { + capwap_itemlist_remove(devicehandle->globalhandle->devicelist, search); + break; + } + + search = search->next; + } + + /* */ + capwap_free(devicehandle); + } } /* */ static wifi_global_handle nl80211_global_init(void) { - return NULL; + struct nl80211_global_handle* globalhandle; + + /* */ + globalhandle = (struct nl80211_global_handle*)capwap_alloc(sizeof(struct nl80211_global_handle)); + memset(globalhandle, 0, sizeof(struct nl80211_global_handle)); + + /* Configure global netlink callback */ + globalhandle->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!globalhandle->nl_cb) { + capwap_free(globalhandle); + return NULL; + } + + /* Create netlink socket */ + globalhandle->nl = nl_create_handle(globalhandle->nl_cb); + if (!globalhandle->nl) { + nl_cb_put(globalhandle->nl_cb); + capwap_free(globalhandle); + return NULL; + } + + /* Get nl80211 netlink family */ + globalhandle->nl80211_id = genl_ctrl_resolve(globalhandle->nl, "nl80211"); + if (globalhandle->nl80211_id < 0) { + capwap_logging_warning("Unable to found mac80211 kernel module"); + nl_socket_free(globalhandle->nl); + nl_cb_put(globalhandle->nl_cb); + capwap_free(globalhandle); + return NULL; + } + + /* Configure global callback function */ + nl_cb_set(globalhandle->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl80211_no_seq_check, NULL); + /* TODO */ + + /* Device list */ + globalhandle->devicelist = capwap_list_create(); + + return (wifi_global_handle)globalhandle; } /* */ -void nl80211_global_deinit(wifi_global_handle handle) { +static void nl80211_global_deinit(wifi_global_handle handle) { + struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle; + + if (globalhandle) { + ASSERT(globalhandle->devicelist->count == 0); + + if (globalhandle->nl) { + nl_socket_free(globalhandle->nl); + } + + if (globalhandle->nl_cb) { + nl_cb_put(globalhandle->nl_cb); + } + + capwap_list_free(globalhandle->devicelist); + capwap_free(globalhandle); + } } /* Driver function */ diff --git a/src/binding/wifi/drivers/wifi_nl80211.h b/src/binding/wifi/drivers/wifi_nl80211.h new file mode 100644 index 0000000..33a940d --- /dev/null +++ b/src/binding/wifi/drivers/wifi_nl80211.h @@ -0,0 +1,35 @@ +#ifndef __WIFI_NL80211_HEADER__ +#define __WIFI_NL80211_HEADER__ + +/* Compatibility functions */ +#if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30) +#define nl_sock nl_handle +#endif + +/* */ +typedef int (*nl_valid_cb)(struct nl_msg* msg, void* data); + +/* Global handle */ +struct nl80211_global_handle { + struct nl_sock* nl; + struct nl_cb* nl_cb; + int nl80211_id; + + struct capwap_list* devicelist; +}; + +/* Device handle */ +struct nl80211_device_handle { + struct nl80211_global_handle* globalhandle; + + uint32_t phyindex; + char phyname[IFNAMSIZ]; +}; + +/* Physical device info */ +struct nl80211_phydevice_item { + uint32_t index; + char name[IFNAMSIZ]; +}; + +#endif /* __WIFI_NL80211_HEADER__ */ diff --git a/src/common/capwap_array.c b/src/common/capwap_array.c index 96d4a33..aa29811 100644 --- a/src/common/capwap_array.c +++ b/src/common/capwap_array.c @@ -70,22 +70,28 @@ void capwap_array_resize(struct capwap_array* array, unsigned long count) { if (array->count == count) { return; } - + if (count > 0) { newbuffer = capwap_alloc(array->itemsize * count); if (!newbuffer) { capwap_outofmemory(); } } - + if (array->buffer) { if (newbuffer != NULL) { - memcpy(newbuffer, array->buffer, array->itemsize * min(array->count, count)); + int newcount = min(array->count, count); + memcpy(newbuffer, array->buffer, array->itemsize * newcount); + + /* Zeroed new items */ + if (array->zeroed && (count > newcount)) { + memset(newbuffer + array->itemsize * newcount, 0, array->itemsize * (count - newcount)); + } } - + capwap_free(array->buffer); } - + array->buffer = newbuffer; array->count = count; } diff --git a/src/common/capwap_array.h b/src/common/capwap_array.h index d6e2e5d..3e27b7d 100644 --- a/src/common/capwap_array.h +++ b/src/common/capwap_array.h @@ -5,6 +5,7 @@ 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); @@ -13,9 +14,4 @@ void capwap_array_free(struct capwap_array* array); void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos); void capwap_array_resize(struct capwap_array* array, unsigned long count); -/* Helper */ -#define capwap_array_getitem(x, y, z) *((z*)capwap_array_get_item_pointer((x), (y))) -#define capwap_array_setnewitem(x, y, z) *((z*)capwap_array_get_item_pointer((x), (x)->count)) = (y) - - #endif /* __CAPWAP_ARRAY_HEADER__ */ diff --git a/src/common/capwap_logging.h b/src/common/capwap_logging.h index 71a9a29..ddf402a 100644 --- a/src/common/capwap_logging.h +++ b/src/common/capwap_logging.h @@ -32,6 +32,11 @@ void capwap_logging_printf(int level, const char *format, ...); #define capwap_logging_error(f, args...) capwap_logging_printf(CAPWAP_LOGGING_ERROR, f, ##args) #define capwap_logging_warning(f, args...) capwap_logging_printf(CAPWAP_LOGGING_WARNING, f, ##args) #define capwap_logging_info(f, args...) capwap_logging_printf(CAPWAP_LOGGING_INFO, f, ##args) + +#ifdef DISABLE_LOGGING_DEBUG +#define capwap_logging_debug(f, args...) +#else #define capwap_logging_debug(f, args...) capwap_logging_printf(CAPWAP_LOGGING_DEBUG, f, ##args) +#endif #endif /* __CAPWAP_LOGGING_HEADER__ */ diff --git a/src/wtp/wtp.c b/src/wtp/wtp.c index 27a4803..2582109 100644 --- a/src/wtp/wtp.c +++ b/src/wtp/wtp.c @@ -158,6 +158,7 @@ static void wtp_print_usage(void) { /* Parsing configuration */ static int wtp_parsing_configuration_1_0(config_t* config) { int i; + int result; int configInt; int configIPv4; int configIPv6; @@ -246,6 +247,29 @@ static int wtp_parsing_configuration_1_0(config_t* config) { } } + /* Initialize binding */ + switch (g_wtp.binding) { + case CAPWAP_WIRELESS_BINDING_NONE: { + break; + } + + case CAPWAP_WIRELESS_BINDING_IEEE80211: { + /* Initialize wifi binding driver */ + capwap_logging_info("Initializing wifi binding engine"); + if (wifi_init_driver()) { + capwap_logging_fatal("Unable initialize wifi binding engine"); + return 0; + } + + break; + } + + default: { + capwap_logging_fatal("Unable initialize unknown binding engine: %hu", g_wtp.binding); + return 0; + } + } + /* Set tunnelmode of WTP */ if (config_lookup(config, "application.tunnelmode") != NULL) { g_wtp.mactunnel.mode = 0; @@ -364,6 +388,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) { for (i = 0; i < count; i++) { struct wtp_radio* radio; char radioname[IFNAMSIZ]; + char drivername[WIFI_DRIVER_NAME_SIZE]; unsigned char radiotype = 0; int radiostatus = WTP_RADIO_ENABLED; @@ -372,66 +397,89 @@ static int wtp_parsing_configuration_1_0(config_t* config) { if (config_setting_lookup_string(configElement, "device", &configString) == CONFIG_TRUE) { if (*configString && (strlen(configString) < IFNAMSIZ)) { strcpy(radioname, configString); - if (config_setting_lookup_string(configElement, "type", &configString) == CONFIG_TRUE) { - int length = strlen(configString); - - for (i = 0; i < length; i++) { - switch (configString[i]) { - case 'a': { - radiotype |= CAPWAP_RADIO_TYPE_80211A; - break; - } + if (config_setting_lookup_string(configElement, "driver", &configString) == CONFIG_TRUE) { + if (*configString && (strlen(configString) < WIFI_DRIVER_NAME_SIZE)) { + strcpy(drivername, configString); + if (config_setting_lookup_string(configElement, "type", &configString) == CONFIG_TRUE) { + int length = strlen(configString); - case 'b': { - radiotype |= CAPWAP_RADIO_TYPE_80211B; - break; - } - - case 'g': { - radiotype |= CAPWAP_RADIO_TYPE_80211G; - break; - } - - case 'n': { - radiotype |= CAPWAP_RADIO_TYPE_80211N; - break; + for (i = 0; i < length; i++) { + switch (configString[i]) { + case 'a': { + radiotype |= CAPWAP_RADIO_TYPE_80211A; + break; + } + + case 'b': { + radiotype |= CAPWAP_RADIO_TYPE_80211B; + break; + } + + case 'g': { + radiotype |= CAPWAP_RADIO_TYPE_80211G; + break; + } + + case 'n': { + radiotype |= CAPWAP_RADIO_TYPE_80211N; + break; + } + + default: { + capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value"); + return 0; + } + } } - - default: { - capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value"); - return 0; - } - } - } + + if (radiotype != 0) { + int radioid; - if (radiotype != 0) { - if (config_setting_lookup_string(configElement, "status", &configString) == CONFIG_TRUE) { - if (!strcmp(configString, "enabled")) { - radiostatus = WTP_RADIO_ENABLED; - } else if (!strcmp(configString, "disabled")) { - radiostatus = WTP_RADIO_DISABLED; - } else if (!strcmp(configString, "hwfailure")) { - radiostatus = WTP_RADIO_HWFAILURE; - } else if (!strcmp(configString, "swfailure")) { - radiostatus = WTP_RADIO_SWFAILURE; + if (config_setting_lookup_string(configElement, "status", &configString) == CONFIG_TRUE) { + if (!strcmp(configString, "enabled")) { + radiostatus = WTP_RADIO_ENABLED; + } else if (!strcmp(configString, "disabled")) { + radiostatus = WTP_RADIO_DISABLED; + } else if (!strcmp(configString, "hwfailure")) { + radiostatus = WTP_RADIO_HWFAILURE; + } else if (!strcmp(configString, "swfailure")) { + radiostatus = WTP_RADIO_SWFAILURE; + } else { + capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value"); + return 0; + } + } + + /* Initialize radio device */ + radioid = g_wtp.radios->count + 1; + if (radiostatus == WTP_RADIO_ENABLED) { + result = wifi_create_device(radioid, radioname, drivername); + if (result) { + radiostatus = WTP_RADIO_HWFAILURE; + capwap_logging_warning("Unable to register radio device: %s - %s", radioname, drivername); + } + } + + /* Create new radio device */ + radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count); + strcpy(radio->device, radioname); + radio->radioinformation.radioid = radioid; + radio->radioinformation.radiotype = radiotype; + radio->status = radiostatus; } else { capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value"); return 0; } + } else { + capwap_logging_error("Invalid configuration file, element application.descriptor.radio.type not found"); + return 0; } - - /* Create new radio device */ - radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count); - strcpy(radio->device, radioname); - radio->radioinformation.radioid = g_wtp.radios->count; - radio->radioinformation.radiotype = radiotype; - radio->status = radiostatus; } else { - capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value"); + capwap_logging_error("Invalid configuration file, application.descriptor.radio.driver string length exceeded"); return 0; } } else { - capwap_logging_error("Invalid configuration file, element application.descriptor.radio.type not found"); + capwap_logging_error("Invalid configuration file, element application.descriptor.radio.driver not found"); return 0; } } else { @@ -921,54 +969,33 @@ int main(int argc, char** argv) { result = WTP_ERROR_LOAD_CONFIGURATION; capwap_logging_fatal("Error to load configuration"); } else if (value > 0) { - /* Initialize binding */ - switch (g_wtp.binding) { - case CAPWAP_WIRELESS_BINDING_NONE: { - value = 0; - break; - } + capwap_logging_info("Startup WTP"); - case CAPWAP_WIRELESS_BINDING_IEEE80211: { - /* Initialize wifi binding driver */ - capwap_logging_info("Initializing wifi binding engine"); - value = wifi_init_driver(); - break; - } + /* Start WTP */ + wtp_dfa_change_state(CAPWAP_START_TO_IDLE_STATE); + + /* Complete configuration WTP */ + result = wtp_configure(); + if (result == CAPWAP_SUCCESSFUL) { + /* Init complete */ + wtp_dfa_change_state(CAPWAP_IDLE_STATE); + + /* Running WTP */ + result = wtp_dfa_execute(); + + /* Close socket */ + capwap_close_sockets(&g_wtp.net); } - /* */ - if (value) { - result = WTP_ERROR_INIT_BINDING; - capwap_logging_fatal("Unable initialize binding engine"); - } else { - capwap_logging_info("Startup WTP"); + capwap_logging_info("Terminate WTP"); - /* Start WTP */ - wtp_dfa_change_state(CAPWAP_START_TO_IDLE_STATE); - - /* Complete configuration WTP */ - result = wtp_configure(); - if (result == CAPWAP_SUCCESSFUL) { - /* Init complete */ - wtp_dfa_change_state(CAPWAP_IDLE_STATE); - - /* Running WTP */ - result = wtp_dfa_execute(); - - /* Close socket */ - capwap_close_sockets(&g_wtp.net); - } - - capwap_logging_info("Terminate WTP"); - - /* Free binding */ - switch (g_wtp.binding) { - case CAPWAP_WIRELESS_BINDING_IEEE80211: { - /* Free wifi binding driver */ - wifi_free_driver(); - capwap_logging_info("Free wifi binding engine"); - break; - } + /* Free binding */ + switch (g_wtp.binding) { + case CAPWAP_WIRELESS_BINDING_IEEE80211: { + /* Free wifi binding driver */ + wifi_free_driver(); + capwap_logging_info("Free wifi binding engine"); + break; } } }