diff --git a/README.md b/README.md index f395b7d..888ad98 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/build/wtp/Makefile.am b/build/wtp/Makefile.am index 67c08c5..10c21aa 100755 --- a/build/wtp/Makefile.am +++ b/build/wtp/Makefile.am @@ -23,6 +23,7 @@ bin_PROGRAMS = wtp AM_CFLAGS = -D_REENTRANT \ -D_GNU_SOURCE \ + -fno-strict-aliasing \ ${LIBNL_CFLAGS} if DTLS_ENABLED diff --git a/configure.ac b/configure.ac index 481fab4..5691fba 100644 --- a/configure.ac +++ b/configure.ac @@ -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"]) diff --git a/src/common/capwap_network.c b/src/common/capwap_network.c index 2b30a3c..f74a3c3 100644 --- a/src/common/capwap_network.c +++ b/src/common/capwap_network.c @@ -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; } /* */ diff --git a/src/common/capwap_network.h b/src/common/capwap_network.h index 054a5f8..0ecd01f 100644 --- a/src/common/capwap_network.h +++ b/src/common/capwap_network.h @@ -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); diff --git a/src/wtp/binding/ieee80211/netlink_link.c b/src/wtp/binding/ieee80211/netlink_link.c index 7ccc1b0..e752704 100644 --- a/src/wtp/binding/ieee80211/netlink_link.c +++ b/src/wtp/binding/ieee80211/netlink_link.c @@ -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; } /* */ diff --git a/src/wtp/binding/ieee80211/netlink_link.h b/src/wtp/binding/ieee80211/netlink_link.h index b5c7597..43a08f2 100644 --- a/src/wtp/binding/ieee80211/netlink_link.h +++ b/src/wtp/binding/ieee80211/netlink_link.h @@ -4,6 +4,8 @@ #include #include +#include + /* */ #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); /* */ diff --git a/src/wtp/binding/ieee80211/wifi_drivers.c b/src/wtp/binding/ieee80211/wifi_drivers.c index 86fd2eb..75fa598 100644 --- a/src/wtp/binding/ieee80211/wifi_drivers.c +++ b/src/wtp/binding/ieee80211/wifi_drivers.c @@ -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) || diff --git a/src/wtp/binding/ieee80211/wifi_drivers.h b/src/wtp/binding/ieee80211/wifi_drivers.h index 19389bf..322ce65 100644 --- a/src/wtp/binding/ieee80211/wifi_drivers.h +++ b/src/wtp/binding/ieee80211/wifi_drivers.h @@ -5,6 +5,8 @@ #include #include "ieee80211.h" +#include + /* */ #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); diff --git a/src/wtp/binding/ieee80211/wifi_nl80211.c b/src/wtp/binding/ieee80211/wifi_nl80211.c index 06ee763..136e8cf 100644 --- a/src/wtp/binding/ieee80211/wifi_nl80211.c +++ b/src/wtp/binding/ieee80211/wifi_nl80211.c @@ -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, diff --git a/src/wtp/binding/ieee80211/wifi_nl80211.h b/src/wtp/binding/ieee80211/wifi_nl80211.h index 9687b91..aaadce9 100644 --- a/src/wtp/binding/ieee80211/wifi_nl80211.h +++ b/src/wtp/binding/ieee80211/wifi_nl80211.h @@ -1,6 +1,8 @@ #ifndef __WIFI_NL80211_HEADER__ #define __WIFI_NL80211_HEADER__ +#include + #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; }; diff --git a/src/wtp/wtp.c b/src/wtp/wtp.c index f84366d..9a1c126 100644 --- a/src/wtp/wtp.c +++ b/src/wtp/wtp.c @@ -10,6 +10,7 @@ #include "wtp_radio.h" #include +#include #include 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); } diff --git a/src/wtp/wtp.h b/src/wtp/wtp.h index 2b1487d..ebdeb55 100644 --- a/src/wtp/wtp.h +++ b/src/wtp/wtp.h @@ -2,6 +2,8 @@ #define __CAPWAP_WTP_HEADER__ /* standard include */ +#include + #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; diff --git a/src/wtp/wtp_dfa.c b/src/wtp/wtp_dfa.c index 6217c9b..1072c65 100644 --- a/src/wtp/wtp_dfa.c +++ b/src/wtp/wtp_dfa.c @@ -6,14 +6,74 @@ #include "wtp_radio.h" #include +#include #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) diff --git a/src/wtp/wtp_dfa.h b/src/wtp/wtp_dfa.h index 85a0397..6d459fc 100644 --- a/src/wtp/wtp_dfa.h +++ b/src/wtp/wtp_dfa.h @@ -1,6 +1,8 @@ #ifndef __WTP_DFA_HEADER__ #define __WTP_DFA_HEADER__ +#include + #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__ */ diff --git a/src/wtp/wtp_dfa_configure.c b/src/wtp/wtp_dfa_configure.c index 32d54ca..8a1a44c 100644 --- a/src/wtp/wtp_dfa_configure.c +++ b/src/wtp/wtp_dfa_configure.c @@ -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 */ } diff --git a/src/wtp/wtp_dfa_datacheck.c b/src/wtp/wtp_dfa_datacheck.c index 8deb3d6..5afbe83 100644 --- a/src/wtp/wtp_dfa_datacheck.c +++ b/src/wtp/wtp_dfa_datacheck.c @@ -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; diff --git a/src/wtp/wtp_dfa_discovery.c b/src/wtp/wtp_dfa_discovery.c index cdd8638..17a8440 100644 --- a/src/wtp/wtp_dfa_discovery.c +++ b/src/wtp/wtp_dfa_discovery.c @@ -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); } /* */ diff --git a/src/wtp/wtp_dfa_dtls.c b/src/wtp/wtp_dfa_dtls.c index c6ae4f3..372e93f 100644 --- a/src/wtp/wtp_dfa_dtls.c +++ b/src/wtp/wtp_dfa_dtls.c @@ -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); } diff --git a/src/wtp/wtp_dfa_idle.c b/src/wtp/wtp_dfa_idle.c index 8985e9d..2d24b2f 100644 --- a/src/wtp/wtp_dfa_idle.c +++ b/src/wtp/wtp_dfa_idle.c @@ -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); } diff --git a/src/wtp/wtp_dfa_join.c b/src/wtp/wtp_dfa_join.c index 85b6b2a..e2a61af 100644 --- a/src/wtp/wtp_dfa_join.c +++ b/src/wtp/wtp_dfa_join.c @@ -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); } diff --git a/src/wtp/wtp_dfa_reset.c b/src/wtp/wtp_dfa_reset.c index 32cf377..00c3e65 100644 --- a/src/wtp/wtp_dfa_reset.c +++ b/src/wtp/wtp_dfa_reset.c @@ -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(); diff --git a/src/wtp/wtp_dfa_run.c b/src/wtp/wtp_dfa_run.c index 05769e5..325c6f2 100644 --- a/src/wtp/wtp_dfa_run.c +++ b/src/wtp/wtp_dfa_run.c @@ -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: diff --git a/src/wtp/wtp_dfa_sulking.c b/src/wtp/wtp_dfa_sulking.c index b8c3484..f540fd2 100644 --- a/src/wtp/wtp_dfa_sulking.c +++ b/src/wtp/wtp_dfa_sulking.c @@ -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); } /* */ diff --git a/src/wtp/wtp_kmod.c b/src/wtp/wtp_kmod.c index 826707b..08016f9 100644 --- a/src/wtp/wtp_kmod.c +++ b/src/wtp/wtp_kmod.c @@ -5,6 +5,9 @@ #include #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; } diff --git a/src/wtp/wtp_kmod.h b/src/wtp/wtp_kmod.h index 2588277..072b857 100644 --- a/src/wtp/wtp_kmod.h +++ b/src/wtp/wtp_kmod.h @@ -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; diff --git a/src/wtp/wtp_radio.c b/src/wtp/wtp_radio.c index d884183..7b70209 100644 --- a/src/wtp/wtp_radio.c +++ b/src/wtp/wtp_radio.c @@ -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;