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 "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

View File

@ -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);
}

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 "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
@ -86,25 +78,36 @@ int wifi_clients_try(const u8 *address, uint32_t freq, uint32_t ssi_signal) {
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);

View File

@ -2,8 +2,24 @@
#define __WIFICTLD_WIFI_CLIENTS_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
@ -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