add ubus 'service' to request current state + handling accept by ssi_signal

This commit is contained in:
Martin/Geno 2018-07-17 19:32:58 +02:00
parent c6ee586501
commit ed8e91f54b
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
7 changed files with 228 additions and 35 deletions

View File

@ -1,6 +1,10 @@
#ifndef __WIFICTLD_UBUS_H
#define __WIFICTLD_UBUS_H
#include <libubus.h> #include <libubus.h>
#include "log.h" #include "log.h"
#include "ubus_events.h" #include "ubus_events.h"
#include "ubus_service.h"
static struct ubus_context *ctx; static struct ubus_context *ctx;
@ -20,15 +24,22 @@ int wifictld_ubus_init()
return 1; return 1;
} }
// connect to ubus // add to uloop
ret = wifictld_ubus_bind_events(ctx); ubus_add_uloop(ctx);
// add bbs
ret = wifictld_ubus_add_bss(ctx);
if (ret) { if (ret) {
log_error("Failed to connect to ubus"); log_error("Failed to add ubus service");
return 1; return 1;
} }
// add to uloop // bind events
ubus_add_uloop(ctx); ret = wifictld_ubus_bind_events(ctx);
if (ret) {
log_error("Failed to bind for ubus events");
return 2;
}
return 0; return 0;
} }
@ -38,3 +49,5 @@ void wifictld_ubus_close()
{ {
ubus_free(ctx); ubus_free(ctx);
} }
#endif

View File

@ -10,7 +10,6 @@
int client_probe_learning = 0; int client_probe_learning = 0;
static struct blob_buf b; static struct blob_buf b;
static struct ubus_context *ctx_main;
// bind on every hostapd by receive all ubus registered services // 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; return WLAN_STATUS_SUCCESS;
} }
log_verbose("%s["MACSTR"] freq: %d signal %d", method, MAC2STR(addr), freq, ssi_signal); 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"); log_verbose(" learn");
wifi_clients_learn(addr, freq, ssi_signal); wifi_clients_learn(addr, freq, ssi_signal);
} }

View File

@ -0,0 +1,147 @@
#include <libubus.h>
#include <libubox/avl.h>
#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);
}

View File

@ -0,0 +1,8 @@
#ifndef __WIFICTLD_UBUS_SERVICE_H
#define __WIFICTLD_UBUS_SERVICE_H
#include <libubus.h>
int wifictld_ubus_add_bss(struct ubus_object *ctx);
#endif

View File

@ -6,27 +6,16 @@
#include "log.h" #include "log.h"
#include "wifi_clients.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); struct avl_tree clients_by_addr;
static struct avl_tree clients_by_addr;
static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr) static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr)
{ {
return memcmp(k1, k2, ETH_ALEN); 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() { int wifi_clients_init() {
avl_init(&clients_by_addr, avl_compare_macaddr, false, NULL); avl_init(&clients_by_addr, avl_compare_macaddr, false, NULL);
return 0; 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)); log_debug("wifi_clients.__get_client("MACSTR"): gen new client\n", MAC2STR(address));
client = calloc(sizeof(*client), 1); client = calloc(sizeof(*client), 1);
memcpy(client->addr, address, sizeof(client->addr)); memcpy(client->addr, address, sizeof(client->addr));
client->highfreq = 0;
client->try = 0; client->try = 0;
client->connected = 0;
client->freq_highest = 0;
client->signal_lowfreq = 0;
client->signal_highfreq = 0;
client->time = 0; client->time = 0;
client->avl.key = client->addr; client->avl.key = client->addr;
log_debug("wifi_clients.__get_client("MACSTR"): add client to mem\n", MAC2STR(address)); 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) { void __client_learn(struct wifi_client *client, uint32_t freq, uint32_t ssi_signal) {
log_debug("wifi_clients.__client_learn(., %d):", freq); log_debug("wifi_clients.__client_learn(., %d):", freq);
if (client->highfreq < freq) { if (client->freq_highest < freq) {
client->highfreq = freq; client->freq_highest = freq;
log_debug(" new highfreq"); log_debug(" new highest freq");
} }
if (client->highfreq > WIFI_CLIENT_FREQ_THREASHOLD) { if (freq > WIFI_CLIENT_FREQ_THREASHOLD) {
client->highfreq = ssi_signal; client->signal_highfreq = ssi_signal;
}else{ }else{
client->lowsignal = ssi_signal; client->signal_lowfreq = ssi_signal;
} }
log_debug("\n"); log_debug("\n");
//TODO time set and reset clean //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_learn(client, freq, ssi_signal);
client->try++; client->try++;
log_info("auth(mac="MACSTR" freq=%d ssi=%d try=%d): ", MAC2STR(address), 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) { if (freq > WIFI_CLIENT_FREQ_THREASHOLD) {
client->try = 0;
log_info("accept\n"); log_info("accept\n");
client->try = 0;
client->connected = 1;
return 0; 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"); log_info("reject - learned higher freq\n");
return -1; return -1;
} }
if(client->try > client_freq_try_threashold) { if(client->try > client_try_threashold) {
client->try = 0;
log_info("accept - threashold\n"); log_info("accept - threashold\n");
client->try = 0;
client->connected = 1;
return 0; return 0;
} }
log_info("reject\n"); log_info("reject\n");
return client->try; 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; struct wifi_client *client;
client = avl_find_element(&clients_by_addr, addr, client, avl); client = avl_find_element(&clients_by_addr, addr, client, avl);

View File

@ -2,8 +2,24 @@
#define __WIFICTLD_WIFI_CLIENTS_H #define __WIFICTLD_WIFI_CLIENTS_H
#include <stdint.h> #include <stdint.h>
#include <libubox/avl.h>
#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 #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); 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); 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 #endif