switch timeout processing to libev

Rework the timeout and network code to use libev.
This commit is contained in:
Andreas Schultz 2016-03-30 10:39:04 +02:00
parent a4cb96da7c
commit 9572de350a
27 changed files with 654 additions and 816 deletions

View File

@ -6,6 +6,8 @@ This fork is currently focusing on the WTP side only.
## STATUS
NOTE: The WTP has been ported to libev, the AC has not been adjusted and is therefor broken for the moment.
### WTP tested and working features:
* 802.11b
@ -37,6 +39,7 @@ NOTE: To run WTP you must have a wireless card that has Linux driver based on th
* libconfig-dev
* libjson0-dev
* libnl-dev
* libev-dev
* libtool
* libxml2-dev
* wolfssl 3.8 or newer

View File

@ -23,6 +23,7 @@ bin_PROGRAMS = wtp
AM_CFLAGS = -D_REENTRANT \
-D_GNU_SOURCE \
-fno-strict-aliasing \
${LIBNL_CFLAGS}
if DTLS_ENABLED

View File

@ -174,6 +174,7 @@ AC_DEFINE_UNQUOTED([LIBCONFIG_LOOKUP_INT_ARG], [$LIBCONFIG_LOOKUP_INT_ARG], [con
# Check PTHREAD library
AC_CHECK_HEADER([pthread.h], [], [AC_MSG_ERROR(You need the pthread headers)])
AC_CHECK_LIB([pthread], [pthread_create], [PTHREAD_LIBS="-lpthread"], [AC_MSG_ERROR(You need the pthread library)])
AC_CHECK_LIB([ev], [ev_run],, [AC_MSG_ERROR(Required library ev missing)])
# Check SSL library
PKG_CHECK_MODULES([WOLFSSL], [wolfssl >= 3.8.0], [have_wolfssl_ssl="yes"], [have_wolfssl_ssl="no"])

View File

@ -235,83 +235,42 @@ int capwap_compare_ip(union sockaddr_capwap* addr1, union sockaddr_capwap* addr2
return -1;
}
/* Wait receive packet with timeout */
int capwap_wait_recvready(struct pollfd* fds, int fdscount, struct capwap_timeout* timeout) {
int i;
int readysocket;
int polltimeout = CAPWAP_TIMEOUT_INFINITE;
ASSERT(fds);
ASSERT(fdscount > 0);
/* Check timeout */
if (timeout) {
polltimeout = capwap_timeout_getcoming(timeout);
if (!polltimeout) {
capwap_timeout_hasexpired(timeout);
return CAPWAP_RECV_ERROR_TIMEOUT;
}
}
for (i = 0; i < fdscount; i++) {
fds[i].revents = 0;
}
/* Wait event */
readysocket = poll(fds, fdscount, polltimeout);
if (readysocket > 0) {
/* Get packet from only one socket */
for (i = 0; i < fdscount; i++) {
if (fds[i].revents & POLLIN) {
return i;
} else if ((fds[i].revents & (POLLHUP | POLLERR | POLLNVAL))) {
return CAPWAP_RECV_ERROR_SOCKET;
}
}
} else if (!readysocket && timeout) {
capwap_timeout_hasexpired(timeout);
return CAPWAP_RECV_ERROR_TIMEOUT;
} else if (errno == EINTR) {
return CAPWAP_RECV_ERROR_INTR;
}
return CAPWAP_RECV_ERROR_SOCKET;
}
/* Receive packet from fd */
int capwap_recvfrom(int sock, void* buffer, int* size, union sockaddr_capwap* fromaddr, union sockaddr_capwap* toaddr) {
int result = 0;
struct iovec iov;
struct msghdr msgh;
struct cmsghdr* cmsg;
ssize_t capwap_recvfrom(int sock, void* buffer, size_t len,
union sockaddr_capwap* fromaddr,
union sockaddr_capwap* toaddr)
{
ssize_t r = 0;
char cbuf[256];
struct iovec iov = {
.iov_base = buffer,
.iov_len = len
};
struct msghdr msgh = {
.msg_control = cbuf,
.msg_controllen = sizeof(cbuf),
.msg_name = &fromaddr->ss,
.msg_namelen = sizeof(struct sockaddr_storage),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_flags = 0
};
struct cmsghdr* cmsg;
ASSERT(sock >= 0);
ASSERT(buffer != NULL);
ASSERT(size != NULL);
ASSERT(*size > 0);
ASSERT(len > 0);
ASSERT(fromaddr != NULL);
/* */
iov.iov_base = buffer;
iov.iov_len = *size;
memset(&msgh, 0, sizeof(struct msghdr));
msgh.msg_control = cbuf;
msgh.msg_controllen = sizeof(cbuf);
msgh.msg_name = &fromaddr->ss;
msgh.msg_namelen = sizeof(struct sockaddr_storage);
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
msgh.msg_flags = 0;
/* Receive packet with recvmsg */
while (result <= 0) {
result = recvmsg(sock, &msgh, 0);
if ((result <= 0) && (errno != EAGAIN) && (errno != EINTR)) {
capwap_logging_warning("Unable to recv packet, recvmsg return %d with error %d", result, errno);
return -1;
}
do {
r = recvmsg(sock, &msgh, MSG_DONTWAIT);
} while (r < 0 && errno == EINTR);
if (r < 0) {
if (errno != EAGAIN)
capwap_logging_warning("Unable to recv packet, recvmsg return %d with error %d", r, errno);
return r;
}
/* Check if IPv4 is mapped into IPv6 */
@ -357,18 +316,18 @@ int capwap_recvfrom(int sock, void* buffer, int* size, union sockaddr_capwap* fr
}
}
/* Packet receive */
*size = result;
#ifdef DEBUG
{
char strfromaddr[INET6_ADDRSTRLEN];
char strtoaddr[INET6_ADDRSTRLEN];
capwap_logging_debug("Receive packet from %s:%d to %s with size %d", capwap_address_to_string(fromaddr, strfromaddr, INET6_ADDRSTRLEN), (int)CAPWAP_GET_NETWORK_PORT(fromaddr), capwap_address_to_string(toaddr, strtoaddr, INET6_ADDRSTRLEN), result);
capwap_logging_debug("Receive packet from %s:%d to %s with size %d",
capwap_address_to_string(fromaddr, strfromaddr, INET6_ADDRSTRLEN),
(int)CAPWAP_GET_NETWORK_PORT(fromaddr),
capwap_address_to_string(toaddr, strtoaddr, INET6_ADDRSTRLEN), r);
}
#endif
return 0;
return r;
}
/* */

View File

@ -74,8 +74,9 @@ int capwap_compare_ip(union sockaddr_capwap* addr1, union sockaddr_capwap* addr2
int capwap_sendto(int sock, void* buffer, int size, union sockaddr_capwap* toaddr);
int capwap_sendto_fragmentpacket(int sock, struct capwap_list* fragmentlist, union sockaddr_capwap* toaddr);
int capwap_wait_recvready(struct pollfd* fds, int fdscount, struct capwap_timeout* timeout);
int capwap_recvfrom(int sock, void* buffer, int* size, union sockaddr_capwap* fromaddr, union sockaddr_capwap* toaddr);
ssize_t capwap_recvfrom(int sock, void *buffer, size_t len,
union sockaddr_capwap* fromaddr,
union sockaddr_capwap* toaddr);
int capwap_address_from_string(const char* ip, union sockaddr_capwap* sockaddr);
const char* capwap_address_to_string(union sockaddr_capwap* sockaddr, char* ip, int len);

View File

@ -4,6 +4,8 @@
#include "wifi_drivers.h"
#include "netlink_link.h"
static void netlink_event_receive_cb(EV_P_ ev_io *w, int revents);
/* */
struct netlink_request {
struct nlmsghdr hdr;
@ -12,7 +14,8 @@ struct netlink_request {
};
/* */
struct netlink* netlink_init(void) {
struct netlink *netlink_init(wifi_global_handle handle)
{
int sock;
struct sockaddr_nl local;
struct netlink* netlinkhandle;
@ -34,43 +37,61 @@ struct netlink* netlink_init(void) {
/* Netlink reference */
netlinkhandle = (struct netlink*)capwap_alloc(sizeof(struct netlink));
netlinkhandle->handle = handle;
netlinkhandle->sock = sock;
netlinkhandle->nl_sequence = 1;
ev_io_init(&netlinkhandle->io_ev, netlink_event_receive_cb, sock, EV_READ);
ev_io_start(EV_DEFAULT_UC_ &netlinkhandle->io_ev);
return netlinkhandle;
}
/* */
void netlink_free(struct netlink* netlinkhandle) {
void netlink_free(struct netlink* netlinkhandle)
{
ASSERT(netlinkhandle != NULL);
ASSERT(netlinkhandle->sock >= 0);
if (ev_is_active(&netlinkhandle->io_ev))
ev_io_stop(EV_DEFAULT_UC_ &netlinkhandle->io_ev);
/* */
close(netlinkhandle->sock);
capwap_free(netlinkhandle);
}
static void invoke_event_fn(netlink_event_fn event_fn, struct netlink *netlinkhandle, struct nlmsghdr* message)
{
if (!event_fn)
return;
if (NLMSG_PAYLOAD(message, 0) < sizeof(struct ifinfomsg))
return;
event_fn(netlinkhandle->handle,
NLMSG_DATA(message),
(uint8_t*)(NLMSG_DATA(message) + NLMSG_ALIGN(sizeof(struct ifinfomsg))),
NLMSG_PAYLOAD(message, sizeof(struct ifinfomsg)));
}
/* */
void netlink_event_receive(int fd, void** params, int paramscount) {
static void netlink_event_receive_cb(EV_P_ ev_io *w, int revents)
{
struct netlink *netlinkhandle = (struct netlink *)
(((char *)w) - offsetof(struct netlink, io_ev));
int result;
struct netlink* netlinkhandle;
struct sockaddr_nl from;
socklen_t fromlen;
char buffer[8192];
struct nlmsghdr* message;
ASSERT(fd >= 0);
ASSERT(params != NULL);
ASSERT(paramscount == 2);
/* */
netlinkhandle = (struct netlink*)params[0];
/* Retrieve all netlink message */
for (;;) {
/* Get message */
fromlen = sizeof(struct sockaddr_nl);
result = recvfrom(netlinkhandle->sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&from, &fromlen);
result = recvfrom(w->fd, buffer, sizeof(buffer), MSG_DONTWAIT,
(struct sockaddr *)&from, &fromlen);
if (result <= 0) {
if (errno == EINTR) {
continue;
@ -84,21 +105,18 @@ void netlink_event_receive(int fd, void** params, int paramscount) {
message = (struct nlmsghdr*)buffer;
while (NLMSG_OK(message, result)) {
switch (message->nlmsg_type) {
case RTM_NEWLINK: {
if (netlinkhandle->newlink_event && NLMSG_PAYLOAD(message, 0) >= sizeof(struct ifinfomsg)) {
netlinkhandle->newlink_event((wifi_global_handle)params[1], NLMSG_DATA(message), (uint8_t*)(NLMSG_DATA(message) + NLMSG_ALIGN(sizeof(struct ifinfomsg))), NLMSG_PAYLOAD(message, sizeof(struct ifinfomsg)));
}
case RTM_NEWLINK:
invoke_event_fn(netlinkhandle->newlink_event,
netlinkhandle, message);
break;
break;
}
case RTM_DELLINK:
invoke_event_fn(netlinkhandle->dellink_event,
netlinkhandle, message);
break;
case RTM_DELLINK: {
if (netlinkhandle->dellink_event && NLMSG_PAYLOAD(message, 0) >= sizeof(struct ifinfomsg)) {
netlinkhandle->dellink_event((wifi_global_handle)params[1], NLMSG_DATA(message), (uint8_t*)(NLMSG_DATA(message) + NLMSG_ALIGN(sizeof(struct ifinfomsg))), NLMSG_PAYLOAD(message, sizeof(struct ifinfomsg)));
}
break;
}
default:
break;
}
/* */

View File

@ -4,6 +4,8 @@
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
#include <ev.h>
/* */
#ifndef IFLA_IFNAME
#define IFLA_IFNAME 3
@ -37,17 +39,23 @@
#define IFF_DORMANT 0x20000
#endif
typedef void (*netlink_event_fn)(wifi_global_handle handle, struct ifinfomsg* infomsg,
uint8_t* data, int length);
/* */
struct netlink {
wifi_global_handle handle;
int sock;
void (*newlink_event)(wifi_global_handle handle, struct ifinfomsg* infomsg, uint8_t* data, int length);
void (*dellink_event)(wifi_global_handle handle, struct ifinfomsg* infomsg, uint8_t* data, int length);
ev_io io_ev;
netlink_event_fn newlink_event;
netlink_event_fn dellink_event;
int nl_sequence;
};
/* */
struct netlink* netlink_init(void);
struct netlink* netlink_init(wifi_global_handle handle);
void netlink_free(struct netlink* netlinkhandle);
/* */

View File

@ -25,15 +25,22 @@ static struct wifi_global g_wifiglobal;
static uint8_t g_bufferIEEE80211[IEEE80211_MTU];
/* */
static void wifi_station_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
static void wifi_wlan_deauthentication_station(struct wifi_wlan* wlan, struct wifi_station* station, uint16_t reasoncode, int reusestation);
static void wifi_station_timeout_delete(EV_P_ ev_timer *w, int revents);
static void wifi_station_timeout_deauth(EV_P_ ev_timer *w, int revents);
static void wifi_wlan_deauthentication_station(struct wifi_wlan* wlan,
struct wifi_station* station,
uint16_t reasoncode,
int reusestation);
/* */
static void wifi_wlan_getrates(struct wifi_device* device, uint8_t* rates, int ratescount, struct device_setrates_params* device_params) {
static void wifi_wlan_getrates(struct wifi_device* device,
uint8_t* rates, int ratescount,
struct device_setrates_params* device_params)
{
int i, j, w;
int radiotype;
uint32_t mode = 0;
const struct wifi_capability* capability;
const struct wifi_capability* capability;
ASSERT(device != NULL);
ASSERT(rates != NULL);
@ -262,10 +269,7 @@ static void wifi_station_clean(struct wifi_station* station) {
}
/* Remove timers */
if (station->idtimeout != CAPWAP_TIMEOUT_INDEX_NO_SET) {
capwap_timeout_deletetimer(g_wifiglobal.timeout, station->idtimeout);
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
}
ev_timer_stop(EV_DEFAULT_UC_ &station->timeout);
/* */
station->flags = 0;
@ -273,7 +277,8 @@ static void wifi_station_clean(struct wifi_station* station) {
}
/* */
static void wifi_station_delete(struct wifi_station* station) {
static void wifi_station_delete(struct wifi_station* station)
{
ASSERT(station != NULL);
/* */
@ -283,8 +288,10 @@ static void wifi_station_delete(struct wifi_station* station) {
wifi_station_clean(station);
/* Delay delete station */
station->timeoutaction = WIFI_STATION_TIMEOUT_ACTION_DELETE;
station->idtimeout = capwap_timeout_set(g_wifiglobal.timeout, station->idtimeout, WIFI_STATION_TIMEOUT_AFTER_DEAUTHENTICATED, wifi_station_timeout, station, NULL);
ev_timer_stop(EV_DEFAULT_UC_ &station->timeout);
ev_timer_init(&station->timeout, wifi_station_timeout_delete,
WIFI_STATION_TIMEOUT_AFTER_DEAUTHENTICATED / 1000.0, 0.);
ev_timer_start(EV_DEFAULT_UC_ &station->timeout);
}
/* */
@ -327,7 +334,6 @@ static struct wifi_station* wifi_station_create(struct wifi_wlan* wlan, const ui
/* Initialize station */
memcpy(station->address, address, MACADDRESS_EUI48_LENGTH);
capwap_printf_macaddress(station->addrtext, address, MACADDRESS_EUI48_LENGTH);
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
/* Add to pool */
capwap_hash_add(g_wifiglobal.stations, station);
@ -371,7 +377,11 @@ static void wifi_wlan_send_mgmt_deauthentication(struct wifi_wlan* wlan, const u
}
/* */
static void wifi_wlan_deauthentication_station(struct wifi_wlan* wlan, struct wifi_station* station, uint16_t reasoncode, int reusestation) {
static void wifi_wlan_deauthentication_station(struct wifi_wlan* wlan,
struct wifi_station* station,
uint16_t reasoncode,
int reusestation)
{
ASSERT(wlan != NULL);
ASSERT(station != NULL);
@ -389,31 +399,33 @@ static void wifi_wlan_deauthentication_station(struct wifi_wlan* wlan, struct wi
}
/* */
static void wifi_station_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
struct wifi_station* station = (struct wifi_station*)context;
static void wifi_station_timeout_delete(EV_P_ ev_timer *w, int revents)
{
struct wifi_station *station = (struct wifi_station *)
(((char *)w) - offsetof(struct wifi_station, timeout));
ASSERT(station != NULL);
/* Free station into hash callback function */
wifi_station_clean(station);
capwap_hash_delete(g_wifiglobal.stations, station->address);
}
if (station->idtimeout == index) {
switch (station->timeoutaction) {
case WIFI_STATION_TIMEOUT_ACTION_DELETE: {
/* Free station into hash callback function */
wifi_station_clean(station);
capwap_hash_delete(g_wifiglobal.stations, station->address);
break;
}
static void wifi_station_timeout_deauth(EV_P_ ev_timer *w, int revents)
{
struct wifi_station *station = (struct wifi_station *)
(((char *)w) - offsetof(struct wifi_station, timeout));
struct wifi_wlan* wlan = (struct wifi_wlan *)w->data;
case WIFI_STATION_TIMEOUT_ACTION_DEAUTHENTICATE: {
capwap_logging_warning("The %s station has not completed the association in time", station->addrtext);
wifi_wlan_deauthentication_station((struct wifi_wlan*)param, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID, 0);
break;
}
}
}
capwap_logging_warning("The %s station has not completed the association in time",
station->addrtext);
wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID, 0);
}
/* */
static void wifi_wlan_receive_station_mgmt_probe_request(struct wifi_wlan* wlan, const struct ieee80211_header_mgmt* frame, int length, uint8_t rssi, uint8_t snr, uint16_t rate) {
static void wifi_wlan_receive_station_mgmt_probe_request(struct wifi_wlan* wlan,
const struct ieee80211_header_mgmt* frame,
int length, uint8_t rssi,
uint8_t snr, uint16_t rate)
{
int ielength;
int ssidcheck;
int nowaitack;
@ -590,8 +602,11 @@ static void wifi_wlan_receive_station_mgmt_authentication(struct wifi_wlan* wlan
station = wifi_station_create(wlan, frame->sa);
if (station) {
/* A station is removed if the association does not complete within a given period of time */
station->timeoutaction = WIFI_STATION_TIMEOUT_ACTION_DEAUTHENTICATE;
station->idtimeout = capwap_timeout_set(g_wifiglobal.timeout, station->idtimeout, WIFI_STATION_TIMEOUT_ASSOCIATION_COMPLETE, wifi_station_timeout, station, wlan);
ev_timer_stop(EV_DEFAULT_UC_ &station->timeout);
ev_timer_init(&station->timeout, wifi_station_timeout_deauth,
WIFI_STATION_TIMEOUT_ASSOCIATION_COMPLETE / 1000.0, 0.);
station->timeout.data = wlan;
ev_timer_start(EV_DEFAULT_UC_ &station->timeout);
responsestatuscode = IEEE80211_STATUS_SUCCESS;
} else {
responsestatuscode = IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
@ -1134,11 +1149,10 @@ static int wifi_wlan_receive_ac_mgmt_frame(struct wifi_wlan* wlan, struct ieee80
}
/* */
int wifi_driver_init(struct capwap_timeout* timeout) {
int wifi_driver_init()
{
int i;
ASSERT(timeout != NULL);
/* Socket utils */
memset(&g_wifiglobal, 0, sizeof(struct wifi_global));
g_wifiglobal.sock_util = socket(AF_PACKET, SOCK_RAW, 0);
@ -1156,7 +1170,6 @@ int wifi_driver_init(struct capwap_timeout* timeout) {
}
/* */
g_wifiglobal.timeout = timeout;
g_wifiglobal.devices = capwap_list_create();
g_wifiglobal.stations = capwap_hash_create(WIFI_STATIONS_HASH_SIZE);
g_wifiglobal.stations->item_gethash = wifi_hash_station_gethash;
@ -1234,44 +1247,6 @@ void wifi_driver_free(void) {
close(g_wifiglobal.sock_util);
}
/* */
int wifi_event_getfd(struct pollfd* fds, struct wifi_event* events, int count) {
int i;
int result = 0;
struct capwap_list_item* itemdevice;
struct capwap_list_item* itemwlan;
if ((count > 0) && (!fds || !events)) {
return -1;
}
/* Get from driver */
for (i = 0; wifi_driver[i].ops != NULL; i++) {
result += wifi_driver[i].ops->global_getfdevent(wifi_driver[i].handle, (count ? &fds[result] : NULL), (count ? &events[result] : NULL));
}
/* Get from device */
for (itemdevice = g_wifiglobal.devices->first; itemdevice != NULL; itemdevice = itemdevice->next) {
struct wifi_device* device = (struct wifi_device*)itemdevice->item;
if (device->handle) {
result += device->instance->ops->device_getfdevent(device, (count ? &fds[result] : NULL), (count ? &events[result] : NULL));
/* Get from wlan */
if (device->wlans) {
for (itemwlan = device->wlans->first; itemwlan != NULL; itemwlan = itemwlan->next) {
struct wifi_wlan* wlan = (struct wifi_wlan*)itemwlan->item;
if (wlan->handle) {
result += device->instance->ops->wlan_getfdevent(wlan, (count ? &fds[result] : NULL), (count ? &events[result] : NULL));
}
}
}
}
}
return result;
}
/* */
struct wifi_wlan* wifi_get_wlan(uint32_t ifindex) {
struct capwap_list_item* itemdevice;
@ -1318,39 +1293,40 @@ struct wifi_device* wifi_device_connect(const char* ifname, const char* driver)
/* Search driver */
for (i = 0; wifi_driver[i].ops != NULL; i++) {
if (!strcmp(driver, wifi_driver[i].ops->name)) {
itemdevice = capwap_itemlist_create(sizeof(struct wifi_device));
device = (struct wifi_device*)itemdevice->item;
memset(device, 0, sizeof(struct wifi_device));
if (strcmp(driver, wifi_driver[i].ops->name) != 0)
continue;
/* */
device->global = &g_wifiglobal;
device->instance = &wifi_driver[i];
strcpy(device->phyname, ifname);
itemdevice = capwap_itemlist_create(sizeof(struct wifi_device));
device = (struct wifi_device*)itemdevice->item;
memset(device, 0, sizeof(struct wifi_device));
/* Device init */
if (!wifi_driver[i].ops->device_init(wifi_driver[i].handle, device)) {
/* Registered new device */
device->wlans = capwap_list_create();
/* */
device->global = &g_wifiglobal;
device->instance = &wifi_driver[i];
strcpy(device->phyname, ifname);
/* Device capability */
device->capability = (struct wifi_capability*)capwap_alloc(sizeof(struct wifi_capability));
memset(device->capability, 0, sizeof(struct wifi_capability));
device->capability->bands = capwap_array_create(sizeof(struct wifi_band_capability), 0, 1);
device->capability->ciphers = capwap_array_create(sizeof(struct wifi_cipher_capability), 0, 1);
/* Retrieve device capability */
device->instance->ops->device_getcapability(device, device->capability);
/* Appent to device list */
capwap_itemlist_insert_after(g_wifiglobal.devices, NULL, itemdevice);
} else {
capwap_itemlist_free(itemdevice);
device = NULL;
}
break;
/* Device init */
if (wifi_driver[i].ops->device_init(wifi_driver[i].handle, device)) {
capwap_itemlist_free(itemdevice);
return NULL;
}
/* Registered new device */
device->wlans = capwap_list_create();
/* Device capability */
device->capability = (struct wifi_capability*)capwap_alloc(sizeof(struct wifi_capability));
memset(device->capability, 0, sizeof(struct wifi_capability));
device->capability->bands = capwap_array_create(sizeof(struct wifi_band_capability), 0, 1);
device->capability->ciphers = capwap_array_create(sizeof(struct wifi_cipher_capability), 0, 1);
/* Retrieve device capability */
device->instance->ops->device_getcapability(device, device->capability);
/* Appent to device list */
capwap_itemlist_insert_after(g_wifiglobal.devices, NULL, itemdevice);
break;
}
return device;
@ -1886,10 +1862,6 @@ int wifi_station_authorize(struct wifi_wlan* wlan, struct station_add_params* pa
return 0;
}
/* */
capwap_timeout_deletetimer(g_wifiglobal.timeout, station->idtimeout);
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
/* Station is authorized only after Authentication and Association */
station->flags |= WIFI_STATION_FLAGS_AUTHORIZED;
if (!(station->flags & WIFI_STATION_FLAGS_AUTHENTICATED) ||

View File

@ -5,6 +5,8 @@
#include <linux/if_ether.h>
#include "ieee80211.h"
#include <ev.h>
/* */
#define WIFI_DRIVER_NAME_SIZE 16
@ -227,9 +229,6 @@ struct wifi_global {
int sock_util;
struct capwap_list* devices;
/* Timeout */
struct capwap_timeout* timeout;
/* Stations */
struct capwap_hash* stations;
};
@ -353,8 +352,7 @@ struct wifi_station {
unsigned long flags;
/* Timers */
int timeoutaction;
unsigned long idtimeout;
struct ev_timer timeout;
/* */
uint16_t capability;
@ -380,12 +378,10 @@ struct wifi_driver_ops {
/* Global initialize driver */
wifi_global_handle (*global_init)(void);
int (*global_getfdevent)(wifi_global_handle handle, struct pollfd* fds, struct wifi_event* events);
void (*global_deinit)(wifi_global_handle handle);
/* Device functions */
int (*device_init)(wifi_global_handle handle, struct wifi_device* device);
int (*device_getfdevent)(struct wifi_device* device, struct pollfd* fds, struct wifi_event* events);
int (*device_getcapability)(struct wifi_device* device, struct wifi_capability* capability);
void (*device_updatebeacons)(struct wifi_device* device);
int (*device_setfrequency)(struct wifi_device* device);
@ -395,7 +391,6 @@ struct wifi_driver_ops {
/* WLAN functions */
wifi_wlan_handle (*wlan_create)(struct wifi_device* device, struct wifi_wlan* wlan);
int (*wlan_getfdevent)(struct wifi_wlan* wlan, struct pollfd* fds, struct wifi_event* events);
int (*wlan_startap)(struct wifi_wlan* wlan);
void (*wlan_stopap)(struct wifi_wlan* wlan);
int (*wlan_sendframe)(struct wifi_wlan* wlan, uint8_t* frame, int length, uint32_t frequency, uint32_t duration, int offchannel_tx_ok, int no_cck_rate, int no_wait_ack);
@ -407,12 +402,9 @@ struct wifi_driver_ops {
};
/* Initialize wifi driver engine */
int wifi_driver_init(struct capwap_timeout* timeout);
int wifi_driver_init(void);
void wifi_driver_free(void);
/* Get File Descriptor Event */
int wifi_event_getfd(struct pollfd* fds, struct wifi_event* events, int count);
/* */
struct wifi_wlan* wifi_get_wlan(uint32_t ifindex);

View File

@ -120,7 +120,12 @@ static int nl80211_ack_handler(struct nl_msg* msg, void* arg) {
}
/* */
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) {
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;
@ -156,12 +161,17 @@ static int nl80211_send_and_recv(struct nl_sock* nl, struct nl_cb* nl_cb, struct
}
/* */
static int nl80211_send_and_recv_msg(struct nl80211_global_handle* globalhandle, struct nl_msg* msg, nl_valid_cb valid_cb, void* data) {
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_family_handler(struct nl_msg* msg, void* data) {
static int cb_family_handler(struct nl_msg* msg, void* data)
{
int i;
struct nlattr* mcast_group;
struct nlattr* tb_msg[CTRL_ATTR_MAX + 1];
@ -591,52 +601,37 @@ static wifi_wlan_handle nl80211_wlan_create(struct wifi_device* device, struct w
memset(wlanhandle, 0, sizeof(struct nl80211_wlan_handle));
wlanhandle->devicehandle = devicehandle;
wlanhandle->nl_fd = -1;
return (wifi_wlan_handle)wlanhandle;
}
/* */
static void nl80211_event_receive(int fd, void** params, int paramscount) {
static void nl80211_global_event_receive_cb(EV_P_ ev_io *w, int revents)
{
struct nl80211_global_handle *globalhandle = (struct nl80211_global_handle *)
(((char *)w) - offsetof(struct nl80211_global_handle, nl_event_ev));
int res;
ASSERT(fd >= 0);
ASSERT(params != NULL);
ASSERT(paramscount == 2);
capwap_logging_warning("nl80211_global_event_receive_cb on fd %d", w->fd);
/* */
res = nl_recvmsgs((struct nl_sock*)params[0], (struct nl_cb*)params[1]);
res = nl_recvmsgs(globalhandle->nl_event, globalhandle->nl_cb);
if (res) {
capwap_logging_warning("Receive nl80211 message failed: %d", res);
}
}
/* */
static int nl80211_wlan_getfdevent(struct wifi_wlan* wlan, struct pollfd* fds, struct wifi_event* events) {
struct nl80211_wlan_handle* wlanhandle;
ASSERT(wlan != NULL);
ASSERT(wlan->handle != NULL);
static void nl80211_wlan_event_receive_cb(EV_P_ ev_io *w, int revents)
{
struct nl80211_wlan_handle *wlanhandle = (struct nl80211_wlan_handle *)
(((char *)w) - offsetof(struct nl80211_wlan_handle, nl_ev));
int res;
capwap_logging_warning("nl80211_wlan_event_receive_cb on fd %d", w->fd);
/* */
wlanhandle = (struct nl80211_wlan_handle*)wlan->handle;
if (!(wlan->flags & WIFI_WLAN_RUNNING) || (wlanhandle->nl_fd < 0)) {
return 0;
res = nl_recvmsgs(wlanhandle->nl, wlanhandle->nl_cb);
if (res) {
capwap_logging_warning("Receive nl80211 message failed: %d", res);
}
if (fds) {
fds[0].fd = wlanhandle->nl_fd;
fds[0].events = POLLIN | POLLERR | POLLHUP;
}
if (events) {
events[0].event_handler = nl80211_event_receive;
events[0].params[0] = (void*)wlanhandle->nl;
events[0].params[1] = (void*)wlanhandle->nl_cb;
events[0].paramscount = 2;
}
return 1;
}
/* */
@ -807,11 +802,8 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
nl_cb_set(wlanhandle->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_wlan_valid_handler, (void*)wlan);
wlanhandle->nl = nl_create_handle(wlanhandle->nl_cb);
if (wlanhandle->nl) {
wlanhandle->nl_fd = nl_socket_get_fd(wlanhandle->nl);
} else {
if (!wlanhandle->nl)
return -1;
}
/* Register frames */
for (i = 0; i < sizeof(g_stypes) / sizeof(g_stypes[0]); i++) {
@ -837,6 +829,12 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
/* Enable interface */
wlan->flags |= WIFI_WLAN_RUNNING;
/* hook into I/O loop */
ev_io_init(&wlanhandle->nl_ev, nl80211_wlan_event_receive_cb,
nl_socket_get_fd(wlanhandle->nl), EV_READ);
ev_io_start(EV_DEFAULT_UC_ &wlanhandle->nl_ev);
if (wifi_iface_up(wlanhandle->devicehandle->globalhandle->sock_util, wlan->virtname)) {
return -1;
}
@ -897,10 +895,12 @@ static void nl80211_wlan_stopap(struct wifi_wlan* wlan) {
nl80211_wlan_set_profile(wlan, NL80211_IFTYPE_STATION);
/* */
if (ev_is_active(&wlanhandle->nl_ev))
ev_io_stop(EV_DEFAULT_UC_ &wlanhandle->nl_ev);
if (wlanhandle->nl) {
nl_socket_free(wlanhandle->nl);
wlanhandle->nl = NULL;
wlanhandle->nl_fd = -1;
}
if (wlanhandle->nl_cb) {
@ -1229,14 +1229,6 @@ int nl80211_device_init(wifi_global_handle handle, struct wifi_device* device) {
return 0;
}
/* */
static int nl80211_device_getfdevent(struct wifi_device* device, struct pollfd* fds, struct wifi_event* events) {
ASSERT(device != NULL);
ASSERT(device->handle != NULL);
return 0;
}
/* */
static unsigned long nl80211_get_cipher(uint32_t chiper) {
switch (chiper) {
@ -1676,7 +1668,8 @@ static int nl80211_device_setfrequency(struct wifi_device* device) {
}
/* */
static void nl80211_device_deinit(struct wifi_device* device) {
static void nl80211_device_deinit(struct wifi_device* device)
{
struct nl80211_device_handle* devicehandle;
ASSERT(device != NULL);
@ -1689,36 +1682,38 @@ static void nl80211_device_deinit(struct wifi_device* device) {
}
/* */
static 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) {
if (globalhandle->netlinkhandle) {
netlink_free(globalhandle->netlinkhandle);
}
if (!globalhandle)
return;
if (globalhandle->nl) {
nl_socket_free(globalhandle->nl);
}
if (globalhandle->netlinkhandle)
netlink_free(globalhandle->netlinkhandle);
if (globalhandle->nl_event) {
nl_socket_free(globalhandle->nl_event);
}
if (globalhandle->nl)
nl_socket_free(globalhandle->nl);
if (globalhandle->nl_cb) {
nl_cb_put(globalhandle->nl_cb);
}
if (globalhandle->nl_event)
nl_socket_free(globalhandle->nl_event);
if (globalhandle->sock_util >= 0) {
close(globalhandle->sock_util);
}
if (ev_is_active(&globalhandle->nl_event_ev))
ev_io_stop(EV_DEFAULT_UC_ &globalhandle->nl_event_ev);
capwap_free(globalhandle);
}
if (globalhandle->nl_cb)
nl_cb_put(globalhandle->nl_cb);
if (globalhandle->sock_util >= 0)
close(globalhandle->sock_util);
capwap_free(globalhandle);
}
/* */
static void nl80211_global_newlink_event(wifi_global_handle handle, struct ifinfomsg* infomsg, uint8_t* data, int length) {
static void nl80211_global_newlink_event(wifi_global_handle handle, struct ifinfomsg* infomsg,
uint8_t* data, int length)
{
struct wifi_wlan* wlan;
struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle;
@ -1727,22 +1722,29 @@ static void nl80211_global_newlink_event(wifi_global_handle handle, struct ifinf
/* Search device */
wlan = wifi_get_wlan(infomsg->ifi_index);
if (wlan) {
if (!(wlan->flags & WIFI_WLAN_RUNNING)) {
if ((infomsg->ifi_flags & IFF_UP) && (wifi_iface_getstatus(globalhandle->sock_util, wlan->virtname) > 0)) {
wifi_iface_down(globalhandle->sock_util, wlan->virtname);
}
} else if (wlan->flags & WIFI_WLAN_SET_BEACON) {
if ((wlan->flags & WIFI_WLAN_OPERSTATE_RUNNING) && (infomsg->ifi_flags & IFF_LOWER_UP) && !(infomsg->ifi_flags & (IFF_RUNNING | IFF_DORMANT))) {
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)wlan->handle;
netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle, wlan->virtindex, -1, IF_OPER_UP);
}
if (!wlan)
return;
if (!(wlan->flags & WIFI_WLAN_RUNNING)) {
if ((infomsg->ifi_flags & IFF_UP) &&
(wifi_iface_getstatus(globalhandle->sock_util, wlan->virtname) > 0)) {
wifi_iface_down(globalhandle->sock_util, wlan->virtname);
}
} else if (wlan->flags & WIFI_WLAN_SET_BEACON) {
if ((wlan->flags & WIFI_WLAN_OPERSTATE_RUNNING) &&
(infomsg->ifi_flags & IFF_LOWER_UP) &&
!(infomsg->ifi_flags & (IFF_RUNNING | IFF_DORMANT))) {
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)wlan->handle;
netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle,
wlan->virtindex, -1, IF_OPER_UP);
}
}
}
/* */
static void nl80211_global_dellink_event(wifi_global_handle handle, struct ifinfomsg* infomsg, uint8_t* data, int length) {
static void nl80211_global_dellink_event(wifi_global_handle handle, struct ifinfomsg* infomsg,
uint8_t* data, int length)
{
}
/* */
@ -1768,7 +1770,8 @@ static int nl80211_global_valid_handler(struct nl_msg* msg, void* data) {
}
/* */
static wifi_global_handle nl80211_global_init(void) {
static wifi_global_handle nl80211_global_init()
{
int result;
struct nl80211_global_handle* globalhandle;
@ -1793,19 +1796,22 @@ static wifi_global_handle nl80211_global_init(void) {
/* Create netlink socket for event */
globalhandle->nl_event = nl_create_handle(globalhandle->nl_cb);
if (globalhandle->nl_event) {
globalhandle->nl_event_fd = nl_socket_get_fd(globalhandle->nl_event);
} else {
if (!globalhandle->nl_event) {
nl80211_global_deinit((wifi_global_handle)globalhandle);
return NULL;
}
/* hook into I/O loop */
ev_io_init(&globalhandle->nl_event_ev, nl80211_global_event_receive_cb,
nl_socket_get_fd(globalhandle->nl_event), EV_READ);
ev_io_start(EV_DEFAULT_UC_ &globalhandle->nl_event_ev);
/* Add membership scan events */
result = nl80211_get_multicast_id(globalhandle, "nl80211", "scan");
if (result >= 0) {
result = nl_socket_add_membership(globalhandle->nl_event, result);
}
if (result < 0) {
nl80211_global_deinit((wifi_global_handle)globalhandle);
return NULL;
@ -1841,7 +1847,7 @@ static wifi_global_handle nl80211_global_init(void) {
nl_cb_set(globalhandle->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_global_valid_handler, NULL);
/* Netlink lisk status */
globalhandle->netlinkhandle = netlink_init();
globalhandle->netlinkhandle = netlink_init((wifi_global_handle)globalhandle);
if (!globalhandle->netlinkhandle) {
nl80211_global_deinit((wifi_global_handle)globalhandle);
return NULL;
@ -1860,46 +1866,14 @@ static wifi_global_handle nl80211_global_init(void) {
return (wifi_global_handle)globalhandle;
}
/* */
static int nl80211_global_getfdevent(wifi_global_handle handle, struct pollfd* fds, struct wifi_event* events) {
struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle;
ASSERT(handle != NULL);
ASSERT(globalhandle->nl_event_fd >= 0);
ASSERT(globalhandle->netlinkhandle != NULL);
ASSERT(globalhandle->netlinkhandle->sock >= 0);
if (fds) {
fds[0].fd = globalhandle->nl_event_fd;
fds[0].events = POLLIN | POLLERR | POLLHUP;
fds[1].fd = globalhandle->netlinkhandle->sock;
fds[1].events = POLLIN | POLLERR | POLLHUP;
}
if (events) {
events[0].event_handler = nl80211_event_receive;
events[0].params[0] = (void*)globalhandle->nl_event;
events[0].params[1] = (void*)globalhandle->nl_cb;
events[0].paramscount = 2;
events[1].event_handler = netlink_event_receive;
events[1].params[0] = (void*)globalhandle->netlinkhandle;
events[1].params[1] = (void*)globalhandle;
events[1].paramscount = 2;
}
return 2;
}
/* Driver function */
const struct wifi_driver_ops wifi_driver_nl80211_ops = {
.name = "nl80211",
.description = "Linux nl80211/cfg80211",
.global_init = nl80211_global_init,
.global_getfdevent = nl80211_global_getfdevent,
.global_deinit = nl80211_global_deinit,
.device_init = nl80211_device_init,
.device_getfdevent = nl80211_device_getfdevent,
.device_getcapability = nl80211_device_getcapability,
.device_updatebeacons = nl80211_device_updatebeacons,
.device_settxqueue = nl80211_device_settxqueue,
@ -1907,7 +1881,6 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = {
.device_deinit = nl80211_device_deinit,
.wlan_create = nl80211_wlan_create,
.wlan_getfdevent = nl80211_wlan_getfdevent,
.wlan_startap = nl80211_wlan_startap,
.wlan_stopap = nl80211_wlan_stopap,
.wlan_sendframe = nl80211_wlan_sendframe,

View File

@ -1,6 +1,8 @@
#ifndef __WIFI_NL80211_HEADER__
#define __WIFI_NL80211_HEADER__
#include <ev.h>
#include "capwap_hash.h"
#include "netlink_link.h"
@ -18,12 +20,13 @@ 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 nl_sock* nl_event;
int nl_event_fd;
struct nl_sock* nl;
struct nl_cb* nl_cb;
struct nl_sock *nl_event;
ev_io nl_event_ev;
struct netlink* netlinkhandle;
@ -39,9 +42,9 @@ struct nl80211_device_handle {
struct nl80211_wlan_handle {
struct nl80211_device_handle* devicehandle;
struct nl_sock* nl;
int nl_fd;
struct nl_cb* nl_cb;
struct nl_sock *nl;
ev_io nl_ev;
struct nl_cb *nl_cb;
uint64_t last_cookie;
};

View File

@ -10,6 +10,7 @@
#include "wtp_radio.h"
#include <arpa/inet.h>
#include <ev.h>
#include <libconfig.h>
struct wtp_t g_wtp;
@ -22,7 +23,8 @@ struct wtp_t g_wtp;
static char g_configurationfile[260] = WTP_STANDARD_CONFIGURATION_FILE;
/* Alloc WTP */
static int wtp_init(void) {
static int wtp_init(void)
{
/* Init WTP with default value */
memset(&g_wtp, 0, sizeof(struct wtp_t));
@ -39,13 +41,6 @@ static int wtp_init(void) {
g_wtp.discoveryinterval = WTP_DISCOVERY_INTERVAL;
g_wtp.echointerval = WTP_ECHO_INTERVAL;
/* */
g_wtp.timeout = capwap_timeout_init();
g_wtp.idtimercontrol = capwap_timeout_createtimer(g_wtp.timeout);
g_wtp.idtimerecho = capwap_timeout_createtimer(g_wtp.timeout);
g_wtp.idtimerkeepalive = capwap_timeout_createtimer(g_wtp.timeout);
g_wtp.idtimerkeepalivedead = capwap_timeout_createtimer(g_wtp.timeout);
/* Socket */
capwap_network_init(&g_wtp.net);
@ -127,7 +122,6 @@ static void wtp_destroy(void) {
wtp_free_discovery_response_array();
capwap_array_free(g_wtp.acdiscoveryresponse);
capwap_timeout_free(g_wtp.timeout);
/* Free local message elements */
capwap_free(g_wtp.name.name);
@ -914,7 +908,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
case CAPWAP_WIRELESS_BINDING_IEEE80211: {
/* Initialize wifi binding driver */
capwap_logging_info("Initializing wifi binding engine");
if (wifi_driver_init(g_wtp.timeout)) {
if (wifi_driver_init()) {
capwap_logging_fatal("Unable initialize wifi binding engine");
return 0;
}
@ -1346,40 +1340,26 @@ static int wtp_configure(void) {
capwap_logging_fatal("Cannot bind control address");
return WTP_ERROR_NETWORK;
}
wtp_socket_io_start();
return CAPWAP_SUCCESSFUL;
}
static void wtp_wait_radio_ready_timeout_cb(EV_P_ ev_timer *w, int revents)
{
ev_break (EV_A_ EVBREAK_ONE);
}
/* */
static void wtp_wait_radio_ready(void) {
int index;
struct wtp_fds fds;
static void wtp_wait_radio_ready(void)
{
ev_timer timeout;
/* Get only radio file descriptor */
memset(&fds, 0, sizeof(struct wtp_fds));
wtp_dfa_update_fdspool(&fds);
if (fds.wifieventscount > 0) {
ASSERT(fds.fdsnetworkcount == 0);
ASSERT(fds.kmodeventscount == 0);
ev_timer_init(&timeout, wtp_wait_radio_ready_timeout_cb,
WTP_RADIO_INITIALIZATION_INTERVAL / 1000, 0.);
ev_timer_start(EV_DEFAULT_UC_ &timeout);
for (;;) {
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_RADIO_INITIALIZATION_INTERVAL, NULL, NULL, NULL);
/* Wait packet */
index = capwap_wait_recvready(fds.fdspoll, fds.fdstotalcount, g_wtp.timeout);
if (index < 0) {
break;
} else if (!fds.wifievents[index].event_handler) {
break;
}
fds.wifievents[index].event_handler(fds.fdspoll[index].fd, fds.wifievents[index].params, fds.wifievents[index].paramscount);
}
}
/* */
wtp_dfa_free_fdspool(&fds);
capwap_timeout_unset(g_wtp.timeout, g_wtp.idtimercontrol);
ev_run(EV_DEFAULT_UC_ 0);
}
/* */
@ -1393,6 +1373,8 @@ int main(int argc, char** argv) {
int value;
int result = CAPWAP_SUCCESSFUL;
ev_default_loop(0);
/* Init logging */
capwap_logging_init();
capwap_logging_verboselevel(CAPWAP_LOGGING_ERROR);
@ -1445,7 +1427,7 @@ int main(int argc, char** argv) {
}
/* Wait the initialization of radio interfaces */
capwap_logging_info("Wait the initialization of radio interfaces");
capwap_logging_info("Wait for the initialization of radio interfaces");
wtp_wait_radio_ready();
/* Connect WTP with kernel module */
@ -1463,9 +1445,11 @@ int main(int argc, char** argv) {
result = wtp_configure();
if (result == CAPWAP_SUCCESSFUL) {
/* Running WTP */
result = wtp_dfa_running();
/* Close sockets */
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
}

View File

@ -2,6 +2,8 @@
#define __CAPWAP_WTP_HEADER__
/* standard include */
#include <ev.h>
#include "capwap.h"
#include "capwap_dtls.h"
#include "capwap_network.h"
@ -76,7 +78,11 @@ struct wtp_t {
/* */
unsigned short mtu;
struct capwap_network net;
struct wtp_fds fds;
/* libev watchers */
ev_io socket_ev;
ev_signal sigint_ev;
ev_signal sigterm_ev;
/* */
unsigned long state;
@ -88,11 +94,10 @@ struct wtp_t {
int echointerval;
/* Timer */
struct capwap_timeout* timeout;
unsigned long idtimercontrol;
unsigned long idtimerecho;
unsigned long idtimerkeepalive;
unsigned long idtimerkeepalivedead;
struct ev_timer timercontrol;
struct ev_timer timerecho;
struct ev_timer timerkeepalive;
struct ev_timer timerkeepalivedead;
struct capwap_wtpname_element name;
struct capwap_acname_element acname;

View File

@ -6,14 +6,74 @@
#include "wtp_radio.h"
#include <signal.h>
#include <ev.h>
#define WTP_RECV_NOERROR_RADIO -1001
/* Handler signal */
static void wtp_signal_handler(int signum) {
if ((signum == SIGINT) || (signum == SIGTERM)) {
g_wtp.running = 0;
static const struct dfa_states {
void (*state_enter)(void);
void (*state_execute)(struct capwap_parsed_packet *packet);
} dfa_states[] = {
[CAPWAP_IDLE_STATE] = {
.state_enter = wtp_dfa_state_idle_enter,
},
[CAPWAP_DISCOVERY_STATE] = {
.state_enter = wtp_dfa_state_discovery_enter,
.state_execute = wtp_dfa_state_discovery,
},
[CAPWAP_SULKING_STATE] = {
.state_enter = wtp_dfa_state_sulking_enter,
.state_execute = wtp_dfa_state_sulking,
},
[CAPWAP_DTLS_CONNECT_STATE] = {
.state_enter = wtp_dfa_state_dtlsconnect_enter,
},
[CAPWAP_DTLS_TEARDOWN_STATE] = {
.state_enter = wtp_dfa_state_dtlsteardown_enter,
.state_execute = wtp_dfa_state_dtlsteardown,
},
[CAPWAP_JOIN_STATE] = {
.state_enter = wtp_dfa_state_join_enter,
.state_execute = wtp_dfa_state_join,
},
[CAPWAP_IMAGE_DATA_STATE] = {
},
[CAPWAP_CONFIGURE_STATE] = {
.state_enter = wtp_dfa_state_configure_enter,
.state_execute = wtp_dfa_state_configure,
},
[CAPWAP_RESET_STATE] = {
.state_enter = wtp_dfa_state_reset_enter,
},
[CAPWAP_DATA_CHECK_STATE] = {
.state_enter = wtp_dfa_state_datacheck_enter,
.state_execute = wtp_dfa_state_datacheck,
},
[CAPWAP_RUN_STATE] = {
.state_enter = wtp_dfa_state_run_enter,
.state_execute = wtp_dfa_state_run,
},
[CAPWAP_DEAD_STATE] = {
.state_enter = wtp_dfa_state_dead_enter,
}
};
static inline int is_valid_state(int state)
{
return (state >= 0) && (state < (sizeof(dfa_states) / sizeof(dfa_states[0])));
}
/* libev handler */
static void signal_cb (EV_P_ ev_signal *w, int revents);
static void capwap_control_cb(EV_P_ ev_io *w, int revents);
/* Handler signal */
static void signal_cb (EV_P_ ev_signal *w, int revents)
{
g_wtp.running = 0;
/* Teardown */
wtp_teardown_connection();
}
/* */
@ -77,228 +137,12 @@ static void wtp_dfa_execute(struct capwap_parsed_packet* packet)
{
ASSERT(packet != NULL);
switch (g_wtp.state) {
case CAPWAP_DISCOVERY_STATE:
wtp_dfa_state_discovery(packet);
break;
case CAPWAP_SULKING_STATE:
wtp_dfa_state_sulking(packet);
break;
case CAPWAP_DTLS_CONNECT_STATE:
if (!is_valid_state(g_wtp.state) ||
!dfa_states[g_wtp.state].state_execute) {
capwap_logging_debug("Got packet in invalid WTP state: %lu", g_wtp.state);
wtp_teardown_connection();
break;
case CAPWAP_DTLS_TEARDOWN_STATE:
wtp_dfa_state_dtlsteardown(packet);
break;
case CAPWAP_JOIN_STATE:
wtp_dfa_state_join(packet);
break;
case CAPWAP_CONFIGURE_STATE:
wtp_dfa_state_configure(packet);
break;
case CAPWAP_DATA_CHECK_STATE:
wtp_dfa_state_datacheck(packet);
break;
case CAPWAP_RUN_STATE:
wtp_dfa_state_run(packet);
break;
default:
capwap_logging_debug("Unknown WTP action event: %lu", g_wtp.state);
wtp_teardown_connection();
break;
}
}
/* */
static int wtp_recvfrom(struct wtp_fds* fds, void* buffer, int* size, union sockaddr_capwap* recvfromaddr, union sockaddr_capwap* recvtoaddr) {
int index;
ASSERT(fds != NULL);
ASSERT(fds->fdspoll != NULL);
ASSERT(fds->fdstotalcount > 0);
ASSERT(buffer != NULL);
ASSERT(size != NULL);
ASSERT(*size > 0);
ASSERT(recvfromaddr != NULL);
ASSERT(recvtoaddr != NULL);
/* Wait packet */
index = capwap_wait_recvready(fds->fdspoll, fds->fdstotalcount, g_wtp.timeout);
if (index < 0) {
return index;
} else if ((fds->wifieventsstartpos >= 0) && (index >= fds->wifieventsstartpos)) {
int pos = index - fds->wifieventsstartpos;
if (pos < fds->wifieventscount) {
if (!fds->wifievents[pos].event_handler) {
return CAPWAP_RECV_ERROR_SOCKET;
}
fds->wifievents[pos].event_handler(fds->fdspoll[index].fd, fds->wifievents[pos].params, fds->wifievents[pos].paramscount);
}
return WTP_RECV_NOERROR_RADIO;
} 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 WTP_RECV_NOERROR_RADIO;
}
/* Receive packet */
if (capwap_recvfrom(fds->fdspoll[index].fd, buffer, size, recvfromaddr, recvtoaddr)) {
return CAPWAP_RECV_ERROR_SOCKET;
}
return index;
}
/* */
static int wtp_dfa_init_fdspool(struct wtp_fds* fds, struct capwap_network* net) {
ASSERT(fds != NULL);
ASSERT(net != NULL);
/* */
memset(fds, 0, sizeof(struct wtp_fds));
fds->fdsnetworkcount = capwap_network_set_pollfd(net, NULL, 0);
fds->fdspoll = (struct pollfd*)capwap_alloc(sizeof(struct pollfd) * fds->fdsnetworkcount);
/* 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;
}
/* Update Event File Descriptor */
wtp_dfa_update_fdspool(fds);
return 0;
}
/* */
int wtp_dfa_update_fdspool(struct wtp_fds* fds) {
int totalcount;
int kmodcount;
int wificount;
struct pollfd* fdsbuffer;
ASSERT(fds != NULL);
/* Retrieve number of Dynamic File Descriptor Event */
kmodcount = wtp_kmod_getfd(NULL, NULL, 0);
wificount = wifi_event_getfd(NULL, NULL, 0);
if ((kmodcount < 0) || (wificount < 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 wtp_kmod_event*)((kmodcount > 0) ? capwap_alloc(sizeof(struct wtp_kmod_event) * kmodcount) : NULL);
}
/* Wifi Events Callback */
fds->wifieventsstartpos = -1;
if (wificount != fds->wifieventscount) {
if (fds->wifievents) {
capwap_free(fds->wifievents);
}
/* */
fds->wifieventscount = wificount;
fds->wifievents = (struct wifi_event*)((wificount > 0) ? capwap_alloc(sizeof(struct wifi_event) * wificount) : NULL);
}
/* Resize poll */
totalcount = fds->fdsnetworkcount + fds->kmodeventscount + fds->wifieventscount;
if (fds->fdstotalcount != totalcount) {
fdsbuffer = (struct pollfd*)capwap_alloc(sizeof(struct pollfd) * totalcount);
if (fds->fdspoll) {
if (fds->fdsnetworkcount > 0) {
memcpy(fdsbuffer, fds->fdspoll, sizeof(struct pollfd) * fds->fdsnetworkcount);
}
capwap_free(fds->fdspoll);
}
/* */
fds->fdspoll = fdsbuffer;
fds->fdstotalcount = totalcount;
}
/* Retrieve File Descriptor Kernel Module Event */
if (fds->kmodeventscount > 0) {
fds->kmodeventsstartpos = fds->fdsnetworkcount;
wtp_kmod_getfd(&fds->fdspoll[fds->kmodeventsstartpos], fds->kmodevents, fds->kmodeventscount);
}
/* Retrieve File Descriptor Wifi Event */
if (fds->wifieventscount > 0) {
fds->wifieventsstartpos = fds->fdsnetworkcount + fds->kmodeventscount;
wifi_event_getfd(&fds->fdspoll[fds->wifieventsstartpos], fds->wifievents, fds->wifieventscount);
}
return fds->fdstotalcount;
}
/* */
void wtp_dfa_free_fdspool(struct wtp_fds* fds) {
ASSERT(fds != NULL);
if (fds->fdspoll) {
capwap_free(fds->fdspoll);
}
if (fds->kmodevents) {
capwap_free(fds->kmodevents);
}
if (fds->wifievents) {
capwap_free(fds->wifievents);
}
}
/* */
static void wtp_dfa_closeapp(void) {
g_wtp.running = 0;
/* Teardown */
wtp_teardown_connection();
/* Wait RFC teardown timeout */
for (;;) {
if (capwap_timeout_wait(capwap_timeout_getcoming(g_wtp.timeout)) < 0) {
break;
}
if (capwap_timeout_hasexpired(g_wtp.timeout) == g_wtp.idtimercontrol) {
break;
}
}
/* */
ASSERT(g_wtp.state == CAPWAP_DEAD_STATE);
} else
dfa_states[g_wtp.state].state_execute(packet);
}
static void wtp_dfa_process_packet(void *buffer, int buffersize,
@ -338,10 +182,9 @@ static void wtp_dfa_process_packet(void *buffer, int buffersize,
if (oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE &&
g_wtp.dtls.action == CAPWAP_DTLS_ACTION_DATA) {
if (g_wtp.state == CAPWAP_DTLS_CONNECT_STATE) {
wtp_send_join();
} else {
wtp_dfa_change_state(CAPWAP_JOIN_STATE);
} else
wtp_teardown_connection();
}
}
} else if (oldaction == CAPWAP_DTLS_ACTION_DATA &&
g_wtp.dtls.action == CAPWAP_DTLS_ACTION_SHUTDOWN) {
@ -450,56 +293,71 @@ static void wtp_dfa_process_packet(void *buffer, int buffersize,
}
/* WTP state machine */
int wtp_dfa_running(void)
int wtp_dfa_running()
{
int result = CAPWAP_SUCCESSFUL;
char buffer[CAPWAP_MAX_PACKET_SIZE];
int buffersize;
int index;
union sockaddr_capwap fromaddr;
union sockaddr_capwap toaddr;
/* Configure poll struct */
if (wtp_dfa_init_fdspool(&g_wtp.fds, &g_wtp.net)) {
return CAPWAP_GENERIC_ERROR;
}
/* Handler signal */
g_wtp.running = 1;
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, wtp_signal_handler);
signal(SIGTERM, wtp_signal_handler);
ev_signal_init(&g_wtp.sigint_ev, signal_cb, SIGINT);
ev_signal_init(&g_wtp.sigterm_ev, signal_cb, SIGTERM);
ev_signal_start(EV_DEFAULT_UC_ &g_wtp.sigint_ev);
ev_signal_start(EV_DEFAULT_UC_ &g_wtp.sigterm_ev);
/* Init complete, start DFA */
wtp_dfa_change_state(CAPWAP_IDLE_STATE);
wtp_dfa_state_idle();
/* */
while (g_wtp.state != CAPWAP_DEAD_STATE) {
ev_run(EV_DEFAULT_UC_ 0);
return result;
}
void wtp_socket_io_start()
{
capwap_logging_debug("Start EV_IO on socket %d", g_wtp.net.socket);
/* Configure libev struct */
ev_io_init (&g_wtp.socket_ev, capwap_control_cb, g_wtp.net.socket, EV_READ);
ev_io_start(EV_DEFAULT_UC_ &g_wtp.socket_ev);
}
void wtp_socket_io_stop()
{
capwap_logging_debug("Stop EV_IO on socket %d", g_wtp.socket_ev.fd);
ev_io_stop(EV_DEFAULT_UC_ &g_wtp.socket_ev);
}
static void capwap_control_cb(EV_P_ ev_io *w, int revents)
{
char buffer[CAPWAP_MAX_PACKET_SIZE];
ssize_t r;
union sockaddr_capwap fromaddr;
union sockaddr_capwap toaddr;
while (42) {
/* If request wait packet from AC */
buffersize = sizeof(buffer);
index = wtp_recvfrom(&g_wtp.fds, &buffer, &buffersize, &fromaddr, &toaddr);
capwap_logging_debug("WTP got data: idx: %d, size: %d", index, buffersize);
do {
capwap_logging_debug("Receive CAPWAP Control Channel message");
r = capwap_recvfrom(w->fd, &buffer, sizeof(buffer),
&fromaddr, &toaddr);
} while (r < 0 && errno == EINTR);
capwap_logging_debug("WTP got data: r: %zd", r);
if (!g_wtp.running) {
capwap_logging_debug("Closing WTP, Teardown connection");
wtp_dfa_closeapp();
ev_io_stop (EV_A_ w);
break;
}
if (index == CAPWAP_RECV_ERROR_INTR ||
index == WTP_RECV_NOERROR_RADIO) {
/* Ignore recv */
continue;
} else if (index == CAPWAP_RECV_ERROR_SOCKET) {
/* Socket close */
if (r < 0) {
if (errno != EAGAIN) {
capwap_logging_debug("capwap_control_cb I/O error %m, exiting loop");
ev_io_stop (EV_A_ w);
ev_break (EV_A_ EVBREAK_ONE);
}
break;
} else if (index < 0) {
continue;
/* TODO: Really? Previosly, this was hidden in the
* overly deep indention, check if that is correct */
}
if (g_wtp.teardown) {
@ -507,24 +365,29 @@ int wtp_dfa_running(void)
continue; /* Drop packet */
}
wtp_dfa_process_packet(&buffer, buffersize, &fromaddr, &toaddr);
wtp_dfa_process_packet(&buffer, r, &fromaddr, &toaddr);
}
/* Free memory */
wtp_dfa_free_fdspool(&g_wtp.fds);
return result;
}
/* Change WTP state machine */
void wtp_dfa_change_state(int state) {
if (state != g_wtp.state) {
capwap_logging_debug("WTP change state from %s to %s", capwap_dfa_getname(g_wtp.state), capwap_dfa_getname(state));
capwap_logging_debug("WTP change state from %s to %s",
capwap_dfa_getname(g_wtp.state),
capwap_dfa_getname(state));
g_wtp.state = state;
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timercontrol);
if (is_valid_state(g_wtp.state) &&
dfa_states[g_wtp.state].state_enter)
dfa_states[g_wtp.state].state_enter();
}
}
/* */
void wtp_free_reference_last_request(void) {
void wtp_free_reference_last_request(void)
{
capwap_list_flush(g_wtp.requestfragmentpacket);
}
@ -536,8 +399,7 @@ void wtp_free_reference_last_response(void) {
}
/* */
void wtp_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index,
void* context, void* param)
static void wtp_dfa_retransmition_timeout_cb(EV_P_ ev_timer *w, int revents)
{
if (!g_wtp.requestfragmentpacket->count) {
capwap_logging_warning("Invalid retransmition request packet");
@ -564,8 +426,31 @@ void wtp_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long
}
/* Update timeout */
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_RETRANSMIT_INTERVAL,
wtp_dfa_retransmition_timeout, NULL, NULL);
ev_timer_again(EV_A_ w);
}
/* */
void wtp_dfa_start_retransmition_timer()
{
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timercontrol);
ev_timer_init(&g_wtp.timercontrol, wtp_dfa_retransmition_timeout_cb,
0., WTP_RETRANSMIT_INTERVAL / 1000.0);
ev_timer_again(EV_DEFAULT_UC_ &g_wtp.timercontrol);
}
/* */
void wtp_dfa_stop_retransmition_timer()
{
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timercontrol);
}
/* */
void wtp_timeout_stop_all()
{
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timercontrol);
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timerecho);
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timerkeepalive);
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timerkeepalivedead);
}
void wtp_reset_state(void)

View File

@ -1,6 +1,8 @@
#ifndef __WTP_DFA_HEADER__
#define __WTP_DFA_HEADER__
#include <ev.h>
#include "capwap_network.h"
#include "capwap_protocol.h"
#include "capwap_element.h"
@ -16,13 +18,17 @@ void wtp_free_discovery_response_array(void);
/* */
void wtp_teardown_connection(void);
/* */
void wtp_socket_io_start(void);
void wtp_socket_io_stop(void);
/* */
void wtp_free_packet_rxmng(void);
void wtp_free_reference_last_request(void);
void wtp_free_reference_last_response(void);
/* State machine */
int wtp_dfa_running(void);
int wtp_dfa_running();
void wtp_dfa_change_state(int state);
/* */
@ -30,39 +36,32 @@ void wtp_start_dtlssetup(void);
void wtp_start_datachannel(void);
/* */
void wtp_send_join(void);
void wtp_send_configure(void);
void wtp_send_datacheck(void);
/* */
void wtp_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
int wtp_dfa_update_fdspool(struct wtp_fds* fds);
void wtp_dfa_free_fdspool(struct wtp_fds* fds);
void wtp_dfa_start_retransmition_timer(void);
void wtp_dfa_stop_retransmition_timer(void);
/* */
void wtp_dfa_state_idle(void);
void wtp_dfa_state_idle_enter(void);
void wtp_dfa_state_discovery_enter(void);
void wtp_dfa_state_sulking_enter(void);
void wtp_dfa_state_dtlsconnect_enter(void);
void wtp_dfa_state_dtlsteardown_enter(void);
void wtp_dfa_state_join_enter(void);
void wtp_dfa_state_configure_enter(void);
void wtp_dfa_state_reset_enter(void);
void wtp_dfa_state_datacheck_enter(void);
void wtp_dfa_state_run_enter(void);
void wtp_dfa_state_dead_enter(void);
void wtp_dfa_state_discovery(struct capwap_parsed_packet* packet);
void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet);
void wtp_dfa_state_sulking(struct capwap_parsed_packet* packet);
void wtp_dfa_state_sulking_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet);
void wtp_dfa_state_join(struct capwap_parsed_packet* packet);
void wtp_dfa_state_configure(struct capwap_parsed_packet* packet);
void wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet);
void wtp_dfa_state_run(struct capwap_parsed_packet* packet);
void wtp_dfa_state_run_echo_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void wtp_dfa_state_run_keepalive_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void wtp_dfa_state_run_keepalivedead_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
void wtp_dfa_state_reset(void);
/* */
void wtp_ieee80211_packet(uint8_t radioid, const struct ieee80211_header* header, int length);
@ -70,6 +69,7 @@ void wtp_ieee80211_packet(uint8_t radioid, const struct ieee80211_header* header
void wtp_recv_data_keepalive(void);
void wtp_recv_data(uint8_t* buffer, int length);
void wtp_timeout_stop_all(void);
void wtp_reset_state(void);
#endif /* __WTP_DFA_HEADER__ */

View File

@ -81,7 +81,7 @@ static void cfg_binding_add_ieee80211(struct capwap_packet_txmng* txmngpacket)
}
/* */
void wtp_send_configure(void)
void wtp_dfa_state_configure_enter(void)
{
struct capwap_header_data capwapheader;
struct capwap_acnamepriority_element acnamepriority;
@ -129,9 +129,7 @@ void wtp_send_configure(void)
}
g_wtp.retransmitcount = 0;
wtp_dfa_change_state(CAPWAP_CONFIGURE_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_RETRANSMIT_INTERVAL,
wtp_dfa_retransmition_timeout, NULL, NULL);
wtp_dfa_start_retransmition_timer();
}
/* */
@ -160,6 +158,8 @@ void wtp_dfa_state_configure(struct capwap_parsed_packet* packet)
return;
}
wtp_dfa_stop_retransmition_timer();
g_wtp.localseqnumber++;
/* Valid packet, free request packet */
@ -187,5 +187,5 @@ void wtp_dfa_state_configure(struct capwap_parsed_packet* packet)
return;
}
wtp_send_datacheck(); /* Send change state event packet */
wtp_dfa_change_state(CAPWAP_DATA_CHECK_STATE); /* Send change state event packet */
}

View File

@ -4,7 +4,7 @@
#include "wtp_dfa.h"
/* */
void wtp_send_datacheck(void)
void wtp_dfa_state_datacheck_enter(void)
{
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
@ -44,9 +44,7 @@ void wtp_send_datacheck(void)
}
g_wtp.retransmitcount = 0;
wtp_dfa_change_state(CAPWAP_DATA_CHECK_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_RETRANSMIT_INTERVAL,
wtp_dfa_retransmition_timeout, NULL, NULL);
wtp_dfa_start_retransmition_timer();
}
/* */
@ -74,15 +72,19 @@ void wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet)
return;
}
wtp_dfa_stop_retransmition_timer();
g_wtp.localseqnumber++;
/* Valid packet, free request packet */
wtp_free_reference_last_request();
/* Check the success of the Request */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet,
CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
capwap_logging_warning("Receive Data Check Response with error: %d", (int)resultcode->code);
capwap_logging_warning("Receive Data Check Response with error: %d",
(int)resultcode->code);
wtp_teardown_connection();
return;

View File

@ -91,8 +91,7 @@ static void wtp_send_discovery_request()
}
/* */
void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned long index,
void* context, void* param)
static void wtp_dfa_state_discovery_timeout(EV_P_ ev_timer *w, int revents)
{
long discoveryinterval;
@ -198,6 +197,7 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
if (capwap_connect_socket(&g_wtp.net, &peeraddr) < 0) {
capwap_logging_fatal("Cannot bind control address");
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
return;
}
@ -205,6 +205,7 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
/* Retrieve local address */
if (capwap_getsockname(&g_wtp.net, &localaddr) < 0) {
capwap_logging_fatal("Cannot get local endpoint address");
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
return;
}
@ -214,7 +215,7 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
/* */
if (!g_wtp.enabledtls) {
wtp_send_join(); /* Bypass DTLS connection */
wtp_dfa_change_state(CAPWAP_JOIN_STATE); /* Bypass DTLS connection */
} else {
wtp_start_dtlssetup(); /* Create DTLS connection */
}
@ -228,17 +229,30 @@ void wtp_dfa_state_discovery_timeout(struct capwap_timeout* timeout, unsigned lo
if (g_wtp.discoverycount >= WTP_MAX_DISCOVERY_COUNT) {
/* Timeout discovery state */
wtp_dfa_change_state(CAPWAP_SULKING_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_SILENT_INTERVAL,
wtp_dfa_state_sulking_timeout, NULL, NULL);
return;
}
wtp_send_discovery_request();
/* Wait before send another Discovery Request */
discoveryinterval = (capwap_get_rand(g_wtp.discoveryinterval - WTP_MIN_DISCOVERY_INTERVAL) + WTP_MIN_DISCOVERY_INTERVAL);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, discoveryinterval, wtp_dfa_state_discovery_timeout, NULL, NULL);
discoveryinterval = capwap_get_rand(g_wtp.discoveryinterval - WTP_MIN_DISCOVERY_INTERVAL) +
WTP_MIN_DISCOVERY_INTERVAL;
w->repeat = discoveryinterval / 1000.0;
ev_timer_again(EV_A_ w);
}
/* */
void wtp_dfa_state_discovery_enter(void)
{
long discoveryinterval;
discoveryinterval = capwap_get_rand(g_wtp.discoveryinterval - WTP_MIN_DISCOVERY_INTERVAL) +
WTP_MIN_DISCOVERY_INTERVAL;
/* Wait before send Discovery Request */
ev_timer_init(&g_wtp.timercontrol, wtp_dfa_state_discovery_timeout,
0., discoveryinterval / 1000.0);
ev_timer_again(EV_DEFAULT_UC_ &g_wtp.timercontrol);
}
/* */

View File

@ -1,35 +1,46 @@
#include "wtp.h"
#include "capwap_dfa.h"
#include "wtp_dfa.h"
#include "wtp_radio.h"
/* */
static void wtp_dfa_state_dtlsconnect_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
static void wtp_dfa_state_dtlsconnect_timeout(EV_P_ ev_timer *w, int revents)
{
wtp_teardown_connection();
}
/* */
void wtp_start_dtlssetup(void) {
void wtp_dfa_state_dead_enter(void)
{
ev_break(EV_DEFAULT_UC_ EVBREAK_ALL);
}
/* */
void wtp_dfa_state_dtlsconnect_enter(void)
{
ev_timer_init(&g_wtp.timercontrol, wtp_dfa_state_dtlsconnect_timeout,
WTP_DTLS_INTERVAL / 1000.0, 0.);
ev_timer_start(EV_DEFAULT_UC_ &g_wtp.timercontrol);
}
/* */
void wtp_start_dtlssetup(void)
{
/* Create DTLS session */
if (!capwap_crypt_createsession(&g_wtp.dtls, &g_wtp.dtlscontext)) {
wtp_dfa_change_state(CAPWAP_SULKING_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_SILENT_INTERVAL,
wtp_dfa_state_sulking_timeout, NULL, NULL);
return;
}
if (capwap_crypt_open(&g_wtp.dtls) == CAPWAP_HANDSHAKE_ERROR) {
wtp_dfa_change_state(CAPWAP_SULKING_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_SILENT_INTERVAL,
wtp_dfa_state_sulking_timeout, NULL, NULL);
} else {
} else
wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_DTLS_INTERVAL,
wtp_dfa_state_dtlsconnect_timeout, NULL, NULL);
}
}
/* */
void wtp_start_datachannel(void) {
void wtp_start_datachannel(void)
{
union sockaddr_capwap dataaddr;
/* Set AC data address */
@ -39,7 +50,9 @@ void wtp_start_datachannel(void) {
#ifdef DEBUG
{
char addr[INET6_ADDRSTRLEN];
capwap_logging_debug("Create data channel with peer %s:%d", capwap_address_to_string(&dataaddr, addr, INET6_ADDRSTRLEN), (int)CAPWAP_GET_NETWORK_PORT(&dataaddr));
capwap_logging_debug("Create data channel with peer %s:%d",
capwap_address_to_string(&dataaddr, addr, INET6_ADDRSTRLEN),
(int)CAPWAP_GET_NETWORK_PORT(&dataaddr));
}
#endif
@ -57,14 +70,10 @@ void wtp_start_datachannel(void) {
/* Set timer */
wtp_dfa_change_state(CAPWAP_RUN_STATE);
capwap_timeout_unset(g_wtp.timeout, g_wtp.idtimercontrol);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimerecho, g_wtp.echointerval, wtp_dfa_state_run_echo_timeout, NULL, NULL);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimerkeepalivedead, WTP_DATACHANNEL_KEEPALIVEDEAD, wtp_dfa_state_run_keepalivedead_timeout, NULL, NULL);
}
/* */
static void wtp_dfa_state_dtlsteardown_timeout(struct capwap_timeout* timeout,
unsigned long index, void* context, void* param)
static void wtp_dfa_state_dtlsteardown_timeout(EV_P_ ev_timer *w, int revents)
{
/* Free and reset resource */
if (g_wtp.dtls.enable)
@ -76,6 +85,9 @@ static void wtp_dfa_state_dtlsteardown_timeout(struct capwap_timeout* timeout,
g_wtp.acname.name = NULL;
}
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
/* */
wtp_reset_state();
@ -85,12 +97,17 @@ static void wtp_dfa_state_dtlsteardown_timeout(struct capwap_timeout* timeout,
} else if ((g_wtp.faileddtlssessioncount >= WTP_FAILED_DTLS_SESSION_RETRY) ||
(g_wtp.faileddtlsauthfailcount >= WTP_FAILED_DTLS_SESSION_RETRY)) {
wtp_dfa_change_state(CAPWAP_SULKING_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_SILENT_INTERVAL,
wtp_dfa_state_sulking_timeout, NULL, NULL);
} else {
} else
wtp_dfa_change_state(CAPWAP_IDLE_STATE);
wtp_dfa_state_idle();
}
}
/* */
void wtp_dfa_state_dtlsteardown_enter(void)
{
wtp_timeout_stop_all();
ev_timer_init(&g_wtp.timercontrol, wtp_dfa_state_dtlsteardown_timeout,
WTP_DTLS_SESSION_DELETE / 1000.0, 0.);
ev_timer_start(EV_DEFAULT_UC_ &g_wtp.timercontrol);
}
/* */
@ -102,18 +119,16 @@ void wtp_teardown_connection(void)
{
g_wtp.teardown = 1;
/* TODO: close SSID ? */
wtp_radio_reset();
/* DTSL Control */
ev_io_stop(EV_DEFAULT_UC_ &g_wtp.socket_ev);
/* DTLS Control */
if (g_wtp.dtls.enable)
capwap_crypt_close(&g_wtp.dtls);
/* Close data channel session */
wtp_kmod_resetsession();
/* */
wtp_dfa_change_state(CAPWAP_DTLS_TEARDOWN_STATE);
capwap_timeout_unsetall(g_wtp.timeout);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_DTLS_SESSION_DELETE,
wtp_dfa_state_dtlsteardown_timeout, NULL, NULL);
}

View File

@ -23,11 +23,13 @@ static int wtp_join_prefered_ac()
g_wtp.acpreferedselected++;
/* restart and connect the control Socket */
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
if (capwap_bind_sockets(&g_wtp.net) < 0) {
capwap_logging_fatal("Cannot bind control address");
return -1;
}
wtp_socket_io_start();
if(!peeraddr->resolved) {
if (capwap_address_from_string(peeraddr->fqdn, &peeraddr->sockaddr)) {
@ -42,6 +44,7 @@ static int wtp_join_prefered_ac()
if (capwap_connect_socket(&g_wtp.net, &peeraddr->sockaddr) < 0) {
capwap_logging_fatal("Cannot bind control address");
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
return -1;
}
@ -49,6 +52,7 @@ static int wtp_join_prefered_ac()
/* Retrieve local address */
if (capwap_getsockname(&g_wtp.net, &localaddr) < 0) {
capwap_logging_fatal("Cannot get local endpoint address");
wtp_socket_io_stop();
capwap_close_sockets(&g_wtp.net);
return -1;
}
@ -58,10 +62,9 @@ static int wtp_join_prefered_ac()
/* */
if (!g_wtp.enabledtls) {
wtp_send_join(); /* Bypass DTLS connection */
} else {
wtp_dfa_change_state(CAPWAP_JOIN_STATE); /* Bypass DTLS connection */
} else
wtp_start_dtlssetup(); /* Create DTLS connection */
}
return 0;
}
@ -70,32 +73,29 @@ static int wtp_join_prefered_ac()
}
/* */
void wtp_dfa_state_idle(void) {
long discoveryinterval;
void wtp_dfa_state_idle_enter(void)
{
/* Remove teardown */
g_wtp.teardown = 0;
capwap_timeout_unsetall(g_wtp.timeout);
wtp_timeout_stop_all();
if (wtp_join_prefered_ac() == 0)
return;
if (g_wtp.net.socket < 0)
if (g_wtp.net.socket < 0) {
if (capwap_bind_sockets(&g_wtp.net) < 0) {
capwap_logging_fatal("Cannot bind control address");
exit(-1);
}
wtp_socket_io_start();
}
/* Discovery AC */
g_wtp.acpreferedselected = 0;
/* Set discovery interval */
g_wtp.discoverycount = 0;
discoveryinterval = capwap_get_rand(g_wtp.discoveryinterval - WTP_MIN_DISCOVERY_INTERVAL) + WTP_MIN_DISCOVERY_INTERVAL;
/* Change state */
wtp_dfa_change_state(CAPWAP_DISCOVERY_STATE);
/* Wait before send Discovery Request */
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, discoveryinterval, wtp_dfa_state_discovery_timeout, NULL, NULL);
}

View File

@ -7,7 +7,7 @@
#include "wtp_radio.h"
/* */
void wtp_send_join(void)
void wtp_dfa_state_join_enter(void)
{
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
@ -87,9 +87,7 @@ void wtp_send_join(void)
}
g_wtp.retransmitcount = 0;
wtp_dfa_change_state(CAPWAP_JOIN_STATE);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_RETRANSMIT_INTERVAL,
wtp_dfa_retransmition_timeout, NULL, NULL);
wtp_dfa_start_retransmition_timer();
}
/* */
@ -119,6 +117,8 @@ void wtp_dfa_state_join(struct capwap_parsed_packet* packet)
return;
}
wtp_dfa_stop_retransmition_timer();
g_wtp.localseqnumber++;
/* Valid packet, free request packet */
@ -160,5 +160,5 @@ void wtp_dfa_state_join(struct capwap_parsed_packet* packet)
return;
}
wtp_send_configure(); /* Send configuration packet */
wtp_dfa_change_state(CAPWAP_CONFIGURE_STATE);
}

View File

@ -3,7 +3,8 @@
#include "wtp_dfa.h"
/* */
void wtp_dfa_state_reset(void) {
void wtp_dfa_state_reset_enter(void)
{
/* Teardown connection and close application */
g_wtp.running = 0;
wtp_teardown_connection();

View File

@ -5,6 +5,11 @@
#include "wtp_radio.h"
#include "ieee80211.h"
/* ev timer callbacks */
static void wtp_dfa_state_run_echo_timeout(EV_P_ ev_timer *w, int revents);
static void wtp_dfa_state_run_keepalive_timeout(EV_P_ ev_timer *w, int revents);
static void wtp_dfa_state_run_keepalivedead_timeout(EV_P_ ev_timer *w, int revents);
/* */
static int send_echo_request(void)
{
@ -241,8 +246,7 @@ static void receive_ieee80211_wlan_configuration_request(struct capwap_parsed_pa
}
/* */
void wtp_dfa_state_run_echo_timeout(struct capwap_timeout* timeout, unsigned long index,
void* context, void* param)
static void wtp_dfa_state_run_echo_timeout(EV_P_ ev_timer *w, int revents)
{
capwap_logging_debug("Send Echo Request");
if (send_echo_request()) {
@ -252,18 +256,15 @@ void wtp_dfa_state_run_echo_timeout(struct capwap_timeout* timeout, unsigned lon
}
g_wtp.retransmitcount = 0;
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimercontrol, WTP_RETRANSMIT_INTERVAL,
wtp_dfa_retransmition_timeout, NULL, NULL);
wtp_dfa_start_retransmition_timer();
}
/* */
void wtp_dfa_state_run_keepalive_timeout(struct capwap_timeout* timeout, unsigned long index,
void* context, void* param)
static void wtp_dfa_state_run_keepalive_timeout(EV_P_ ev_timer *w, int revents)
{
capwap_logging_debug("Send Keep-Alive");
capwap_timeout_unset(g_wtp.timeout, g_wtp.idtimerkeepalive);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimerkeepalivedead, WTP_DATACHANNEL_KEEPALIVEDEAD,
wtp_dfa_state_run_keepalivedead_timeout, NULL, NULL);
ev_timer_again(EV_A_ &g_wtp.timerkeepalivedead);
if (wtp_kmod_send_keepalive()) {
capwap_logging_error("Unable to send Keep-Alive");
@ -272,8 +273,7 @@ void wtp_dfa_state_run_keepalive_timeout(struct capwap_timeout* timeout, unsigne
}
/* */
void wtp_dfa_state_run_keepalivedead_timeout(struct capwap_timeout* timeout, unsigned long index,
void* context, void* param)
static void wtp_dfa_state_run_keepalivedead_timeout(EV_P_ ev_timer *w, int revents)
{
capwap_logging_info("Keep-Alive timeout, teardown");
wtp_teardown_connection();
@ -284,9 +284,10 @@ void wtp_recv_data_keepalive(void) {
capwap_logging_debug("Receive Keep-Alive");
/* Receive Data Keep-Alive, wait for next packet */
capwap_timeout_unset(g_wtp.timeout, g_wtp.idtimerkeepalivedead);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimerkeepalive, WTP_DATACHANNEL_KEEPALIVE_INTERVAL,
wtp_dfa_state_run_keepalive_timeout, NULL, NULL);
if (ev_is_active(&g_wtp.timerkeepalivedead))
ev_timer_stop(EV_DEFAULT_UC_ &g_wtp.timerkeepalivedead);
ev_timer_again(EV_DEFAULT_UC_ &g_wtp.timerkeepalive);
}
/* */
@ -307,6 +308,23 @@ void wtp_recv_data(uint8_t* buffer, int length) {
}
}
/* */
void wtp_dfa_state_run_enter()
{
ev_timer_init(&g_wtp.timerecho,
wtp_dfa_state_run_echo_timeout,
0., g_wtp.echointerval / 1000.0);
ev_timer_init(&g_wtp.timerkeepalivedead,
wtp_dfa_state_run_keepalivedead_timeout,
0., WTP_DATACHANNEL_KEEPALIVEDEAD / 1000.0);
ev_timer_init(&g_wtp.timerkeepalive,
wtp_dfa_state_run_keepalive_timeout,
0., WTP_DATACHANNEL_KEEPALIVE_INTERVAL / 1000.0);
ev_timer_again(EV_DEFAULT_UC_ &g_wtp.timerecho);
ev_timer_again(EV_DEFAULT_UC_ &g_wtp.timerkeepalivedead);
}
/* */
void wtp_dfa_state_run(struct capwap_parsed_packet* packet)
{
@ -316,9 +334,12 @@ void wtp_dfa_state_run(struct capwap_parsed_packet* packet)
g_wtp.localseqnumber != packet->rxmngpacket->ctrlmsg.seq)
return;
/* Update sequence */
if (!capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type))
if (!capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type)) {
wtp_dfa_stop_retransmition_timer();
/* Update sequence */
g_wtp.localseqnumber++;
}
/* Parsing message */
switch (packet->rxmngpacket->ctrlmsg.type) {
@ -333,9 +354,9 @@ void wtp_dfa_state_run(struct capwap_parsed_packet* packet)
case CAPWAP_ECHO_RESPONSE:
if (!receive_echo_response(packet)) {
capwap_logging_debug("Receive Echo Response");
capwap_timeout_unset(g_wtp.timeout, g_wtp.idtimercontrol);
capwap_timeout_set(g_wtp.timeout, g_wtp.idtimerecho, g_wtp.echointerval,
wtp_dfa_state_run_echo_timeout, NULL, NULL);
g_wtp.timerecho.repeat = g_wtp.echointerval / 1000.0;
ev_timer_again(EV_DEFAULT_UC_ &g_wtp.timerecho);
}
break;
@ -363,7 +384,6 @@ void wtp_dfa_state_run(struct capwap_parsed_packet* packet)
case CAPWAP_RESET_REQUEST:
receive_reset_request(packet);
wtp_dfa_change_state(CAPWAP_RESET_STATE);
wtp_dfa_state_reset();
break;
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST:

View File

@ -3,14 +3,22 @@
#include "wtp_dfa.h"
/* */
void wtp_dfa_state_sulking_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
static void wtp_dfa_state_sulking_timeout(EV_P_ ev_timer *w, int revents)
{
g_wtp.discoverycount = 0;
g_wtp.faileddtlssessioncount = 0;
g_wtp.faileddtlsauthfailcount = 0;
/* */
wtp_dfa_change_state(CAPWAP_IDLE_STATE);
wtp_dfa_state_idle();
}
/* */
void wtp_dfa_state_sulking_enter()
{
ev_timer_init(&g_wtp.timercontrol, wtp_dfa_state_sulking_timeout,
WTP_SILENT_INTERVAL / 1000.0, 0.);
ev_timer_start(EV_DEFAULT_UC_ &g_wtp.timercontrol);
}
/* */

View File

@ -5,6 +5,9 @@
#include <netlink/genl/ctrl.h>
#include "nlsmartcapwap.h"
/* libev handler */
static void wtp_kmod_event_receive(EV_P_ ev_io *w, int revents);
/* Compatibility functions */
#ifdef HAVE_LIBNL_10
static uint32_t g_portbitmap[32] = { 0 };
@ -183,15 +186,15 @@ static int wtp_kmod_link(void) {
}
/* */
static void wtp_kmod_event_receive(int fd, void** params, int paramscount) {
static void wtp_kmod_event_receive(EV_P_ ev_io *w, int revents)
{
struct wtp_kmod_handle *kmodhandle = (struct wtp_kmod_handle *)
(((char *)w) - offsetof(struct wtp_kmod_handle, nl_ev));
int res;
ASSERT(fd >= 0);
ASSERT(params != NULL);
ASSERT(paramscount == 2);
/* */
res = nl_recvmsgs((struct nl_sock*)params[0], (struct nl_cb*)params[1]);
res = nl_recvmsgs(kmodhandle->nl, kmodhandle->nl_cb);
if (res) {
capwap_logging_warning("Receive kernel module message failed: %d", res);
}
@ -496,34 +499,6 @@ int wtp_kmod_isconnected(void) {
return (g_wtp.kmodhandle.nlsmartcapwap_id ? 1 : 0);
}
/* */
int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count) {
int kmodcount = (wtp_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_wtp.kmodhandle.nl_fd;
fds[0].events = POLLIN | POLLERR | POLLHUP;
/* */
events[0].event_handler = wtp_kmod_event_receive;
events[0].params[0] = (void*)g_wtp.kmodhandle.nl;
events[0].params[1] = (void*)g_wtp.kmodhandle.nl_cb;
events[0].paramscount = 2;
return kmodcount;
}
/* */
int wtp_kmod_init(void) {
int result;
@ -542,8 +517,6 @@ int wtp_kmod_init(void) {
return -1;
}
g_wtp.kmodhandle.nl_fd = nl_socket_get_fd(g_wtp.kmodhandle.nl);
/* Get nlsmartcapwap netlink family */
g_wtp.kmodhandle.nlsmartcapwap_id = genl_ctrl_resolve(g_wtp.kmodhandle.nl, NLSMARTCAPWAP_GENL_NAME);
if (g_wtp.kmodhandle.nlsmartcapwap_id < 0) {
@ -579,6 +552,12 @@ int wtp_kmod_init(void) {
/* */
g_wtp.kmodhandle.interfaces = capwap_list_create();
/* Configure libev struct */
ev_io_init(&g_wtp.kmodhandle.nl_ev, wtp_kmod_event_receive,
nl_socket_get_fd(g_wtp.kmodhandle.nl), EV_READ);
ev_io_start(EV_DEFAULT_UC_ &g_wtp.kmodhandle.nl_ev);
return 0;
}

View File

@ -21,9 +21,9 @@ struct wtp_kmod_iface_handle {
/* */
struct wtp_kmod_handle {
struct nl_sock* nl;
int nl_fd;
struct nl_cb* nl_cb;
int nlsmartcapwap_id;
ev_io nl_ev;
/* */
struct nl_sock* nlmsg;

View File

@ -165,9 +165,6 @@ void wtp_radio_reset()
radio->initialized = 0;
}
/* Update Event File Descriptor */
wtp_dfa_update_fdspool(&g_wtp.fds);
}
static void push_wtp_update_configuration_item(struct capwap_array *updateitems,
@ -709,9 +706,6 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
/* Mark interface as used */
wlan->in_use = 1;
/* Update Event File Descriptor */
wtp_dfa_update_fdspool(&g_wtp.fds);
/* Retrieve macaddress of new device */
bssid->radioid = addwlan->radioid;
bssid->wlanid = addwlan->wlanid;