multiple update
This commit is contained in:
parent
f2dda6e115
commit
9082a7855c
@ -31,7 +31,7 @@ application: {
|
|||||||
|
|
||||||
descriptor: {
|
descriptor: {
|
||||||
radio = (
|
radio = (
|
||||||
{ device = "wifi0"; type = "bg"; status = "enabled"; }
|
{ device = "phy0"; driver = "nl80211"; type = "bg"; status = "enabled"; }
|
||||||
);
|
);
|
||||||
|
|
||||||
encryption = [
|
encryption = [
|
||||||
|
@ -96,7 +96,7 @@ AC_ARG_WITH(
|
|||||||
# WTP drivers wifi binding
|
# WTP drivers wifi binding
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
[wifi-drivers-nl80211],
|
[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"]
|
[enable_wifi_drivers_nl80211="yes"]
|
||||||
)
|
)
|
||||||
@ -115,6 +115,7 @@ if test "${enable_debug}" = "yes"; then
|
|||||||
CFLAGS="${CFLAGS} -DDEBUG -Wall -Werror -g -O0"
|
CFLAGS="${CFLAGS} -DDEBUG -Wall -Werror -g -O0"
|
||||||
else
|
else
|
||||||
CFLAGS="${CFLAGS} -O2"
|
CFLAGS="${CFLAGS} -O2"
|
||||||
|
AC_DEFINE([DISABLE_LOGGING_DEBUG], [1], [Disable logging debug])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -231,7 +232,6 @@ PKG_CHECK_MODULES(
|
|||||||
)]
|
)]
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
test "$has_libnl_ver" -gt 1 &&
|
|
||||||
|
|
||||||
if test "${enable_wifi_drivers_nl80211}" = "yes"; then
|
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)])
|
AC_CHECK_HEADERS([netlink/genl/genl.h netlink/genl/family.h netlink/genl/ctrl.h], [], [AC_MSG_ERROR(You need the netlink header)])
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
#include "wifi_drivers.h"
|
#include "wifi_drivers.h"
|
||||||
|
#include "capwap_array.h"
|
||||||
/* */
|
|
||||||
struct wifi_driver_instance {
|
|
||||||
struct wifi_driver_ops* ops; /* Driver functions */
|
|
||||||
|
|
||||||
wifi_global_handle handle; /* Global instance handle */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Declare enable wifi driver */
|
/* Declare enable wifi driver */
|
||||||
#ifdef ENABLE_WIFI_DRIVERS_NL80211
|
#ifdef ENABLE_WIFI_DRIVERS_NL80211
|
||||||
@ -19,30 +13,93 @@ static struct wifi_driver_instance wifi_driver[] = {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Radio instance */
|
||||||
|
static struct capwap_array* wifi_device = NULL;
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int wifi_init_driver(void) {
|
int wifi_init_driver(void) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; wifi_driver[i].ops != NULL; i++) {
|
for (i = 0; wifi_driver[i].ops != NULL; i++) {
|
||||||
if (!wifi_driver[i].ops->global_init) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize driver */
|
/* Initialize driver */
|
||||||
|
ASSERT(wifi_driver[i].ops->global_init != NULL);
|
||||||
wifi_driver[i].handle = wifi_driver[i].ops->global_init();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
void wifi_free_driver(void) {
|
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++) {
|
for (i = 0; wifi_driver[i].ops != NULL; i++) {
|
||||||
/* Free driver */
|
|
||||||
if (wifi_driver[i].ops->global_deinit) {
|
if (wifi_driver[i].ops->global_deinit) {
|
||||||
wifi_driver[i].ops->global_deinit(wifi_driver[i].handle);
|
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;
|
||||||
|
}
|
||||||
|
@ -8,10 +8,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include "capwap_debug.h"
|
#include "capwap_debug.h"
|
||||||
#include "capwap_logging.h"
|
#include "capwap_logging.h"
|
||||||
|
|
||||||
|
/* */
|
||||||
|
#define WIFI_DRIVER_NAME_SIZE 16
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
typedef void* wifi_global_handle;
|
typedef void* wifi_global_handle;
|
||||||
typedef void* wifi_device_handle;
|
typedef void* wifi_device_handle;
|
||||||
@ -35,8 +39,23 @@ struct wifi_driver_ops {
|
|||||||
void (*device_deinit)(wifi_device_handle handle);
|
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 */
|
/* Initialize wifi driver engine */
|
||||||
int wifi_init_driver(void);
|
int wifi_init_driver(void);
|
||||||
void wifi_free_driver(void);
|
void wifi_free_driver(void);
|
||||||
|
|
||||||
|
/* */
|
||||||
|
int wifi_create_device(int radioid, char* ifname, char* driver);
|
||||||
|
|
||||||
#endif /* __WIFI_DRIVERS_HEADER__ */
|
#endif /* __WIFI_DRIVERS_HEADER__ */
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
#include "wifi_drivers.h"
|
#include "wifi_drivers.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <net/if.h>
|
||||||
#include <netlink/genl/genl.h>
|
#include <netlink/genl/genl.h>
|
||||||
#include <netlink/genl/family.h>
|
#include <netlink/genl/family.h>
|
||||||
#include <netlink/genl/ctrl.h>
|
#include <netlink/genl/ctrl.h>
|
||||||
#include <linux/nl80211.h>
|
#include <linux/nl80211.h>
|
||||||
|
|
||||||
|
#include "capwap_list.h"
|
||||||
|
#include "wifi_nl80211.h"
|
||||||
|
|
||||||
/* Compatibility functions */
|
/* Compatibility functions */
|
||||||
#if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30)
|
#if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30)
|
||||||
#define nl_sock nl_handle
|
|
||||||
static uint32_t port_bitmap[32] = { 0 };
|
static uint32_t port_bitmap[32] = { 0 };
|
||||||
|
|
||||||
static struct nl_sock* nl_socket_alloc_cb(void* cb) {
|
static struct nl_sock* nl_socket_alloc_cb(void* cb) {
|
||||||
@ -42,21 +45,275 @@ static void nl_socket_free(struct nl_sock* handle) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) {
|
static struct nl_sock* nl_create_handle(struct nl_cb* cb) {
|
||||||
return NULL;
|
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) {
|
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 */
|
/* Driver function */
|
||||||
|
35
src/binding/wifi/drivers/wifi_nl80211.h
Normal file
35
src/binding/wifi/drivers/wifi_nl80211.h
Normal file
@ -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__ */
|
@ -80,7 +80,13 @@ void capwap_array_resize(struct capwap_array* array, unsigned long count) {
|
|||||||
|
|
||||||
if (array->buffer) {
|
if (array->buffer) {
|
||||||
if (newbuffer != NULL) {
|
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);
|
capwap_free(array->buffer);
|
||||||
|
@ -5,6 +5,7 @@ struct capwap_array {
|
|||||||
void* buffer;
|
void* buffer;
|
||||||
unsigned short itemsize;
|
unsigned short itemsize;
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
|
int zeroed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount);
|
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_get_item_pointer(struct capwap_array* array, unsigned long pos);
|
||||||
void capwap_array_resize(struct capwap_array* array, unsigned long count);
|
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__ */
|
#endif /* __CAPWAP_ARRAY_HEADER__ */
|
||||||
|
@ -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_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_warning(f, args...) capwap_logging_printf(CAPWAP_LOGGING_WARNING, f, ##args)
|
||||||
#define capwap_logging_info(f, args...) capwap_logging_printf(CAPWAP_LOGGING_INFO, f, ##args)
|
#define capwap_logging_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)
|
#define capwap_logging_debug(f, args...) capwap_logging_printf(CAPWAP_LOGGING_DEBUG, f, ##args)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __CAPWAP_LOGGING_HEADER__ */
|
#endif /* __CAPWAP_LOGGING_HEADER__ */
|
||||||
|
205
src/wtp/wtp.c
205
src/wtp/wtp.c
@ -158,6 +158,7 @@ static void wtp_print_usage(void) {
|
|||||||
/* Parsing configuration */
|
/* Parsing configuration */
|
||||||
static int wtp_parsing_configuration_1_0(config_t* config) {
|
static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||||
int i;
|
int i;
|
||||||
|
int result;
|
||||||
int configInt;
|
int configInt;
|
||||||
int configIPv4;
|
int configIPv4;
|
||||||
int configIPv6;
|
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 */
|
/* Set tunnelmode of WTP */
|
||||||
if (config_lookup(config, "application.tunnelmode") != NULL) {
|
if (config_lookup(config, "application.tunnelmode") != NULL) {
|
||||||
g_wtp.mactunnel.mode = 0;
|
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++) {
|
for (i = 0; i < count; i++) {
|
||||||
struct wtp_radio* radio;
|
struct wtp_radio* radio;
|
||||||
char radioname[IFNAMSIZ];
|
char radioname[IFNAMSIZ];
|
||||||
|
char drivername[WIFI_DRIVER_NAME_SIZE];
|
||||||
unsigned char radiotype = 0;
|
unsigned char radiotype = 0;
|
||||||
int radiostatus = WTP_RADIO_ENABLED;
|
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 (config_setting_lookup_string(configElement, "device", &configString) == CONFIG_TRUE) {
|
||||||
if (*configString && (strlen(configString) < IFNAMSIZ)) {
|
if (*configString && (strlen(configString) < IFNAMSIZ)) {
|
||||||
strcpy(radioname, configString);
|
strcpy(radioname, configString);
|
||||||
if (config_setting_lookup_string(configElement, "type", &configString) == CONFIG_TRUE) {
|
if (config_setting_lookup_string(configElement, "driver", &configString) == CONFIG_TRUE) {
|
||||||
int length = strlen(configString);
|
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);
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
switch (configString[i]) {
|
switch (configString[i]) {
|
||||||
case 'a': {
|
case 'a': {
|
||||||
radiotype |= CAPWAP_RADIO_TYPE_80211A;
|
radiotype |= CAPWAP_RADIO_TYPE_80211A;
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'b': {
|
if (radiotype != 0) {
|
||||||
radiotype |= CAPWAP_RADIO_TYPE_80211B;
|
int radioid;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'g': {
|
if (config_setting_lookup_string(configElement, "status", &configString) == CONFIG_TRUE) {
|
||||||
radiotype |= CAPWAP_RADIO_TYPE_80211G;
|
if (!strcmp(configString, "enabled")) {
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 'n': {
|
/* Initialize radio device */
|
||||||
radiotype |= CAPWAP_RADIO_TYPE_80211N;
|
radioid = g_wtp.radios->count + 1;
|
||||||
break;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
/* Create new radio device */
|
||||||
capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value");
|
radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count);
|
||||||
return 0;
|
strcpy(radio->device, radioname);
|
||||||
}
|
radio->radioinformation.radioid = radioid;
|
||||||
}
|
radio->radioinformation.radiotype = radiotype;
|
||||||
}
|
radio->status = radiostatus;
|
||||||
|
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value");
|
capwap_logging_error("Invalid configuration file, unknown application.descriptor.radio.type value");
|
||||||
return 0;
|
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 {
|
} 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;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -921,54 +969,33 @@ int main(int argc, char** argv) {
|
|||||||
result = WTP_ERROR_LOAD_CONFIGURATION;
|
result = WTP_ERROR_LOAD_CONFIGURATION;
|
||||||
capwap_logging_fatal("Error to load configuration");
|
capwap_logging_fatal("Error to load configuration");
|
||||||
} else if (value > 0) {
|
} else if (value > 0) {
|
||||||
/* Initialize binding */
|
capwap_logging_info("Startup WTP");
|
||||||
switch (g_wtp.binding) {
|
|
||||||
case CAPWAP_WIRELESS_BINDING_NONE: {
|
|
||||||
value = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case CAPWAP_WIRELESS_BINDING_IEEE80211: {
|
/* Start WTP */
|
||||||
/* Initialize wifi binding driver */
|
wtp_dfa_change_state(CAPWAP_START_TO_IDLE_STATE);
|
||||||
capwap_logging_info("Initializing wifi binding engine");
|
|
||||||
value = wifi_init_driver();
|
/* Complete configuration WTP */
|
||||||
break;
|
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");
|
||||||
if (value) {
|
|
||||||
result = WTP_ERROR_INIT_BINDING;
|
|
||||||
capwap_logging_fatal("Unable initialize binding engine");
|
|
||||||
} else {
|
|
||||||
capwap_logging_info("Startup WTP");
|
|
||||||
|
|
||||||
/* Start WTP */
|
/* Free binding */
|
||||||
wtp_dfa_change_state(CAPWAP_START_TO_IDLE_STATE);
|
switch (g_wtp.binding) {
|
||||||
|
case CAPWAP_WIRELESS_BINDING_IEEE80211: {
|
||||||
/* Complete configuration WTP */
|
/* Free wifi binding driver */
|
||||||
result = wtp_configure();
|
wifi_free_driver();
|
||||||
if (result == CAPWAP_SUCCESSFUL) {
|
capwap_logging_info("Free wifi binding engine");
|
||||||
/* Init complete */
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user