From 9641780f802335877149910c573188dc80677062 Mon Sep 17 00:00:00 2001 From: Eneas U de Queiroz Date: Tue, 27 Jul 2021 16:52:19 -0300 Subject: [PATCH] Change mode config parameter from int to string This renames "mode" to "rrm_mode", and its type from int to string. This way, we can set the correct mode for a probe request from the STA reported capabilities, along with the preferred order of modes, set by the "rrm_mode" uci config. rrm_mode is a string of possible mode letters: 'p' = passive report 'a' = active report 'b' or 't' = beacon table report. Setting rrm_mode='pat', will try to send passive reports, if available; if not, it will try an active report, using a beacon table if all else fails. If you don't include a letter, the corresponding report type will be disabled. An empty string will disable beacon reports. Unrecognized letters are ignored, as well as repeated modes. If the configuration is not present, a default value of 'pat' will be used. Signed-off-by: Eneas U de Queiroz --- src/include/datastorage.h | 27 ++++++++++++++++++++- src/include/ubus.h | 2 +- src/storage/datastorage.c | 14 ++--------- src/test/test_storage.c | 51 ++++++++++++++++++++++++++++++++++++--- src/utils/dawn_uci.c | 44 +++++++++++++++++++++++++++++++-- src/utils/msghandler.c | 8 +++--- src/utils/ubus.c | 46 +++++++++++++++++++++++++++++++---- 7 files changed, 163 insertions(+), 29 deletions(-) diff --git a/src/include/datastorage.h b/src/include/datastorage.h index 052e2a2..bd66b3e 100644 --- a/src/include/datastorage.h +++ b/src/include/datastorage.h @@ -19,6 +19,15 @@ // ---------------- Defines ------------------- #define MAC_LIST_LENGTH 100 +#define DEFAULT_RRM_MODE_ORDER "pat" +#define RRM_MODE_COUNT 3 + +enum rrm_beacon_rqst_mode { + RRM_BEACON_RQST_MODE_PASSIVE, + RRM_BEACON_RQST_MODE_ACTIVE, + RRM_BEACON_RQST_MODE_BEACON_TABLE, + __RRM_BEACON_RQST_MODE_MAX +}; // ---------------- Global variables ---------------- extern struct mac_entry_s *mac_set; @@ -75,7 +84,8 @@ struct probe_metric_s { int kicking; int op_class; int duration; - int mode; + int rrm_mode_mask; + int rrm_mode_order[__RRM_BEACON_RQST_MODE_MAX]; int scan_channel; }; @@ -174,6 +184,21 @@ typedef struct auth_entry_s assoc_entry; // ---------------- Defines ---------------- #define NEIGHBOR_REPORT_LEN 200 +/* Neighbor report string elements + * [Elemen ID|1][LENGTH|1][BSSID|6][BSSID INFORMATION|4][Operating Class|1][Channel Number|1][PHY Type|1][Operational Subelements] + * first two bytes are not stored + */ +#define NR_BSSID 0 +#define NR_BSSID_INFO 12 +#define NR_OP_CLASS 20 +#define NR_CHANNEL 22 +#define NR_PHY 24 +#ifndef BIT +#define BIT(x) (1U << (x)) +#endif +#define WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE BIT(4) +#define WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE BIT(5) +#define WLAN_RRM_CAPS_BEACON_REPORT_TABLE BIT(6) // ---------------- Global variables ---------------- extern struct auth_entry_s *denied_req_set; diff --git a/src/include/ubus.h b/src/include/ubus.h index 57578c5..8786a81 100644 --- a/src/include/ubus.h +++ b/src/include/ubus.h @@ -68,7 +68,7 @@ void del_client_all_interfaces(const struct dawn_mac client_addr, uint32_t reaso */ void update_hostapd_sockets(struct uloop_timeout *t); -void ubus_send_beacon_report(struct dawn_mac client, int id); +void ubus_send_beacon_report(client *c, int id); void uloop_add_data_cbs(); diff --git a/src/storage/datastorage.c b/src/storage/datastorage.c index db7385d..677da3a 100644 --- a/src/storage/datastorage.c +++ b/src/storage/datastorage.c @@ -18,13 +18,6 @@ struct time_config_s timeout_config; #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#ifndef BIT -#define BIT(x) (1U << (x)) -#endif -#define WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE BIT(4) -#define WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE BIT(5) -#define WLAN_RRM_CAPS_BEACON_REPORT_TABLE BIT(6) - static int probe_compare(probe_entry *probe1, probe_entry *probe2); static int kick_client(ap *kicking_ap, struct client_s *client_entry, char* neighbor_report); @@ -402,11 +395,8 @@ void send_beacon_reports(struct dawn_mac bssid, int id) { !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE), !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_TABLE)); #endif - if (i->rrm_enabled_capa & - (WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | - WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | - WLAN_RRM_CAPS_BEACON_REPORT_TABLE)) - ubus_send_beacon_report(i->client_addr, id); + if (i->rrm_enabled_capa & dawn_metric.rrm_mode_mask) + ubus_send_beacon_report(i, id); i = i->next_entry_bc; } diff --git a/src/test/test_storage.c b/src/test/test_storage.c index cd02bda..e02513d 100644 --- a/src/test/test_storage.c +++ b/src/test/test_storage.c @@ -11,7 +11,7 @@ #include "test_storage.h" /*** Test Stub Functions - Called by SUT ***/ -void ubus_send_beacon_report(struct dawn_mac client, int id) +void ubus_send_beacon_report(client *c, int id) { printf("send_beacon_report() was called...\n"); } @@ -148,7 +148,7 @@ static int array_auto_helper(int action, int i0, int i1) while (cont) { struct dawn_mac this_mac; - uint64_t mac_src = m; + uint64_t mac_src = m; memcpy(&this_mac.u8, &mac_src, ETH_ALEN < sizeof (uint64_t) ? ETH_ALEN : sizeof (uint64_t)); switch (action & ~HELPER_ACTION_MASK) { @@ -320,6 +320,44 @@ static int load_time(time_t* v, char* s) return ret; } +static int get_rrm_mode_val(char mode); +static int get_rrm_mode_val(char mode) { + switch (tolower(mode)) { + case 'a': + return WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE; + break; + case 'p': + return WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE; + break; + case 'b': + case 't': + return WLAN_RRM_CAPS_BEACON_REPORT_TABLE; + break; + } + return 0; +} + +static int parse_rrm_mode(int *rrm_mode_order, const char *mode_string); +static int parse_rrm_mode(int *rrm_mode_order, const char *mode_string) { + int len, mode_val; + int mask = 0, order = 0, pos = 0; + + if (!mode_string) + mode_string = DEFAULT_RRM_MODE_ORDER; + len = strlen(mode_string); + + while (order < __RRM_BEACON_RQST_MODE_MAX) { + if (pos >= len) { + rrm_mode_order[order++] = 0; + } else { + mode_val = get_rrm_mode_val(mode_string[pos++]); + if (mode_val && !(mask & mode_val)) + mask |= (rrm_mode_order[order++] = mode_val); + } + } + return mask; +} + static int consume_actions(int argc, char* argv[], int harness_verbosity); static int consume_actions(int argc, char* argv[], int harness_verbosity) @@ -618,7 +656,12 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) dawn_metric.kicking = 0; dawn_metric.op_class = 0; dawn_metric.duration = 0; - dawn_metric.mode = 0; + dawn_metric.rrm_mode_mask = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | + WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | + WLAN_RRM_CAPS_BEACON_REPORT_TABLE; + dawn_metric.rrm_mode_order[0] = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE; + dawn_metric.rrm_mode_order[1] = WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE; + dawn_metric.rrm_mode_order[2] = WLAN_RRM_CAPS_BEACON_REPORT_TABLE; dawn_metric.scan_channel = 0; } else if (!strncmp(fn, "ap_weight=", 10)) load_int(&dawn_metric.ap_weight, fn + 10); @@ -651,7 +694,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) else if (!strncmp(fn, "kicking=", 8)) load_int(&dawn_metric.kicking, fn + 8); else if (!strncmp(fn, "op_class=", 9)) load_int(&dawn_metric.op_class, fn + 9); else if (!strncmp(fn, "duration=", 9)) load_int(&dawn_metric.duration, fn + 9); - else if (!strncmp(fn, "mode=", 5)) load_int(&dawn_metric.mode, fn + 5); + else if (!strncmp(fn, "rrm_mode=", 9)) dawn_metric.rrm_mode_mask = parse_rrm_mode(dawn_metric.rrm_mode_order, fn + 9); else if (!strncmp(fn, "scan_channel=", 13)) load_int(&dawn_metric.scan_channel, fn + 13); else { printf("ERROR: Loading DAWN control metrics, but don't recognise assignment \"%s\"\n", fn); diff --git a/src/utils/dawn_uci.c b/src/utils/dawn_uci.c index ea65388..74a1af3 100644 --- a/src/utils/dawn_uci.c +++ b/src/utils/dawn_uci.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -77,8 +78,46 @@ struct time_config_s uci_get_time_config() { return ret; } + +static int get_rrm_mode_val(char mode) { + switch (tolower(mode)) { + case 'a': + return WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE; + break; + case 'p': + return WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE; + break; + case 'b': + case 't': + return WLAN_RRM_CAPS_BEACON_REPORT_TABLE; + break; + } + return 0; +} + +static int parse_rrm_mode(int *rrm_mode_order, const char *mode_string) { + int len, mode_val; + int mask = 0, order = 0, pos = 0; + + if (!mode_string) + mode_string = DEFAULT_RRM_MODE_ORDER; + len = strlen(mode_string); + + while (order < __RRM_BEACON_RQST_MODE_MAX) { + if (pos >= len) { + rrm_mode_order[order++] = 0; + } else { + mode_val = get_rrm_mode_val(mode_string[pos++]); + if (mode_val && !(mask & mode_val)) + mask |= (rrm_mode_order[order++] = mode_val); + } + } + return mask; +} + + struct probe_metric_s uci_get_dawn_metric() { - struct probe_metric_s ret; + struct probe_metric_s ret = {0}; struct uci_element *e; uci_foreach_element(&uci_pkg->sections, e) @@ -116,7 +155,8 @@ struct probe_metric_s uci_get_dawn_metric() { ret.set_hostapd_nr = uci_lookup_option_int(uci_ctx, s, "set_hostapd_nr"); ret.op_class = uci_lookup_option_int(uci_ctx, s, "op_class"); ret.duration = uci_lookup_option_int(uci_ctx, s, "duration"); - ret.mode = uci_lookup_option_int(uci_ctx, s, "mode"); + ret.rrm_mode_mask = parse_rrm_mode(ret.rrm_mode_order, + uci_lookup_option_string(uci_ctx, s, "rrm_mode")); ret.scan_channel = uci_lookup_option_int(uci_ctx, s, "scan_channel"); return ret; } diff --git a/src/utils/msghandler.c b/src/utils/msghandler.c index b9d8b3b..4cbf5bd 100644 --- a/src/utils/msghandler.c +++ b/src/utils/msghandler.c @@ -586,7 +586,7 @@ enum { UCI_SET_HOSTAPD_NR, UCI_OP_CLASS, UCI_DURATION, - UCI_MODE, + UCI_RRM_MODE, UCI_SCAN_CHANNEL, __UCI_METIC_MAX }; @@ -639,8 +639,8 @@ static const struct blobmsg_policy uci_metric_policy[__UCI_METIC_MAX] = { [UCI_SET_HOSTAPD_NR] = {.name = "set_hostapd_nr", .type = BLOBMSG_TYPE_INT32}, [UCI_OP_CLASS] = {.name = "op_class", .type = BLOBMSG_TYPE_INT32}, [UCI_DURATION] = {.name = "duration", .type = BLOBMSG_TYPE_INT32}, - [UCI_MODE] = {.name = "mode", .type = BLOBMSG_TYPE_INT32}, - [UCI_SCAN_CHANNEL] = {.name = "mode", .type = BLOBMSG_TYPE_INT32}, + [UCI_RRM_MODE] = {.name = "rrm_mode", .type = BLOBMSG_TYPE_STRING}, + [UCI_SCAN_CHANNEL] = {.name = "scan_channel", .type = BLOBMSG_TYPE_INT32}, }; static const struct blobmsg_policy uci_times_policy[__UCI_TIMES_MAX] = { @@ -752,7 +752,7 @@ static int handle_uci_config(struct blob_attr* msg) { sprintf(cmd_buffer, "dawn.@metric[0].duration=%d", blobmsg_get_u32(tb_metric[UCI_DURATION])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].mode=%d", blobmsg_get_u32(tb_metric[UCI_MODE])); + sprintf(cmd_buffer, "dawn.@metric[0].rrm_mode=%s", blobmsg_get_string(tb_metric[UCI_RRM_MODE])); uci_set_network(cmd_buffer); sprintf(cmd_buffer, "dawn.@metric[0].scan_channel=%d", blobmsg_get_u32(tb_metric[UCI_SCAN_CHANNEL])); diff --git a/src/utils/ubus.c b/src/utils/ubus.c index 7d23449..0ab2143 100644 --- a/src/utils/ubus.c +++ b/src/utils/ubus.c @@ -801,16 +801,31 @@ void update_channel_utilization(struct uloop_timeout *t) { uloop_timeout_set(&channel_utilization_timer, timeout_config.update_chan_util * 1000); } -void ubus_send_beacon_report(struct dawn_mac client, int id) +static int get_mode_from_capability(int capability) { + for (int n = 0; n < __RRM_BEACON_RQST_MODE_MAX; n++) { + switch (capability & dawn_metric.rrm_mode_order[n]) { + case WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE: + return RRM_BEACON_RQST_MODE_PASSIVE; + case WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE: + return RRM_BEACON_RQST_MODE_ACTIVE; + case WLAN_RRM_CAPS_BEACON_REPORT_TABLE: + return RRM_BEACON_RQST_MODE_BEACON_TABLE; + } + } + return -1; +} + +void ubus_send_beacon_report(client *c, int id) { printf("Crafting Beacon Report\n"); int timeout = 1; + blob_buf_init(&b_beacon, 0); - blobmsg_add_macaddr(&b_beacon, "addr", client); + blobmsg_add_macaddr(&b_beacon, "addr", c->client_addr); blobmsg_add_u32(&b_beacon, "op_class", dawn_metric.op_class); blobmsg_add_u32(&b_beacon, "channel", dawn_metric.scan_channel); blobmsg_add_u32(&b_beacon, "duration", dawn_metric.duration); - blobmsg_add_u32(&b_beacon, "mode", dawn_metric.mode); + blobmsg_add_u32(&b_beacon, "mode", get_mode_from_capability(c->rrm_enabled_capa)); printf("Adding string\n"); blobmsg_add_string(&b_beacon, "ssid", ""); @@ -1326,6 +1341,27 @@ void subscribe_to_new_interfaces(const char *hostapd_sock_path) { return; } +static char get_rrm_mode_char(int val) +{ + switch (val) { + case WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE: + return 'p'; + case WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE: + return 'a'; + case WLAN_RRM_CAPS_BEACON_REPORT_TABLE: + return 't'; + } + return '?'; +} + +const static char* get_rrm_mode_string(int *rrm_mode_order) { + static char rrm_mode_string [__RRM_BEACON_RQST_MODE_MAX + 1] = {0}; + + for (int n = 0; n < __RRM_BEACON_RQST_MODE_MAX && rrm_mode_order[n]; n++) + rrm_mode_string[n] = get_rrm_mode_char(rrm_mode_order[n]); + return rrm_mode_string; +} + int uci_send_via_network() { void *metric, *times; @@ -1363,7 +1399,7 @@ int uci_send_via_network() blobmsg_add_u32(&b, "set_hostapd_nr", dawn_metric.set_hostapd_nr); blobmsg_add_u32(&b, "op_class", dawn_metric.op_class); blobmsg_add_u32(&b, "duration", dawn_metric.duration); - blobmsg_add_u32(&b, "mode", dawn_metric.mode); + blobmsg_add_string(&b, "rrm_mode", get_rrm_mode_string(dawn_metric.rrm_mode_order)); blobmsg_add_u32(&b, "scan_channel", dawn_metric.scan_channel); blobmsg_close_table(&b, metric); @@ -1572,7 +1608,7 @@ int ap_get_nr(struct blob_buf *b_local, struct dawn_mac own_bssid_addr, const ch for (i = ap_set; i != NULL; i = i->next_ap) { if (mac_is_equal_bb(own_bssid_addr, i->bssid_addr) || - strncmp((char *)i->ssid, ssid, SSID_MAX_LEN)) { + strncmp((char *)i->ssid, ssid, SSID_MAX_LEN)) { continue; }