restructur headers + force steering (global or probe)

This commit is contained in:
Martin/Geno 2018-07-20 10:03:46 +02:00
parent 901fc3f838
commit 4c3f956f71
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
15 changed files with 201 additions and 126 deletions

View File

@ -0,0 +1,15 @@
#include "config.h"
int verbose = 0;
int client_try_threashold = 3;
int client_signal_threashold = -75;
int clean_every = 600; //in ms = 10min
int clean_older_then = 3600; //in sec = 1h
bool client_force = false;
bool client_force_probe = false;
bool client_probe_steering = true;
// steering contains learning already
bool client_probe_learning = false;

View File

@ -0,0 +1,29 @@
#ifndef __WIFICTLD_CONFIG_H
#define __WIFICTLD_CONFIG_H
#include "include.h"
#define WIFI_CLIENT_FREQ_THREASHOLD 5000
extern int verbose;
extern int client_try_threashold;
extern int client_signal_threashold;
extern int clean_every;
extern int clean_older_then;
// force (disable 2.4 Ghz)
extern bool client_force;
// force (disable 2.4 Ghz) for wifi probes
extern bool client_force_probe;
// use client_try_threashold for probes, too
extern bool client_probe_steering;
/*
steering contains learning already:
when client_probe_steering is set,
client_probe_learning is ignored
*/
extern bool client_probe_learning;
#endif

View File

@ -0,0 +1,3 @@
#include "data.h"
struct avl_tree clients_by_addr = {};

View File

@ -0,0 +1,23 @@
#ifndef __WIFICTLD_DATA_H
#define __WIFICTLD_DATA_H
#include "include.h"
extern struct avl_tree clients_by_addr;
struct wifi_client {
struct avl_node avl;
u8 addr[ETH_ALEN];
time_t time;
int try_probe;
int try_auth;
bool connected;
bool authed;
uint32_t freq_highest;
uint32_t signal_lowfreq;
uint32_t signal_highfreq;
};
#endif

View File

@ -0,0 +1,18 @@
#ifndef __WIFICTLD_INCLUDE_H
#define __WIFICTLD_INCLUDE_H
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <libubus.h>
#include <libubox/avl.h>
#include <libubox/uloop.h>
#include <libubox/blobmsg.h>
#include <getopt.h>
#include "hostapd/ieee802_11_defs.h" // ETH_ALEN + hwaddr_aton
#include "hostapd/common.h"
#endif

View File

@ -1,8 +1,5 @@
#include <stdio.h> #include "config.h"
#include <stdarg.h>
#include "log.h"
int verbose = 0;
#ifdef DEBUG #ifdef DEBUG
void log_debug(const char *format, ...) { void log_debug(const char *format, ...) {

View File

@ -1,8 +1,6 @@
#ifndef __WIFICTLD_LOG_H #ifndef __WIFICTLD_LOG_H
#define __WIFICTLD_LOG_H #define __WIFICTLD_LOG_H
extern int verbose;
void log_info(const char *format, ...); void log_info(const char *format, ...);
void log_verbose(const char *format, ...); void log_verbose(const char *format, ...);
void log_debug(const char *format, ...); void log_debug(const char *format, ...);

View File

@ -1,8 +1,7 @@
#include <getopt.h> #include "include.h"
#include <libubox/uloop.h> #include "config.h"
#include "log.h" #include "log.h"
#include "wifi_clients.h" #include "wifi_clients.h"
#include "ubus_events.h"
#include "ubus.h" #include "ubus.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])

View File

@ -1,7 +1,7 @@
#ifndef __WIFICTLD_UBUS_H #ifndef __WIFICTLD_UBUS_H
#define __WIFICTLD_UBUS_H #define __WIFICTLD_UBUS_H
#include <libubus.h> #include "include.h"
#include "log.h" #include "log.h"
#include "ubus_events.h" #include "ubus_events.h"
#include "ubus_service.h" #include "ubus_service.h"

View File

@ -1,17 +1,8 @@
#include <stdlib.h> #include "include.h"
#include <string.h> #include "config.h"
#include <libubox/blobmsg.h>
#include <libubus.h>
#include "hostapd/ieee802_11_defs.h" // ETH_ALEN + hwaddr_aton
#include "hostapd/common.h"
#include "log.h" #include "log.h"
#include "wifi_clients.h" #include "wifi_clients.h"
bool client_probe_steering = true;
// steering contains learning already
bool client_probe_learning = false;
// bind on every hostapd by receive all ubus registered services // bind on every hostapd by receive all ubus registered services
static void recieve_interfaces(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv); static void recieve_interfaces(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv);

View File

@ -1,15 +1,7 @@
#ifndef __WIFICTLD_UBUS_EVENT_H #ifndef __WIFICTLD_UBUS_EVENT_H
#define __WIFICTLD_UBUS_EVENT_H #define __WIFICTLD_UBUS_EVENT_H
#include <libubus.h> #include "include.h"
extern bool client_probe_steering;
/*
steering contains learning already:
when client_probe_steering is set,
client_probe_learning is ignored
*/
extern bool client_probe_learning;
int wifictld_ubus_bind_events(struct ubus_context *ctx); int wifictld_ubus_bind_events(struct ubus_context *ctx);

View File

@ -1,9 +1,8 @@
#include <libubus.h> #include "include.h"
#include <libubox/avl.h> #include "config.h"
#include "hostapd/common.h"
#include "log.h" #include "log.h"
#include "data.h"
#include "wifi_clients.h" #include "wifi_clients.h"
#include "ubus_events.h"
static struct blob_buf b = {}; static struct blob_buf b = {};
@ -15,11 +14,14 @@ static int ubus_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
struct wifi_client *el; struct wifi_client *el;
blob_buf_init(&b, 0); blob_buf_init(&b, 0);
list = blobmsg_open_table(&b, "clients"); list = blobmsg_open_table(&b, "clients");
avl_for_each_element(&clients_by_addr, el, avl) { avl_for_each_element(&clients_by_addr, el, avl) {
sprintf(mac_buf, MACSTR, MAC2STR(el->addr)); sprintf(mac_buf, MACSTR, MAC2STR(el->addr));
c = blobmsg_open_table(&b, mac_buf); c = blobmsg_open_table(&b, mac_buf);
blobmsg_add_u32(&b, "try_probe", el->try_probe); blobmsg_add_u32(&b, "try_probe", el->try_probe);
blobmsg_add_u32(&b, "try_auth", el->try_auth); blobmsg_add_u32(&b, "try_auth", el->try_auth);
blobmsg_add_u32(&b, "time", el->time); blobmsg_add_u32(&b, "time", el->time);
@ -28,11 +30,14 @@ static int ubus_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
blobmsg_add_u32(&b, "freq_highest", el->freq_highest); blobmsg_add_u32(&b, "freq_highest", el->freq_highest);
blobmsg_add_u32(&b, "signal_lowfreq", el->signal_lowfreq); blobmsg_add_u32(&b, "signal_lowfreq", el->signal_lowfreq);
blobmsg_add_u32(&b, "signal_highfreq", el->signal_highfreq); blobmsg_add_u32(&b, "signal_highfreq", el->signal_highfreq);
blobmsg_close_table(&b, c); blobmsg_close_table(&b, c);
} }
blobmsg_close_array(&b, list); blobmsg_close_array(&b, list);
ubus_send_reply(ctx, req, b.head); ubus_send_reply(ctx, req, b.head);
return 0; return 0;
} }
@ -55,6 +60,7 @@ static int ubus_del_client(struct ubus_context *ctx, struct ubus_object *obj,
if (!tb[DEL_CLIENT_ADDR]) if (!tb[DEL_CLIENT_ADDR])
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
if (hwaddr_aton(blobmsg_data(tb[DEL_CLIENT_ADDR]), addr)) if (hwaddr_aton(blobmsg_data(tb[DEL_CLIENT_ADDR]), addr))
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
@ -67,9 +73,12 @@ static int ubus_get_client_threasholds(struct ubus_context *ctx, struct ubus_obj
struct ubus_request_data *req, const char *method, struct blob_attr *msg) struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{ {
blob_buf_init(&b, 0); blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "try", client_try_threashold); blobmsg_add_u32(&b, "try", client_try_threashold);
blobmsg_add_u32(&b, "signal", client_signal_threashold); blobmsg_add_u32(&b, "signal", client_signal_threashold);
ubus_send_reply(ctx, req, b.head); ubus_send_reply(ctx, req, b.head);
return 0; return 0;
} }
@ -91,12 +100,16 @@ static int ubus_set_client_threashold(struct ubus_context *ctx, struct ubus_obje
struct blob_attr *tb[__SET_CLIENT_THREASHOLD_VALUE_MAX]; 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)); 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])
if (!tb[SET_CLIENT_TRY_THREASHOLD] &&
!tb[SET_CLIENT_SIGNAL_THREASHOLD])
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[SET_CLIENT_TRY_THREASHOLD]) if (tb[SET_CLIENT_TRY_THREASHOLD])
client_try_threashold = blobmsg_get_u32(tb[SET_CLIENT_TRY_THREASHOLD]); client_try_threashold = blobmsg_get_u32(tb[SET_CLIENT_TRY_THREASHOLD]);
if (tb[SET_CLIENT_SIGNAL_THREASHOLD]) if (tb[SET_CLIENT_SIGNAL_THREASHOLD])
client_signal_threashold = blobmsg_get_u32(tb[SET_CLIENT_SIGNAL_THREASHOLD]); client_signal_threashold = blobmsg_get_u32(tb[SET_CLIENT_SIGNAL_THREASHOLD]);
return 0; return 0;
} }
@ -104,9 +117,12 @@ static int ubus_get_clean_values(struct ubus_context *ctx, struct ubus_object *o
struct ubus_request_data *req, const char *method, struct blob_attr *msg) struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{ {
blob_buf_init(&b, 0); blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "every", clean_every); blobmsg_add_u32(&b, "every", clean_every);
blobmsg_add_u32(&b, "older_then", clean_older_then); blobmsg_add_u32(&b, "older_then", clean_older_then);
ubus_send_reply(ctx, req, b.head); ubus_send_reply(ctx, req, b.head);
return 0; return 0;
} }
@ -128,54 +144,75 @@ static int ubus_set_clean_values(struct ubus_context *ctx, struct ubus_object *o
struct blob_attr *tb[__SET_CLEAN_VALUES_MAX]; struct blob_attr *tb[__SET_CLEAN_VALUES_MAX];
blobmsg_parse(ubus_set_clean_values_policy, __SET_CLEAN_VALUES_MAX, tb, blob_data(msg), blob_len(msg)); blobmsg_parse(ubus_set_clean_values_policy, __SET_CLEAN_VALUES_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[SET_CLEAN_EVERY] && !tb[SET_CLEAN_OLDER_THEN])
if (!tb[SET_CLEAN_EVERY] &&
!tb[SET_CLEAN_OLDER_THEN])
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[SET_CLEAN_EVERY]) if (tb[SET_CLEAN_EVERY])
clean_every = blobmsg_get_u32(tb[SET_CLEAN_EVERY]); clean_every = blobmsg_get_u32(tb[SET_CLEAN_EVERY]);
if (tb[SET_CLEAN_OLDER_THEN]) if (tb[SET_CLEAN_OLDER_THEN])
clean_older_then = blobmsg_get_u32(tb[SET_CLEAN_OLDER_THEN]); clean_older_then = blobmsg_get_u32(tb[SET_CLEAN_OLDER_THEN]);
return 0; return 0;
} }
static int ubus_is_client_probe_steering(struct ubus_context *ctx, struct ubus_object *obj,
static int ubus_get_config(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg) struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{ {
blob_buf_init(&b, 0); blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "current", client_probe_steering);
blobmsg_add_u32(&b, "every", clean_every);
blobmsg_add_u32(&b, "older_then", clean_older_then);
ubus_send_reply(ctx, req, b.head); ubus_send_reply(ctx, req, b.head);
return 0; return 0;
} }
static int ubus_toggle_client_probe_steering(struct ubus_context *ctx, struct ubus_object *obj,
enum {
SET_CONFIG_FORCE,
SET_CONFIG_FORCE_PROBE,
SET_CONFIG_PROBE_STEERING,
SET_CONFIG_PROBE_LEARNING,
__SET_CONFIG_MAX
};
static const struct blobmsg_policy ubus_set_config_policy[__SET_CONFIG_MAX] = {
[SET_CONFIG_FORCE] = { "force", BLOBMSG_TYPE_BOOL },
[SET_CONFIG_FORCE_PROBE] = { "force_probe", BLOBMSG_TYPE_BOOL },
[SET_CONFIG_PROBE_STEERING] = { "probe_steering", BLOBMSG_TYPE_BOOL },
[SET_CONFIG_PROBE_LEARNING] = { "probe_learning", BLOBMSG_TYPE_BOOL },
};
static int ubus_set_config(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg) struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{ {
blob_buf_init(&b, 0); struct blob_attr *tb[__SET_CONFIG_MAX];
blobmsg_add_u32(&b, "before", client_probe_steering);
client_probe_steering = !client_probe_steering; blobmsg_parse(ubus_set_config_policy, __SET_CONFIG_MAX, tb, blob_data(msg), blob_len(msg));
blobmsg_add_u32(&b, "current", client_probe_steering);
ubus_send_reply(ctx, req, b.head); if (!tb[SET_CONFIG_FORCE] &&
!tb[SET_CONFIG_FORCE_PROBE] &&
!tb[SET_CONFIG_PROBE_STEERING] &&
!tb[SET_CONFIG_PROBE_LEARNING])
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[SET_CONFIG_FORCE])
client_force = blobmsg_get_bool(tb[SET_CONFIG_FORCE]);
if (tb[SET_CONFIG_FORCE_PROBE])
client_force_probe = blobmsg_get_bool(tb[SET_CONFIG_FORCE_PROBE]);
if (tb[SET_CONFIG_PROBE_STEERING])
client_probe_steering = blobmsg_get_bool(tb[SET_CONFIG_PROBE_STEERING]);
if (tb[SET_CONFIG_PROBE_LEARNING])
client_probe_learning = blobmsg_get_bool(tb[SET_CONFIG_PROBE_LEARNING]);
return 0; 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[] = { static const struct ubus_method wifictld_ubus_methods[] = {
@ -191,13 +228,9 @@ static const struct ubus_method wifictld_ubus_methods[] = {
UBUS_METHOD_NOARG("get_clean_values", ubus_get_clean_values), UBUS_METHOD_NOARG("get_clean_values", ubus_get_clean_values),
UBUS_METHOD("set_clean_values", ubus_set_clean_values, ubus_set_clean_values_policy), UBUS_METHOD("set_clean_values", ubus_set_clean_values, ubus_set_clean_values_policy),
// steering by probe (or only auth) // config threasholds
UBUS_METHOD_NOARG("is_client_probe_steering", ubus_is_client_probe_steering), UBUS_METHOD_NOARG("get_config", ubus_get_config),
UBUS_METHOD_NOARG("toggle_client_probe_steering", ubus_toggle_client_probe_steering), UBUS_METHOD("set_config", ubus_set_config, ubus_set_config_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 = static struct ubus_object_type bss_object_type =

View File

@ -1,7 +1,7 @@
#ifndef __WIFICTLD_UBUS_SERVICE_H #ifndef __WIFICTLD_UBUS_SERVICE_H
#define __WIFICTLD_UBUS_SERVICE_H #define __WIFICTLD_UBUS_SERVICE_H
#include <libubus.h> #include "include.h"
int wifictld_ubus_add_bss(struct ubus_context *ctx); int wifictld_ubus_add_bss(struct ubus_context *ctx);

View File

@ -1,25 +1,14 @@
#include <stdint.h> #include "include.h"
#include <string.h> #include "config.h"
#include <stdlib.h>
#include <time.h>
#include <libubox/avl.h>
#include <libubox/uloop.h>
#include "hostapd/ieee802_11_defs.h" // ETH_ALEN
#include "log.h" #include "log.h"
#include "data.h"
#include "wifi_clients.h" #include "wifi_clients.h"
int client_try_threashold = 3;
int client_signal_threashold = -75;
int clean_every = 600; //in ms = 10min
int clean_older_then = 3600; //in sec = 1h
struct avl_tree clients_by_addr = {};
void clean_cbhandler(struct uloop_timeout *t) void clean_cbhandler(struct uloop_timeout *t)
{ {
int i = 0; int count = 0,
all = 0;
time_t now; time_t now;
time(&now); time(&now);
now -= clean_older_then; now -= clean_older_then;
@ -29,15 +18,16 @@ void clean_cbhandler(struct uloop_timeout *t)
avl_delete(&clients_by_addr, &client->avl); avl_delete(&clients_by_addr, &client->avl);
log_verbose("clean_client(): "MACSTR" remove from memory\n", MAC2STR(client->addr)); log_verbose("clean_client(): "MACSTR" remove from memory\n", MAC2STR(client->addr));
free(client); free(client);
i++; count++;
} }
all++;
} }
uloop_timeout_set(t, clean_every * 1000); uloop_timeout_set(t, clean_every * 1000);
if (i > 0) { if (count > 0) {
log_info("remove %d clients from memory\n", i); log_info("remove %d/%d clients from memory\n", count, all);
}else{ }else{
log_verbose("remove %d clients from memory\n", i); log_verbose("remove %d/%d clients from memory\n", count, all);
} }
} }
@ -117,10 +107,14 @@ int wifi_clients_try(bool auth, const u8 *address, uint32_t freq, uint32_t ssi_s
log_info("auth(try=%d mac="MACSTR" freq=%d ssi=%d): ", client->try_auth, MAC2STR(address), freq, ssi_signal); log_info("auth(try=%d mac="MACSTR" freq=%d ssi=%d): ", client->try_auth, MAC2STR(address), freq, ssi_signal);
client->try_auth++; client->try_auth++;
client->try_probe = 0; client->try_probe = 0;
}else{
if(client_force_probe){
log_verbose("probe(try=%d mac="MACSTR" freq=%d ssi=%d): ", client->try_auth, MAC2STR(address), freq, ssi_signal);
}else{ }else{
log_verbose("probe(try=%d mac="MACSTR" freq=%d ssi=%d): ", client->try_probe, MAC2STR(address), freq, ssi_signal); log_verbose("probe(try=%d mac="MACSTR" freq=%d ssi=%d): ", client->try_probe, MAC2STR(address), freq, ssi_signal);
client->try_probe++; client->try_probe++;
} }
}
if (freq > WIFI_CLIENT_FREQ_THREASHOLD) { if (freq > WIFI_CLIENT_FREQ_THREASHOLD) {
if(!auth){ if(!auth){
client->try_probe = 0; client->try_probe = 0;
@ -133,10 +127,17 @@ int wifi_clients_try(bool auth, const u8 *address, uint32_t freq, uint32_t ssi_s
client->connected = 1; client->connected = 1;
return 0; return 0;
} }
if (client->freq_highest > WIFI_CLIENT_FREQ_THREASHOLD) {
if (client_force || client_force_probe && !auth) {
if(!auth){
log_verbose("reject - force\n");
return -1;
}
log_info("reject - force\n");
return -1;
}
if (client->freq_highest > WIFI_CLIENT_FREQ_THREASHOLD && if (ssi_signal > client_signal_threashold) {
ssi_signal > client_signal_threashold
) {
if(!auth){ if(!auth){
log_verbose("reject - learned higher freq + ssi is high enough\n"); log_verbose("reject - learned higher freq + ssi is high enough\n");
return -1; return -1;
@ -144,6 +145,7 @@ int wifi_clients_try(bool auth, const u8 *address, uint32_t freq, uint32_t ssi_s
log_info("reject - learned higher freq + ssi is high enough\n"); log_info("reject - learned higher freq + ssi is high enough\n");
return -1; return -1;
} }
}
if(auth && client->try_auth > client_try_threashold || if(auth && client->try_auth > client_try_threashold ||
!auth && client->try_probe > client_try_threashold !auth && client->try_probe > client_try_threashold

View File

@ -1,32 +1,7 @@
#ifndef __WIFICTLD_WIFI_CLIENTS_H #ifndef __WIFICTLD_WIFI_CLIENTS_H
#define __WIFICTLD_WIFI_CLIENTS_H #define __WIFICTLD_WIFI_CLIENTS_H
#include <stdint.h> #include "include.h"
#include <time.h>
#include <libubox/avl.h>
#include "hostapd/ieee802_11_defs.h"
extern int client_try_threashold;
extern int client_signal_threashold;
extern int clean_every;
extern int clean_older_then;
extern struct avl_tree clients_by_addr;
struct wifi_client {
struct avl_node avl;
u8 addr[ETH_ALEN];
time_t time;
int try_probe;
int try_auth;
bool connected;
bool authed;
uint32_t freq_highest;
uint32_t signal_lowfreq;
uint32_t signal_highfreq;
};
#define WIFI_CLIENT_FREQ_THREASHOLD 5000
int wifi_clients_init(); int wifi_clients_init();
void wifi_clients_close(); void wifi_clients_close();