diff --git a/wireless/wifictld/src/wifictld.c b/wireless/wifictld/src/main.c similarity index 100% rename from wireless/wifictld/src/wifictld.c rename to wireless/wifictld/src/main.c diff --git a/wireless/wifictld/src/ubus.c b/wireless/wifictld/src/ubus.c index e526c81..7898ae9 100644 --- a/wireless/wifictld/src/ubus.c +++ b/wireless/wifictld/src/ubus.c @@ -1,6 +1,10 @@ +#ifndef __WIFICTLD_UBUS_H +#define __WIFICTLD_UBUS_H + #include #include "log.h" #include "ubus_events.h" +#include "ubus_service.h" static struct ubus_context *ctx; @@ -20,15 +24,22 @@ int wifictld_ubus_init() return 1; } - // connect to ubus - ret = wifictld_ubus_bind_events(ctx); + // add to uloop + ubus_add_uloop(ctx); + + // add bbs + ret = wifictld_ubus_add_bss(ctx); if (ret) { - log_error("Failed to connect to ubus"); + log_error("Failed to add ubus service"); return 1; } - // add to uloop - ubus_add_uloop(ctx); + // bind events + ret = wifictld_ubus_bind_events(ctx); + if (ret) { + log_error("Failed to bind for ubus events"); + return 2; + } return 0; } @@ -38,3 +49,5 @@ void wifictld_ubus_close() { ubus_free(ctx); } + +#endif diff --git a/wireless/wifictld/src/ubus_events.c b/wireless/wifictld/src/ubus_events.c index 640858e..cb44862 100644 --- a/wireless/wifictld/src/ubus_events.c +++ b/wireless/wifictld/src/ubus_events.c @@ -10,7 +10,6 @@ int client_probe_learning = 0; static struct blob_buf b; -static struct ubus_context *ctx_main; // bind on every hostapd by receive all ubus registered services @@ -112,8 +111,12 @@ static int receive_notify(struct ubus_context *ctx, struct ubus_object *obj, str return WLAN_STATUS_SUCCESS; } + log_verbose("%s["MACSTR"] freq: %d signal %d", method, MAC2STR(addr), freq, ssi_signal); - if (!strcmp(method, "probe") && client_probe_learning) { + if (!strcmp(method, "deauth")) { + log_verbose(" disconnect"); + wifi_clients_disconnect(addr, freq, ssi_signal); + } else if (!strcmp(method, "probe") && client_probe_learning) { log_verbose(" learn"); wifi_clients_learn(addr, freq, ssi_signal); } diff --git a/wireless/wifictld/src/ubus_service.c b/wireless/wifictld/src/ubus_service.c new file mode 100644 index 0000000..39eb5d6 --- /dev/null +++ b/wireless/wifictld/src/ubus_service.c @@ -0,0 +1,147 @@ +#include +#include +#include "hostapd/common.h" +#include "log.h" +#include "wifi_clients.h" +#include "ubus_events.h" + +static struct blob_buf b; + +static int ubus_get_clients(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + void *list, *c; + char mac_buf[20]; + struct wifi_client *el; + + blob_buf_init(&b, 0); + list = blobmsg_open_table(&b, "clients"); + avl_for_each_element(&clients_by_addr, el, avl) { + + sprintf(mac_buf, MACSTR, MAC2STR(el->addr)); + c = blobmsg_open_table(&b, mac_buf); + blobmsg_add_u32(&b, "try", el->try); + blobmsg_add_u32(&b, "connected", el->connected); + blobmsg_add_u32(&b, "freq_highest", el->freq_highest); + blobmsg_add_u32(&b, "signal_lowfreq", el->signal_lowfreq); + blobmsg_add_u32(&b, "signal_highfreq", el->signal_highfreq); + blobmsg_close_table(&b, c); + } + + blobmsg_close_array(&b, list); + ubus_send_reply(ctx, req, b.head); + return 0; +} + +enum { + DEL_CLIENT_ADDR, + __DEL_CLIENT_MAX +}; + +static const struct blobmsg_policy ubus_del_client_policy[__DEL_CLIENT_MAX] = { + [DEL_CLIENT_ADDR] = { "addr", BLOBMSG_TYPE_STRING }, +}; + +static int ubus_del_client(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct blob_attr *tb[__DEL_CLIENT_MAX]; + u8 addr[ETH_ALEN]; + + blobmsg_parse(ubus_del_client_policy, __DEL_CLIENT_MAX, tb, blob_data(msg), blob_len(msg)); + + if (!tb[DEL_CLIENT_ADDR]) + return UBUS_STATUS_INVALID_ARGUMENT; + if (hwaddr_aton(blobmsg_data(tb[DEL_CLIENT_ADDR]), addr)) + return UBUS_STATUS_INVALID_ARGUMENT; + + wifi_clients_del(addr); + + return 0; +} + +static int ubus_get_client_threasholds(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + blob_buf_init(&b, 0); + blobmsg_add_u32(&b, "try", client_try_threashold); + blobmsg_add_u32(&b, "signal", client_signal_threashold); + ubus_send_reply(ctx, req, b.head); + return 0; +} + + +enum { + SET_CLIENT_TRY_THREASHOLD, + SET_CLIENT_SIGNAL_THREASHOLD, + __SET_CLIENT_THREASHOLD_VALUE_MAX +}; + +static const struct blobmsg_policy ubus_set_client_threashold_policy[__SET_CLIENT_THREASHOLD_VALUE_MAX] = { + [SET_CLIENT_TRY_THREASHOLD] = { "try", BLOBMSG_TYPE_INT32 }, + [SET_CLIENT_SIGNAL_THREASHOLD] = { "signal", BLOBMSG_TYPE_INT32 }, +}; + +static int ubus_set_client_threashold(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct blob_attr *tb[__SET_CLIENT_THREASHOLD_VALUE_MAX]; + + blobmsg_parse(ubus_set_client_threashold_policy, __SET_CLIENT_THREASHOLD_VALUE_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[SET_CLIENT_TRY_THREASHOLD] && !tb[SET_CLIENT_SIGNAL_THREASHOLD]) + return UBUS_STATUS_INVALID_ARGUMENT; + if (tb[SET_CLIENT_TRY_THREASHOLD]) + client_try_threashold = blobmsg_get_u32(tb[SET_CLIENT_TRY_THREASHOLD]); + if (tb[SET_CLIENT_SIGNAL_THREASHOLD]) + client_signal_threashold = blobmsg_get_u32(tb[SET_CLIENT_SIGNAL_THREASHOLD]); + return 0; +} + +static int ubus_is_client_probe_learning(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + blob_buf_init(&b, 0); + blobmsg_add_u32(&b, "current", client_probe_learning); + ubus_send_reply(ctx, req, b.head); + return 0; +} + +static int ubus_toggle_client_probe_learning(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + blob_buf_init(&b, 0); + blobmsg_add_u32(&b, "before", client_probe_learning); + client_probe_learning = !client_probe_learning; + blobmsg_add_u32(&b, "current", client_probe_learning); + ubus_send_reply(ctx, req, b.head); + return 0; +} + + +static const struct ubus_method wifictld_ubus_methods[] = { + // mgmt client db of bandsteering + UBUS_METHOD_NOARG("get_clients", ubus_get_clients), + UBUS_METHOD("del_client", ubus_del_client, ubus_del_client_policy), + + // client threasholds + UBUS_METHOD_NOARG("get_client_threasholds", ubus_get_client_threasholds), + UBUS_METHOD("set_client_threasholds", ubus_set_client_threashold, ubus_set_client_threashold_policy), + + // learn by probe (or only auth) + UBUS_METHOD_NOARG("is_client_probe_learning", ubus_is_client_probe_learning), + UBUS_METHOD_NOARG("toggle_client_probe_learning", ubus_toggle_client_probe_learning), +}; + +static struct ubus_object_type bss_object_type = + UBUS_OBJECT_TYPE("wifictld_bss", wifictld_ubus_methods); + +static struct ubus_object obj = { + .name = "wifictld", + .type = &bss_object_type, + .methods = wifictld_ubus_methods, + .n_methods = ARRAY_SIZE(wifictld_ubus_methods), + }; + +int wifictld_ubus_add_bss(struct ubus_context *ctx) { + return ubus_add_object(ctx, &obj); +} diff --git a/wireless/wifictld/src/ubus_service.h b/wireless/wifictld/src/ubus_service.h new file mode 100644 index 0000000..d6dee1e --- /dev/null +++ b/wireless/wifictld/src/ubus_service.h @@ -0,0 +1,8 @@ +#ifndef __WIFICTLD_UBUS_SERVICE_H +#define __WIFICTLD_UBUS_SERVICE_H + +#include + +int wifictld_ubus_add_bss(struct ubus_object *ctx); + +#endif diff --git a/wireless/wifictld/src/wifi_clients.c b/wireless/wifictld/src/wifi_clients.c index da1653d..e458fa1 100644 --- a/wireless/wifictld/src/wifi_clients.c +++ b/wireless/wifictld/src/wifi_clients.c @@ -6,27 +6,16 @@ #include "log.h" #include "wifi_clients.h" -int client_freq_try_threashold = 3; +int client_try_threashold = 4; +int client_signal_threashold = -75; -static void wifi_clients_del(const u8 *addr); - -static struct avl_tree clients_by_addr; +struct avl_tree clients_by_addr; static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr) { return memcmp(k1, k2, ETH_ALEN); } -struct wifi_client { - struct avl_node avl; - u8 addr[ETH_ALEN]; - int time; - int try; - uint32_t highfreq; - uint32_t lowsignal; - uint32_t highsignal; -}; - int wifi_clients_init() { avl_init(&clients_by_addr, avl_compare_macaddr, false, NULL); return 0; @@ -47,8 +36,11 @@ struct wifi_client *__get_client(const u8 *address){ log_debug("wifi_clients.__get_client("MACSTR"): gen new client\n", MAC2STR(address)); client = calloc(sizeof(*client), 1); memcpy(client->addr, address, sizeof(client->addr)); - client->highfreq = 0; client->try = 0; + client->connected = 0; + client->freq_highest = 0; + client->signal_lowfreq = 0; + client->signal_highfreq = 0; client->time = 0; client->avl.key = client->addr; log_debug("wifi_clients.__get_client("MACSTR"): add client to mem\n", MAC2STR(address)); @@ -58,14 +50,14 @@ struct wifi_client *__get_client(const u8 *address){ void __client_learn(struct wifi_client *client, uint32_t freq, uint32_t ssi_signal) { log_debug("wifi_clients.__client_learn(., %d):", freq); - if (client->highfreq < freq) { - client->highfreq = freq; - log_debug(" new highfreq"); + if (client->freq_highest < freq) { + client->freq_highest = freq; + log_debug(" new highest freq"); } - if (client->highfreq > WIFI_CLIENT_FREQ_THREASHOLD) { - client->highfreq = ssi_signal; + if (freq > WIFI_CLIENT_FREQ_THREASHOLD) { + client->signal_highfreq = ssi_signal; }else{ - client->lowsignal = ssi_signal; + client->signal_lowfreq = ssi_signal; } log_debug("\n"); //TODO time set and reset clean @@ -83,28 +75,39 @@ int wifi_clients_try(const u8 *address, uint32_t freq, uint32_t ssi_signal) { __client_learn(client, freq, ssi_signal); client->try++; - + log_info("auth(mac="MACSTR" freq=%d ssi=%d try=%d): ", MAC2STR(address), freq, ssi_signal, client->try); if (freq > WIFI_CLIENT_FREQ_THREASHOLD) { - client->try = 0; log_info("accept\n"); + client->try = 0; + client->connected = 1; return 0; } - if (client->highfreq > WIFI_CLIENT_FREQ_THREASHOLD) { + //TODO handle ssi_signal + if (client->freq_highest > WIFI_CLIENT_FREQ_THREASHOLD && + ssi_signal > client_signal_threashold + ) { log_info("reject - learned higher freq\n"); return -1; } - if(client->try > client_freq_try_threashold) { - client->try = 0; + if(client->try > client_try_threashold) { log_info("accept - threashold\n"); + client->try = 0; + client->connected = 1; return 0; } log_info("reject\n"); return client->try; } +void wifi_clients_disconnect(const u8 *address, uint32_t freq, uint32_t ssi_signal) { + struct wifi_client *client; + client = __get_client(address); + __client_learn(client, freq, ssi_signal); + client->connected = 0; +} -static void wifi_clients_del(const u8 *addr) { +void wifi_clients_del(const u8 *addr) { struct wifi_client *client; client = avl_find_element(&clients_by_addr, addr, client, avl); diff --git a/wireless/wifictld/src/wifi_clients.h b/wireless/wifictld/src/wifi_clients.h index e153e2e..953ef27 100644 --- a/wireless/wifictld/src/wifi_clients.h +++ b/wireless/wifictld/src/wifi_clients.h @@ -2,8 +2,24 @@ #define __WIFICTLD_WIFI_CLIENTS_H #include +#include +#include "hostapd/ieee802_11_defs.h" -extern int client_freq_try_threashold; +extern int client_try_threashold; +extern int client_signal_threashold; +extern struct avl_tree clients_by_addr; + + +struct wifi_client { + struct avl_node avl; + u8 addr[ETH_ALEN]; + int time; + int try; + bool connected; + uint32_t freq_highest; + uint32_t signal_lowfreq; + uint32_t signal_highfreq; +}; #define WIFI_CLIENT_FREQ_THREASHOLD 5000 @@ -12,5 +28,8 @@ void wifi_clients_close(); void wifi_clients_learn(const uint8_t *address, uint32_t freq, uint32_t ssi_signal); int wifi_clients_try(const uint8_t *address, uint32_t freq, uint32_t ssi_signal); +void wifi_clients_disconnect(const uint8_t *address, uint32_t freq, uint32_t ssi_signal); + +void wifi_clients_del(const u8 *addr); #endif