add ubus 'service' to request current state + handling accept by ssi_signal
This commit is contained in:
parent
c6ee586501
commit
ed8e91f54b
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
@ -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);
|
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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue