diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95bfa1d..20f6bd8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,9 +14,9 @@ jobs: - name: Install dependencies run: sudo apt install git subversion build-essential python gawk unzip libncurses5-dev zlib1g-dev libssl-dev wget time libncurses-dev - name: Download OpenWrt SDK - run: curl -o openwrt-sdk.tar.xz https://downloads.openwrt.org/snapshots/targets/ath79/generic/openwrt-sdk-ath79-generic_gcc-8.4.0_musl.Linux-x86_64.tar.xz + run: curl -o openwrt-sdk.tar.xz https://downloads.openwrt.org/snapshots/targets/ath79/generic/openwrt-sdk-ath79-generic_gcc-11.2.0_musl.Linux-x86_64.tar.xz - name: Extract OpenWrt SDK - run: tar xf openwrt-sdk.tar.xz && mv openwrt-sdk-ath79-generic_gcc-8.4.0_musl.Linux-x86_64 sdk + run: tar xf openwrt-sdk.tar.xz && mv openwrt-sdk-ath79-generic_gcc-11.2.0_musl.Linux-x86_64 sdk - name: Create config run: make -C sdk defconfig && echo "CONFIG_SRC_TREE_OVERRIDE=y" >> sdk/.config - name: Update package feed diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d10fb9d..fc4f294 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,7 +77,7 @@ SET(SOURCES_TEST_HEADER test/test_header.c) SET(LIBS - ubox ubus json-c blobmsg_json uci gcrypt iwinfo) + ubox ubus json-c blobmsg_json uci gcrypt iwinfo pthread) ADD_EXECUTABLE(dawn ${SOURCES}) ADD_EXECUTABLE(test_storage ${SOURCES_TEST_STORAGE}) diff --git a/src/include/datastorage.h b/src/include/datastorage.h index cb60a33..5e10491 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; @@ -39,26 +48,34 @@ struct mac_entry_s* insert_to_mac_array(struct mac_entry_s* entry, struct mac_en void mac_array_delete(struct mac_entry_s* entry); +int get_band(int freq); // ---------------- Global variables ---------------- /*** Metrics and configuration data ***/ +// TODO: Define a proper version string +#ifndef DAWN_CONFIG_VERSION +#define DAWN_CONFIG_VERSION "3" +#endif + +// Band definitions +// Keep them sorted by frequency, in ascending order +enum dawn_bands { + DAWN_BAND_80211G, + DAWN_BAND_80211A, + __DAWN_BAND_MAX +}; + +// config section name +extern const char *band_config_name[__DAWN_BAND_MAX]; + +// starting frequency +// TODO: make this configurable +extern const int max_band_freq[__DAWN_BAND_MAX]; + // ---------------- Structs ---------------- struct probe_metric_s { - int ap_weight; // TODO: Never evaluated? - int ht_support; // eval_probe_metric()() - int vht_support; // eval_probe_metric()() - int no_ht_support; // eval_probe_metric()() - int no_vht_support; // eval_probe_metric()() - int rssi; // eval_probe_metric()() - int low_rssi; // eval_probe_metric()() - int freq; // eval_probe_metric()() - int chan_util; // eval_probe_metric()() - int max_chan_util; // eval_probe_metric()() - int rssi_val; // eval_probe_metric()() - int low_rssi_val; // eval_probe_metric()() - int chan_util_val; // eval_probe_metric()() - int max_chan_util_val; // eval_probe_metric()() + // Global Configuration int min_probe_count; int bandwidth_threshold; // kick_clients() int use_station_count; // better_ap_available() @@ -69,14 +86,33 @@ struct probe_metric_s { int deny_auth_reason; int deny_assoc_reason; int use_driver_recog; - int min_kick_count; // kick_clients() + int min_number_to_kick; // kick_clients() int chan_util_avg_period; int set_hostapd_nr; int kicking; - int op_class; + int kicking_threshold; int duration; - int mode; - int scan_channel; + int rrm_mode_mask; + int rrm_mode_order[__RRM_BEACON_RQST_MODE_MAX]; + + // Per-band Configuration + int initial_score[__DAWN_BAND_MAX]; // eval_probe_metric()() + int ap_weight[__DAWN_BAND_MAX]; // TODO: Never evaluated? + int ht_support[__DAWN_BAND_MAX]; // eval_probe_metric()() + int vht_support[__DAWN_BAND_MAX]; // eval_probe_metric()() + int no_ht_support[__DAWN_BAND_MAX]; // eval_probe_metric()() + int no_vht_support[__DAWN_BAND_MAX]; // eval_probe_metric()() + int rssi[__DAWN_BAND_MAX]; // eval_probe_metric()() + int low_rssi[__DAWN_BAND_MAX]; // eval_probe_metric()() + int chan_util[__DAWN_BAND_MAX]; // eval_probe_metric()() + int max_chan_util[__DAWN_BAND_MAX]; // eval_probe_metric()() + int rssi_val[__DAWN_BAND_MAX]; // eval_probe_metric()() + int low_rssi_val[__DAWN_BAND_MAX]; // eval_probe_metric()() + int chan_util_val[__DAWN_BAND_MAX]; // eval_probe_metric()() + int max_chan_util_val[__DAWN_BAND_MAX]; // eval_probe_metric()() + int rssi_weight[__DAWN_BAND_MAX]; // eval_probe_metric()() + int rssi_center[__DAWN_BAND_MAX]; // eval_probe_metric()() + struct mac_entry_s* neighbors[__DAWN_BAND_MAX]; // ap_get_nr() }; struct time_config_s { @@ -97,6 +133,7 @@ struct time_config_s { struct network_config_s { char broadcast_ip[MAX_IP_LENGTH]; int broadcast_port; + char server_ip[MAX_IP_LENGTH]; int tcp_port; int network_option; char shared_key[MAX_KEY_LENGTH]; @@ -121,12 +158,15 @@ extern struct probe_metric_s dawn_metric; /* Probe, Auth, Assoc */ +#define SSID_MAX_LEN 32 + // ---------------- Structs ---------------- typedef struct probe_entry_s { struct probe_entry_s* next_probe; struct probe_entry_s* next_probe_skip; struct dawn_mac client_addr; struct dawn_mac bssid_addr; + uint8_t ssid[SSID_MAX_LEN + 1]; // parse_to_beacon_rep() struct dawn_mac target_addr; // TODO: Never evaluated? uint32_t signal; // eval_probe_metric() uint32_t freq; // eval_probe_metric() @@ -169,8 +209,22 @@ typedef struct auth_entry_s assoc_entry; // ---------------- Defines ---------------- -#define SSID_MAX_LEN 32 #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; @@ -200,7 +254,7 @@ typedef struct client_s { char signature[SIGNATURE_LEN]; // TODO: Never evaluated? uint8_t ht_supported; // TODO: Never evaluated? uint8_t vht_supported; // TODO: Never evaluated? - uint32_t freq; // TODO: Never evaluated? + uint32_t freq; // ap_get_nr() uint8_t auth; // TODO: Never evaluated? uint8_t assoc; // TODO: Never evaluated? uint8_t authorized; // TODO: Never evaluated? @@ -220,14 +274,16 @@ typedef struct client_s { typedef struct ap_s { struct ap_s* next_ap; struct dawn_mac bssid_addr; - uint32_t freq; // TODO: Never evaluated? + uint32_t freq; // ap_get_nr() uint8_t ht_support; // eval_probe_metric() uint8_t vht_support; // eval_probe_metric() uint32_t channel_utilization; // eval_probe_metric() time_t time; // remove_old...entries uint32_t station_count; // compare_station_count() <- better_ap_available() - uint8_t ssid[SSID_MAX_LEN]; // compare_sid() < -better_ap_available() + uint8_t ssid[SSID_MAX_LEN + 1]; // compare_sid() < -better_ap_available() char neighbor_report[NEIGHBOR_REPORT_LEN]; + uint32_t op_class; // ubus_send_beacon_report() + uint32_t channel; // ubus_send_beacon_report() uint32_t collision_domain; // TODO: ap_get_collision_count() never evaluated? uint32_t bandwidth; // TODO: Never evaluated? uint32_t ap_weight; // eval_probe_metric() @@ -304,24 +360,27 @@ void remove_old_ap_entries(time_t current_time, long long int threshold); void print_ap_array(); -ap *ap_array_get_ap(struct dawn_mac bssid_mac); +ap *ap_array_get_ap(struct dawn_mac bssid_mac, const uint8_t* ssid); int probe_array_set_all_probe_count(struct dawn_mac client_addr, uint32_t probe_count); -#ifndef DAWN_NO_OUTPUT int ap_get_collision_count(int col_domain); -#endif -void send_beacon_reports(struct dawn_mac bssid, int id); +void send_beacon_reports(ap *a, int id); /* Utils */ // deprecate use of this - it makes things slow #define SORT_LENGTH 5 extern char sort_string[]; +struct kicking_nr { + char nr[NEIGHBOR_REPORT_LEN]; + int score; + struct kicking_nr *next; +}; // ---------------- Functions ------------------- -int better_ap_available(ap *kicking_ap, struct dawn_mac client_addr, char* neighbor_report); +int better_ap_available(ap *kicking_ap, struct dawn_mac client_addr, struct kicking_nr** neighbor_report); // All users of datastorage should call init_ / destroy_mutex at initialisation and termination respectively int init_mutex(); diff --git a/src/include/mac_utils.h b/src/include/mac_utils.h index 3c1299f..04b0dee 100644 --- a/src/include/mac_utils.h +++ b/src/include/mac_utils.h @@ -10,6 +10,9 @@ #define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X" #define MACSTRLOWER "%02x:%02x:%02x:%02x:%02x:%02x" +#define NR_MACSTR "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c" +#define NR_MAC2STR(a) *a, *(a+1), *(a+2), *(a+3), *(a+4), *(a+5), *(a+6), *(a+7), *(a+8), *(a+9), *(a+10), *(a+11) + #ifndef ETH_ALEN #define ETH_ALEN 6 #endif diff --git a/src/include/ubus.h b/src/include/ubus.h index ad36c44..4ad2893 100644 --- a/src/include/ubus.h +++ b/src/include/ubus.h @@ -29,7 +29,7 @@ int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir); /** * Start the umdns timer for updating the zeroconfiguration properties. */ -void start_umdns_update(); +void start_tcp_con_update(); /** * Call umdns update to update the TCP connections. @@ -68,14 +68,7 @@ void del_client_all_interfaces(const struct dawn_mac client_addr, uint32_t reaso */ void update_hostapd_sockets(struct uloop_timeout *t); -/** - * Send control message to all hosts to add the mac to a don't control list. - * @param client_addr - * @return - */ -int send_add_mac(struct dawn_mac client_addr); - -void ubus_send_beacon_report(struct dawn_mac client, int id); +void ubus_send_beacon_report(client *c, ap *a, int id); void uloop_add_data_cbs(); @@ -85,7 +78,7 @@ int build_hearing_map_sort_client(struct blob_buf* b); int build_network_overview(struct blob_buf* b); -int ap_get_nr(struct blob_buf* b, struct dawn_mac own_bssid_addr); +int ap_get_nr(struct blob_buf* b, struct dawn_mac own_bssid_addr, const char *ssid); int parse_add_mac_to_file(struct blob_attr* msg); @@ -146,6 +139,13 @@ int send_set_probe(struct dawn_mac client_addr); * @param duration * @return - 0 = asynchronous (client has been told to remove itself, and caller should manage arrays); 1 = synchronous (caller should assume arrays are updated) */ -int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, char* dest_ap, uint32_t duration); +int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, uint32_t duration); + +/** + * Send control message to all hosts to add the mac to a don't control list. + * @param client_addr + * @return + */ +int send_add_mac(struct dawn_mac client_addr); #endif diff --git a/src/main.c b/src/main.c index 0aa68a4..1a6c50f 100644 --- a/src/main.c +++ b/src/main.c @@ -48,7 +48,6 @@ void signal_handler(int sig) { } } - int main(int argc, char **argv) { const char *ubus_socket = NULL; diff --git a/src/network/networksocket.c b/src/network/networksocket.c index 1f176bf..19bc083 100644 --- a/src/network/networksocket.c +++ b/src/network/networksocket.c @@ -37,7 +37,9 @@ int init_socket_runopts(const char *_ip, int _port, int _multicast_socket) { multicast_socket = _multicast_socket; if (multicast_socket) { +#ifndef DAWN_NO_OUTPUT printf("Settingup multicastsocket!\n"); +#endif sock = setup_multicast_socket(ip, port, &addr); } else { sock = setup_broadcast_socket(ip, port, &addr); @@ -56,7 +58,9 @@ int init_socket_runopts(const char *_ip, int _port, int _multicast_socket) { } } +#ifndef DAWN_NO_OUTPUT fprintf(stdout, "Connected to %s:%d\n", ip, port); +#endif return 0; } @@ -79,7 +83,9 @@ void *receive_msg(void *args) { } recv_string[recv_string_len] = '\0'; +#ifndef DAWN_NO_OUTPUT printf("Received network message: %s\n", recv_string); +#endif handle_network_msg(recv_string); } } @@ -115,7 +121,9 @@ void *receive_msg_enc(void *args) { return 0; } +#ifndef DAWN_NO_OUTPUT printf("Received network message: %s\n", dec); +#endif dawn_free(base64_dec_str); handle_network_msg(dec); dawn_free(dec); diff --git a/src/network/tcpsocket.c b/src/network/tcpsocket.c index 5fd9ea7..91b9660 100644 --- a/src/network/tcpsocket.c +++ b/src/network/tcpsocket.c @@ -11,6 +11,8 @@ #define STR_EVAL(x) #x #define STR_QUOTE(x) STR_EVAL(x) +#define HEADER_SIZE sizeof(uint32_t) + LIST_HEAD(tcp_sock_list); struct network_con_s *tcp_list_contains_address(struct sockaddr_in entry); @@ -36,6 +38,7 @@ struct client { uint32_t curr_len; // bytes read so far }; + static void client_close(struct ustream *s) { struct client *cl = container_of(s, struct client, s.stream); @@ -89,45 +92,40 @@ static void client_to_server_state(struct ustream *s) { static void client_read_cb(struct ustream *s, int bytes) { struct client *cl = container_of(s, struct client, s.stream); - struct ustream_fd* ufd = container_of(s, struct ustream_fd, stream); - + while(1) { - printf("tcp_socket: looping - U-EOF = %d, U-error = %d...\n", ufd->fd.eof, ufd->fd.error); if (cl->state == READ_STATUS_READY) { - printf("tcp_socket: commencing message...\n"); - uint32_t min_len = sizeof(uint32_t); // big enough to get msg length - cl->str = dawn_malloc(min_len); + cl->str = dawn_malloc(HEADER_SIZE); if (!cl->str) { - fprintf(stderr,"tcp_socket: not enough memory (" STR_QUOTE(__LINE__) ")\n"); + fprintf(stderr,"not enough memory (" STR_QUOTE(__LINE__) ")\n"); break; } uint32_t avail_len = ustream_pending_data(s, false); - if (avail_len < min_len){//ensure recv sizeof(uint32_t) - printf("tcp_socket: not complete msg, len:%d, expected len:%u\n", avail_len, min_len); + if (avail_len < HEADER_SIZE){//ensure recv sizeof(uint32_t) dawn_free(cl->str); cl->str = NULL; break; } - if (ustream_read(s, cl->str, min_len) != min_len) // read msg length bytes + if (ustream_read(s, cl->str, HEADER_SIZE) != HEADER_SIZE) // read msg length bytes { - fprintf(stdout,"tcp_socket: msg length read failed\n"); + fprintf(stdout,"msg length read failed\n"); dawn_free(cl->str); cl->str = NULL; break; - } + } - cl->curr_len += min_len; + cl->curr_len += HEADER_SIZE; cl->final_len = ntohl(*(uint32_t *)cl->str); // On failure, dawn_realloc returns a null pointer. The original pointer str // remains valid and may need to be deallocated. char *str_tmp = dawn_realloc(cl->str, cl->final_len); if (!str_tmp) { - fprintf(stderr,"tcp_socket: not enough memory (%" PRIu32 " @ " STR_QUOTE(__LINE__) ")\n", cl->final_len); + fprintf(stderr,"not enough memory (%" PRIu32 " @ " STR_QUOTE(__LINE__) ")\n", cl->final_len); dawn_free(cl->str); cl->str = NULL; break; @@ -140,7 +138,6 @@ static void client_read_cb(struct ustream *s, int bytes) { if (cl->state == READ_STATUS_COMMENCED) { - printf("tcp_socket: reading message...\n"); uint32_t read_len = ustream_pending_data(s, false); if (read_len == 0) @@ -149,26 +146,23 @@ static void client_read_cb(struct ustream *s, int bytes) { if (read_len > (cl->final_len - cl->curr_len)) read_len = cl->final_len - cl->curr_len; - printf("tcp_socket: reading %" PRIu32 " bytes to add to %" PRIu32 " of %" PRIu32 "...\n", - read_len, cl->curr_len, cl->final_len); - uint32_t this_read = ustream_read(s, cl->str + cl->curr_len, read_len); cl->curr_len += this_read; - printf("tcp_socket: ...and we're back, now have %" PRIu32 " bytes\n", cl->curr_len); if (cl->curr_len == cl->final_len){//ensure recv final_len bytes. // Full message now received cl->state = READ_STATUS_COMPLETE; - printf("tcp_socket: message completed\n"); } } if (cl->state == READ_STATUS_COMPLETE) { +#ifndef DAWN_NO_OUTPUT printf("tcp_socket: processing message...\n"); +#endif if (network_config.use_symm_enc) { - char *dec = gcrypt_decrypt_msg(cl->str + 4, cl->final_len - 4); + char *dec = gcrypt_decrypt_msg(cl->str + HEADER_SIZE, cl->final_len - HEADER_SIZE);//len of str is final_len if (!dec) { - fprintf(stderr,"tcp_socket: not enough memory (" STR_QUOTE(__LINE__) ")\n"); + fprintf(stderr,"not enough memory (" STR_QUOTE(__LINE__) ")\n"); dawn_free(cl->str); cl->str = NULL; break; @@ -176,7 +170,7 @@ static void client_read_cb(struct ustream *s, int bytes) { handle_network_msg(dec); dawn_free(dec); } else { - handle_network_msg(cl->str + 4); + handle_network_msg(cl->str + HEADER_SIZE);//len of str is final_len } cl->state = READ_STATUS_READY; @@ -187,8 +181,6 @@ static void client_read_cb(struct ustream *s, int bytes) { } } - printf("tcp_socket: leaving\n"); - return; } @@ -218,7 +210,6 @@ static void server_cb(struct uloop_fd *fd, unsigned int events) { } int run_server(int port) { - printf("Adding socket!\n"); char port_str[12]; sprintf(port_str, "%d", port); @@ -240,7 +231,6 @@ static void client_not_be_used_read_cb(struct ustream *s, int bytes) { len = ustream_read(s, buf, sizeof(buf)); buf[len] = '\0'; - printf("Read %d bytes from SSL connection: %s\n", len, buf); } static void connect_cb(struct uloop_fd *f, unsigned int events) { @@ -255,7 +245,6 @@ static void connect_cb(struct uloop_fd *f, unsigned int events) { return; } - fprintf(stderr, "Connection established\n"); uloop_fd_delete(&entry->fd); entry->stream.stream.notify_read = client_not_be_used_read_cb; @@ -300,7 +289,6 @@ int add_tcp_conncection(char *ipv4, int port) { tcp_entry->fd.cb = connect_cb; uloop_fd_add(&tcp_entry->fd, ULOOP_WRITE | ULOOP_EDGE_TRIGGER); - printf("New TCP connection to %s:%d\n", ipv4, port); list_add(&tcp_entry->list, &tcp_sock_list); return 0; @@ -332,7 +320,6 @@ void send_tcp(char *msg) { { if (con->connected) { int len_ustream = ustream_write(&con->stream.stream, final_str, final_len, 0); - printf("Ustream send: %d\n", len_ustream); if (len_ustream <= 0) { fprintf(stderr,"Ustream error(" STR_QUOTE(__LINE__) ")!\n"); //ERROR HANDLING! @@ -365,7 +352,6 @@ void send_tcp(char *msg) { { if (con->connected) { int len_ustream = ustream_write(&con->stream.stream, final_str, final_len, 0); - printf("Ustream send: %d\n", len_ustream); if (len_ustream <= 0) { //ERROR HANDLING! fprintf(stderr,"Ustream error(" STR_QUOTE(__LINE__) ")!\n"); @@ -396,6 +382,7 @@ struct network_con_s* tcp_list_contains_address(struct sockaddr_in entry) { } void print_tcp_array() { +#ifndef DAWN_NO_OUTPUT struct network_con_s *con; printf("--------Connections------\n"); @@ -404,4 +391,5 @@ void print_tcp_array() { printf("Connecting to Port: %d, Connected: %s\n", ntohs(con->sock_addr.sin_port), con->connected ? "True" : "False"); } printf("------------------\n"); +#endif } diff --git a/src/storage/datastorage.c b/src/storage/datastorage.c index c2f88c5..b37d885 100644 --- a/src/storage/datastorage.c +++ b/src/storage/datastorage.c @@ -26,18 +26,9 @@ 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); - -static void print_ap_entry(ap *entry); +static int kick_client(ap* kicking_ap, struct client_s *client_entry, struct kicking_nr** neighbor_report); static int is_connected(struct dawn_mac bssid_mac, struct dawn_mac client_mac); @@ -49,6 +40,19 @@ struct auth_entry_s *denied_req_set = NULL; int denied_req_last = 0; pthread_mutex_t denied_array_mutex; +// config section name +const char *band_config_name[__DAWN_BAND_MAX] = { + "802_11g", + "802_11a" +}; + +// starting frequency +// TODO: make this configurable +const int max_band_freq[__DAWN_BAND_MAX] = { + 2500, + 5925 // This may cause trouble because there's overlap between bands in different countries +}; + // Ratio of skiping entries to all entries. // Approx sqrt() of large data set, and power of 2 for efficient division when adding entries. #define DAWN_PROBE_SKIP_RATIO 128 @@ -166,7 +170,7 @@ static probe_entry** probe_array_find_first_entry(struct dawn_mac client_mac, st return lo_ptr; } -static ap** ap_array_find_first_entry(struct dawn_mac bssid_mac) +static ap** ap_array_find_first_entry(struct dawn_mac bssid_mac, const uint8_t* ssid) { int lo = 0; ap** lo_ptr = &ap_set; @@ -175,6 +179,7 @@ static ap** ap_array_find_first_entry(struct dawn_mac bssid_mac) while (lo < hi) { ap** i = lo_ptr; int scan_pos = lo; + int this_cmp; // m is next test position of binary search int m = (lo + hi) / 2; @@ -185,7 +190,15 @@ static ap** ap_array_find_first_entry(struct dawn_mac bssid_mac) i = &((*i)->next_ap); } - int this_cmp = mac_compare_bb((*i)->bssid_addr, bssid_mac); + if (ssid) + { + this_cmp = strcmp((char*)(*i)->ssid, (char*)ssid); + } + else + { + this_cmp = 0; + } + this_cmp = this_cmp ? this_cmp : mac_compare_bb((*i)->bssid_addr, bssid_mac); if (this_cmp < 0) { @@ -351,6 +364,28 @@ auth_entry** auth_entry_find_first_entry(struct dawn_mac bssid_mac, struct dawn_ return lo_ptr; } +void send_beacon_reports(ap *a, int id) { + pthread_mutex_lock(&client_array_mutex); + + // Seach for BSSID + client* i = *client_find_first_bc_entry(a->bssid_addr, dawn_mac_null, false); + + // Go threw clients + while (i != NULL && mac_is_equal_bb(i->bssid_addr, a->bssid_addr)) { + dawnlog(LOG_INFO,"Client " MACSTR ": rrm_enabled_capa=%02x: PASSIVE=%d, ACTIVE=%d, TABLE=%d\n", + MAC2STR(i->client_addr.u8), i->rrm_enabled_capa, + !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE), + !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE), + !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_TABLE)); + if (i->rrm_enabled_capa & dawn_metric.rrm_mode_mask) + ubus_send_beacon_report(i, a, id); + + i = i->next_entry_bc; + } + + pthread_mutex_unlock(&client_array_mutex); +} + static struct mac_entry_s** mac_find_first_entry(struct dawn_mac mac) { int lo = 0; @@ -386,64 +421,49 @@ static struct mac_entry_s** mac_find_first_entry(struct dawn_mac mac) return lo_ptr; } -void send_beacon_reports(struct dawn_mac bssid, int id) { - pthread_mutex_lock(&client_array_mutex); +int get_band(int freq) { + int band; - // Seach for BSSID - client* i = *client_find_first_bc_entry(bssid, dawn_mac_null, false); - - // Go threw clients - while (i != NULL && mac_is_equal_bb(i->bssid_addr, bssid)) { - 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); - - i = i->next_entry_bc; - } - - pthread_mutex_unlock(&client_array_mutex); + for (band=0; band < __DAWN_BAND_MAX; band++) + if (freq <= max_band_freq[band]) + return band; + band--; + dawnlog(LOG_ERR, "Warning: frequency %d is beyond the last known band. " + "Using '%s' band parameters.\n", freq, band_config_name[band]); + return band; } // TODO: Can metric be cached once calculated? Add score_fresh indicator and reset when signal changes // TODO: as rest of values look to be static fr any given entry. int eval_probe_metric(struct probe_entry_s* probe_entry, ap* ap_entry) { - int score = 0; + int band, score = 0; + + // TODO: Should RCPI be used here as well? + band = get_band(probe_entry->freq); + score = dawn_metric.initial_score[band]; + score += probe_entry->signal >= dawn_metric.rssi_val[band] ? dawn_metric.rssi[band] : 0; + score += probe_entry->signal <= dawn_metric.low_rssi_val[band] ? dawn_metric.low_rssi[band] : 0; + score += (probe_entry->signal - dawn_metric.rssi_center[band]) * dawn_metric.rssi_weight[band]; // check if ap entry is available if (ap_entry != NULL) { - score += probe_entry->ht_capabilities && ap_entry->ht_support ? dawn_metric.ht_support : 0; - score += !probe_entry->ht_capabilities && !ap_entry->ht_support ? dawn_metric.no_ht_support : 0; // TODO: Is both devices not having a capability worthy of scoring? + score += probe_entry->ht_capabilities && ap_entry->ht_support ? dawn_metric.ht_support[band] : 0; + score += !probe_entry->ht_capabilities && !ap_entry->ht_support ? dawn_metric.no_ht_support[band] : 0; // TODO: Is both devices not having a capability worthy of scoring? // performance anomaly? if (network_config.bandwidth >= 1000 || network_config.bandwidth == -1) { - score += probe_entry->vht_capabilities && ap_entry->vht_support ? dawn_metric.vht_support : 0; + score += probe_entry->vht_capabilities && ap_entry->vht_support ? dawn_metric.vht_support[band] : 0; } - score += !probe_entry->vht_capabilities && !ap_entry->vht_support ? dawn_metric.no_vht_support : 0; // TODO: Is both devices not having a capability worthy of scoring? - score += ap_entry->channel_utilization <= dawn_metric.chan_util_val ? dawn_metric.chan_util : 0; - score += ap_entry->channel_utilization > dawn_metric.max_chan_util_val ? dawn_metric.max_chan_util : 0; + score += !probe_entry->vht_capabilities && !ap_entry->vht_support ? dawn_metric.no_vht_support[band] : 0; // TODO: Is both devices not having a capability worthy of scoring? + score += ap_entry->channel_utilization <= dawn_metric.chan_util_val[band] ? dawn_metric.chan_util[band] : 0; + score += ap_entry->channel_utilization > dawn_metric.max_chan_util_val[band] ? dawn_metric.max_chan_util[band] : 0; score += ap_entry->ap_weight; } - score += (probe_entry->freq > 5000) ? dawn_metric.freq : 0; - - // TODO: Should RCPI be used here as well? - if (probe_entry->signal >= dawn_metric.rssi_val) - score += dawn_metric.rssi; - else if(probe_entry->signal <= dawn_metric.low_rssi_val) - score += dawn_metric.low_rssi; - else - { - score += dawn_metric.low_rssi; - score += ((probe_entry->signal - dawn_metric.low_rssi_val) * - (dawn_metric.rssi - dawn_metric.low_rssi)) / - (dawn_metric.rssi_val - dawn_metric.low_rssi_val); - } - + // TODO: This magic value never checked by caller. What does it achieve? if (score < 0) score = 0; @@ -456,38 +476,95 @@ int eval_probe_metric(struct probe_entry_s* probe_entry, ap* ap_entry) { static int compare_station_count(ap* ap_entry_own, ap* ap_entry_to_compare, struct dawn_mac client_addr) { - dawnlog(LOG_INFO, "Comparing own %d to %d\n", ap_entry_own->station_count, ap_entry_to_compare->station_count); + dawnlog(LOG_INFO,"Comparing own %d to %d\n", ap_entry_own->station_count, ap_entry_to_compare->station_count); int sta_count = ap_entry_own->station_count; int sta_count_to_compare = ap_entry_to_compare->station_count; if (is_connected(ap_entry_own->bssid_addr, client_addr)) { - dawnlog(LOG_INFO, "Own is already connected! Decrease counter!\n"); sta_count--; } if (is_connected(ap_entry_to_compare->bssid_addr, client_addr)) { - dawnlog(LOG_INFO, "Comparing station is already connected! Decrease counter!\n"); sta_count_to_compare--; } - dawnlog(LOG_INFO, "Comparing own station count %d to %d\n", sta_count, sta_count_to_compare); + dawnlog(LOG_INFO,"Comparing own station count %d to %d\n", sta_count, sta_count_to_compare); - return sta_count - sta_count_to_compare > dawn_metric.max_station_diff; + if (sta_count - sta_count_to_compare > dawn_metric.max_station_diff) + return 1; + else if (sta_count_to_compare - sta_count > dawn_metric.max_station_diff) + return -1; + else + return 0; } -int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, char* neighbor_report) { +static struct kicking_nr *find_position(struct kicking_nr *nrlist, int score) { + struct kicking_nr *ret = NULL; + + while (nrlist && nrlist->score < score) { + ret = nrlist; + nrlist = nrlist->next; + } + return ret; +} + +static void remove_kicking_nr_list(struct kicking_nr *nr_list) { + struct kicking_nr *n; + + while(nr_list) { + n = nr_list->next; + dawn_free(nr_list); + nr_list = n; + } +} + +static struct kicking_nr *prune_kicking_nr_list(struct kicking_nr *nr_list, int min_score) { + struct kicking_nr *next; + + while (nr_list && nr_list->score <= min_score) { + next = nr_list->next; + dawn_free(nr_list); + nr_list = next; + } + return nr_list; +} + +static struct kicking_nr *insert_kicking_nr(struct kicking_nr *head, char *nr, int score, bool prune) { + struct kicking_nr *new_entry, *pos; + + if (prune) + head = prune_kicking_nr_list(head, score - dawn_metric.kicking_threshold); + + // we are giving no error information here (not really critical) + if (!(new_entry = dawn_malloc(sizeof (struct kicking_nr)))) + return head; + + strncpy(new_entry->nr, nr, NEIGHBOR_REPORT_LEN); + new_entry->score = score; + pos = find_position(head, score); + if (pos) { + new_entry->next = pos->next; + pos -> next = new_entry; + } else { + new_entry->next = head; + head = new_entry; + } + return head; +} + +int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicking_nr **neighbor_report) { // This remains set to the current AP of client for rest of function probe_entry* own_probe = *probe_array_find_first_entry(client_mac, kicking_ap->bssid_addr, true); int own_score = -1; if (own_probe != NULL && mac_is_equal_bb(own_probe->client_addr, client_mac) && mac_is_equal_bb(own_probe->bssid_addr, kicking_ap->bssid_addr)) { - dawnlog(LOG_INFO, "Calculating own score!\n"); + dawnlog(LOG_INFO,"Calculating own score!\n"); own_score = eval_probe_metric(own_probe, kicking_ap); //TODO: Should the -2 return be handled? } // no entry for own ap - should never happen? else { dawnlog(LOG_INFO, "Current AP not found in probe array!\n"); - return 0; + return -1; } int max_score = own_score; @@ -503,7 +580,7 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, char* neighb continue; } - ap* candidate_ap = ap_array_get_ap(i->bssid_addr); + ap* candidate_ap = ap_array_get_ap(i->bssid_addr, kicking_ap->ssid); if (candidate_ap == NULL) { i = i->next_probe; @@ -516,39 +593,48 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, char* neighb continue; } - dawnlog(LOG_INFO, "Calculating score to compare!\n"); + dawnlog(LOG_INFO,"Calculating score to compare!\n"); int score_to_compare = eval_probe_metric(i, candidate_ap); // Find better score... - if (score_to_compare > max_score) { + if (score_to_compare > max_score + (kick ? 0 : dawn_metric.kicking_threshold)) { if(neighbor_report == NULL) { - dawnlog(LOG_ERR,"Neigbor-Report is NULL!\n"); - return 0; + dawnlog(LOG_ERR,"Neighbor-Report is NULL!\n"); + return 1; // TODO: Should this be -1? } kick = 1; - // instead of returning we append a neighbor report list... - strcpy(neighbor_report, candidate_ap->neighbor_report); + // instead of returning we add the ap to the neighbor report list, pruning it first... + *neighbor_report = insert_kicking_nr(*neighbor_report, candidate_ap->neighbor_report, score_to_compare, true); max_score = score_to_compare; } // if ap have same value but station count is different... // TODO: Is absolute number meaningful when AP have diffeent capacity? - else if (dawn_metric.use_station_count > 0 && score_to_compare == max_score ) { + else if (dawn_metric.use_station_count > 0 && score_to_compare >= max_score ) { + int compare = compare_station_count(kicking_ap, candidate_ap, client_mac); - if (compare_station_count(kicking_ap, candidate_ap, client_mac)) { + if (compare > 0) { if (neighbor_report == NULL) { - dawnlog(LOG_ERR, "Neigbor-Report is NULL!\n"); - return 0; + dawnlog(LOG_ERR, "Neighbor-Report is NULL!\n"); + return 1; // TODO: Should this be -1? } kick = 1; - - strcpy(neighbor_report, candidate_ap->neighbor_report); + *neighbor_report = insert_kicking_nr(*neighbor_report, candidate_ap->neighbor_report, + score_to_compare, true); } + else if (compare == 0 && kick) { + *neighbor_report = insert_kicking_nr(*neighbor_report, candidate_ap->neighbor_report, + score_to_compare, false); + } + } + else if (score_to_compare >= max_score && kick) { + *neighbor_report = insert_kicking_nr(*neighbor_report, candidate_ap->neighbor_report, + score_to_compare, false); } i = i->next_probe; @@ -557,7 +643,7 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, char* neighb return kick; } -static int kick_client(ap* kicking_ap, struct client_s *client_entry, char* neighbor_report) { +static int kick_client(ap* kicking_ap, struct client_s *client_entry, struct kicking_nr** neighbor_report) { int ret = 0; if (!mac_in_maclist(client_entry->client_addr)) { @@ -573,20 +659,21 @@ int kick_clients(ap* kicking_ap, uint32_t id) { int kicked_clients = 0; - dawnlog(LOG_INFO, "-------- KICKING CLIENTS!!!---------\n"); + dawnlog(LOG_INFO,"-------- KICKING CLIENTS!!!---------\n"); char mac_buf_ap[20]; sprintf(mac_buf_ap, MACSTR, MAC2STR(kicking_ap->bssid_addr.u8)); - dawnlog(LOG_INFO, "EVAL %s\n", mac_buf_ap); + dawnlog(LOG_INFO,"EVAL %s\n", mac_buf_ap); // Seach for BSSID client *j = *client_find_first_bc_entry(kicking_ap->bssid_addr, dawn_mac_null, false); // Go threw clients while (j != NULL && mac_is_equal_bb(j->bssid_addr, kicking_ap->bssid_addr)) { - char neighbor_report[NEIGHBOR_REPORT_LEN] = ""; + struct kicking_nr *neighbor_report = NULL; - int do_kick = kick_client(kicking_ap, j, neighbor_report); - dawnlog(LOG_INFO, "Chosen AP %s\n", neighbor_report); + int do_kick = kick_client(kicking_ap, j, &neighbor_report); + for (struct kicking_nr *n = neighbor_report; n; n = n->next) + dawnlog(LOG_INFO,"Chosen AP candidate: " NR_MACSTR ", score=%d\n", NR_MAC2STR(n->nr), n->score); // better ap available if (do_kick == 1) { @@ -596,28 +683,33 @@ int kick_clients(ap* kicking_ap, uint32_t id) { // + chan util is changing a lot // + ping pong behavior of clients will be reduced j->kick_count++; - dawnlog(LOG_INFO, "Comparing kick count! kickcount: %d to min_kick_count: %d!\n", j->kick_count, - dawn_metric.min_kick_count); - if (j->kick_count >= dawn_metric.min_kick_count) { - dawnlog(LOG_INFO, "Better AP available. Kicking client:\n"); + dawnlog(LOG_INFO,"Comparing kick count! kickcount: %d to min_number_to_kick: %d!\n", j->kick_count, + dawn_metric.min_number_to_kick); + if (j->kick_count >= dawn_metric.min_number_to_kick) { + dawnlog(LOG_INFO,"Better AP available. Kicking client:\n"); print_client_entry(j); - dawnlog(LOG_INFO, "Check if client is active receiving!\n"); + dawnlog(LOG_INFO,"Check if client is active receiving!\n"); float rx_rate, tx_rate; - if (get_bandwidth_iwinfo(j->client_addr, &rx_rate, &tx_rate)) { - dawnlog(LOG_INFO, "No active transmission data for client. Don't kick!\n"); + bool have_bandwidth_iwinfo = !(get_bandwidth_iwinfo(j->client_addr, &rx_rate, &tx_rate)); + if (!have_bandwidth_iwinfo && dawn_metric.bandwidth_threshold > 0) { + dawnlog(LOG_INFO,"No active transmission data for client. Don't kick!\n"); } else { // only use rx_rate for indicating if transmission is going on // <= 6MBits <- probably no transmission // tx_rate has always some weird value so don't use ist - if (rx_rate > dawn_metric.bandwidth_threshold) { - dawnlog(LOG_INFO, "Client is probably in active transmisison. Don't kick! RxRate is: %f\n", rx_rate); + if (have_bandwidth_iwinfo && rx_rate > dawn_metric.bandwidth_threshold) { + dawnlog(LOG_INFO,"Client is probably in active transmisison. Don't kick! RxRate is: %f\n", rx_rate); } else { - dawnlog(LOG_INFO, "Client is probably NOT in active transmisison. KICK! RxRate is: %f\n", rx_rate); + if (have_bandwidth_iwinfo) + dawnlog(LOG_INFO,"Client is probably NOT in active transmisison. KICK! RxRate is: %f\n", rx_rate); + else + dawnlog(LOG_INFO,"No active tranmission data for client, but bandwidth_threshold=%d means we don't care. KICK!\n", + dawn_metric.bandwidth_threshold); // here we should send a messsage to set the probe.count for all aps to the min that there is no delay between switching // the hearing map is full... @@ -640,6 +732,8 @@ int kick_clients(ap* kicking_ap, uint32_t id) { // don't delete clients in a row. use update function again... // -> chan_util update, ... add_client_update_timer(timeout_config.update_client * 1000 / 4); + remove_kicking_nr_list(neighbor_report); + neighbor_report = NULL; break; } } @@ -649,22 +743,24 @@ int kick_clients(ap* kicking_ap, uint32_t id) { // no entry in probe array for own bssid // TODO: Is test against -1 from (1 && -1) portable? else if (do_kick == -1) { - dawnlog(LOG_INFO, "No Information about client. Force reconnect:\n"); + dawnlog(LOG_INFO,"No Information about client. Force reconnect:\n"); print_client_entry(j); del_client_interface(id, j->client_addr, 0, 1, 0); } // ap is best else { - dawnlog(LOG_INFO, "AP is best. Client will stay:\n"); + dawnlog(LOG_INFO,"AP is best. Client will stay:\n"); print_client_entry(j); // set kick counter to 0 again j->kick_count = 0; } + remove_kicking_nr_list(neighbor_report); + neighbor_report = NULL; j = j->next_entry_bc; } - dawnlog(LOG_INFO, "---------------------------\n"); + dawnlog(LOG_INFO,"---------------------------\n"); pthread_mutex_unlock(&probe_array_mutex); pthread_mutex_unlock(&client_array_mutex); @@ -676,10 +772,10 @@ void update_iw_info(struct dawn_mac bssid_mac) { pthread_mutex_lock(&client_array_mutex); pthread_mutex_lock(&probe_array_mutex); - dawnlog(LOG_INFO, "-------- IW INFO UPDATE!!!---------\n"); + dawnlog(LOG_INFO,"-------- IW INFO UPDATE!!!---------\n"); char mac_buf_ap[20]; sprintf(mac_buf_ap, MACSTR, MAC2STR(bssid_mac.u8)); - dawnlog(LOG_INFO, "EVAL %s\n", mac_buf_ap); + dawnlog(LOG_INFO,"EVAL %s\n", mac_buf_ap); // Seach for BSSID // Go threw clients @@ -689,19 +785,16 @@ void update_iw_info(struct dawn_mac bssid_mac) { int rssi = get_rssi_iwinfo(j->client_addr); int exp_thr = get_expected_throughput_iwinfo(j->client_addr); double exp_thr_tmp = iee80211_calculate_expected_throughput_mbit(exp_thr); - dawnlog(LOG_INFO, "Expected throughput %f Mbit/sec\n", exp_thr_tmp); + dawnlog(LOG_INFO,"Expected throughput %f Mbit/sec\n", exp_thr_tmp); if (rssi != INT_MIN) { if (!probe_array_update_rssi(j->bssid_addr, j->client_addr, rssi, true)) { - dawnlog(LOG_INFO, "Failed to update rssi!\n"); - } - else { - dawnlog(LOG_INFO, "Updated rssi: %d\n", rssi); + dawnlog(LOG_INFO,"Failed to update rssi!\n"); } } } - dawnlog(LOG_INFO, "---------------------------\n"); + dawnlog(LOG_INFO,"---------------------------\n"); pthread_mutex_unlock(&probe_array_mutex); pthread_mutex_unlock(&client_array_mutex); @@ -766,7 +859,7 @@ void client_array_insert(client *entry, client** insert_pos) { client_entry_last++; if (client_entry_last == ARRAY_CLIENT_LEN) { - dawnlog(LOG_INFO, "warning: client_array overflowing (now contains %d entries)!\n", client_entry_last); + dawnlog(LOG_INFO,"warning: client_array overflowing (now contains %d entries)!\n", client_entry_last); } // Try to keep skip list density stable @@ -926,10 +1019,9 @@ int probe_array_set_all_probe_count(struct dawn_mac client_addr, uint32_t probe_ pthread_mutex_lock(&probe_array_mutex); for (probe_entry *i = probe_set; i != NULL; i = i->next_probe) { if (mac_is_equal_bb(client_addr, i->client_addr)) { - dawnlog(LOG_INFO, "Setting probecount for given mac!\n"); i->counter = probe_count; } else if (mac_compare_bb(client_addr, i->client_addr) > 0) { - dawnlog(LOG_INFO, "MAC not found!\n"); + dawnlog(LOG_INFO,"MAC not found!\n"); break; } } @@ -989,12 +1081,12 @@ probe_entry *probe_array_get_entry(struct dawn_mac bssid_mac, struct dawn_mac cl } void print_probe_array() { - dawnlog(LOG_INFO, "------------------\n"); - dawnlog(LOG_INFO, "Probe Entry Last: %d\n", probe_entry_last); + dawnlog(LOG_INFO,"------------------\n"); + dawnlog(LOG_INFO,"Probe Entry Last: %d\n", probe_entry_last); for (probe_entry* i = probe_set; i != NULL ; i = i->next_probe) { print_probe_entry(i); } - dawnlog(LOG_INFO, "------------------\n"); + dawnlog(LOG_INFO,"------------------\n"); } static struct probe_entry_s* insert_to_skip_array(struct probe_entry_s* entry) { @@ -1016,11 +1108,22 @@ probe_entry* insert_to_array(probe_entry* entry, int inc_counter, int save_80211 // TODO: Add a packed / unpacked wrapper pair? probe_entry** existing_entry = probe_array_find_first_entry(entry->client_addr, entry->bssid_addr, true); - if (((*existing_entry) != NULL) && mac_is_equal_bb((*existing_entry)->client_addr, entry->client_addr) && mac_is_equal_bb((*existing_entry)->bssid_addr, entry->bssid_addr)) { + if (((*existing_entry) != NULL) + && mac_is_equal_bb((*existing_entry)->client_addr, entry->client_addr) + && mac_is_equal_bb((*existing_entry)->bssid_addr, entry->bssid_addr)) { (*existing_entry)->time = expiry; if (inc_counter) (*existing_entry)->counter++; + if (entry->signal) + (*existing_entry)->signal = entry->signal; + + if(entry->ht_capabilities) + (*existing_entry)->ht_capabilities = entry->ht_capabilities; + + if(entry->vht_capabilities) + (*existing_entry)->vht_capabilities = entry->vht_capabilities; + if (save_80211k && entry->rcpi != -1) (*existing_entry)->rcpi = entry->rcpi; @@ -1043,7 +1146,7 @@ probe_entry* insert_to_array(probe_entry* entry, int inc_counter, int save_80211 probe_entry_last++; if (probe_entry_last == PROBE_ARRAY_LEN) { - dawnlog(LOG_INFO, "warning: probe_array overflowing (now contains %d entries)!\n", probe_entry_last); + dawnlog(LOG_INFO,"warning: probe_array overflowing (now contains %d entries)!\n", probe_entry_last); } // Try to keep skip list density stable @@ -1063,10 +1166,11 @@ ap *insert_to_ap_array(ap* entry, time_t expiry) { // TODO: Why do we delete and add here? - ap* old_entry = *ap_array_find_first_entry(entry->bssid_addr); + ap* old_entry = *ap_array_find_first_entry(entry->bssid_addr, entry->ssid); if (old_entry != NULL && - !mac_is_equal_bb((old_entry)->bssid_addr, entry->bssid_addr)) + !mac_is_equal_bb((old_entry)->bssid_addr, entry->bssid_addr) && + !strcmp((char*)old_entry->ssid, (char*)entry->ssid)) old_entry = NULL; if (old_entry != NULL) @@ -1115,15 +1219,15 @@ void ap_array_insert(ap* entry) { ap_entry_last++; if (ap_entry_last == ARRAY_AP_LEN) { - dawnlog(LOG_INFO, "warning: ap_array overflowing (contains %d entries)!\n", ap_entry_last); + dawnlog(LOG_INFO,"warning: ap_array overflowing (contains %d entries)!\n", ap_entry_last); } } -ap* ap_array_get_ap(struct dawn_mac bssid_mac) { +ap* ap_array_get_ap(struct dawn_mac bssid_mac, const uint8_t* ssid) { pthread_mutex_lock(&ap_array_mutex); - ap* ret = *ap_array_find_first_entry(bssid_mac); + ap* ret = *ap_array_find_first_entry(bssid_mac, ssid); pthread_mutex_unlock(&ap_array_mutex); @@ -1205,7 +1309,7 @@ void remove_old_denied_req_entries(time_t current_time, long long int threshold, // client is not connected for a given time threshold! if (logmac && !is_connected_somehwere((*i)->client_addr)) { - dawnlog(LOG_INFO, "Client has probably a bad driver!\n"); + dawnlog(LOG_INFO,"Client has probably a bad driver!\n"); // problem that somehow station will land into this list // maybe delete again? @@ -1292,11 +1396,11 @@ void insert_macs_from_file() { } } - dawnlog(LOG_INFO, "Printing MAC list:\n"); + dawnlog(LOG_INFO,"Printing MAC list:\n"); for (struct mac_entry_s *i = mac_set; i != NULL; i = i->next_mac) { char mac_buf_target[20]; sprintf(mac_buf_target, MACSTR, MAC2STR(i->mac.u8)); - dawnlog(LOG_INFO, "%s\n", mac_buf_target); + dawnlog(LOG_INFO,"%s\n", mac_buf_target); } fclose(fp); @@ -1321,7 +1425,7 @@ struct mac_entry_s** i = mac_find_first_entry(mac); struct mac_entry_s* new_mac = dawn_malloc(sizeof(struct mac_entry_s)); if (new_mac == NULL) { - dawnlog(LOG_INFO, "dawn_malloc of MAC struct failed!\n"); + dawnlog(LOG_INFO,"dawn_malloc of MAC struct failed!\n"); } else { @@ -1375,7 +1479,7 @@ auth_entry* insert_to_denied_req_array(auth_entry* entry, int inc_counter, time_ denied_req_last++; if (denied_req_last == DENY_REQ_ARRAY_LEN) { - dawnlog(LOG_INFO, "warning: denied_req_array overflowing (now contains %d entries)!\n", denied_req_last); + dawnlog(LOG_INFO,"warning: denied_req_array overflowing (now contains %d entries)!\n", denied_req_last); } } @@ -1409,7 +1513,7 @@ struct mac_entry_s* insert_to_mac_array(struct mac_entry_s* entry, struct mac_en mac_set_last++; if (mac_set_last == DENY_REQ_ARRAY_LEN) { - dawnlog(LOG_INFO, "warning: denied_req_array overflowing (now contains %d entries)!\n", mac_set_last); + dawnlog(LOG_INFO,"warning: denied_req_array overflowing (now contains %d entries)!\n", mac_set_last); } return entry; @@ -1431,7 +1535,6 @@ void mac_array_delete(struct mac_entry_s* entry) { } void print_probe_entry(probe_entry *entry) { -#ifndef DAWN_NO_OUTPUT char mac_buf_ap[20]; char mac_buf_client[20]; char mac_buf_target[20]; @@ -1446,11 +1549,9 @@ void print_probe_entry(probe_entry *entry) { "%d, counter: %d, vht: %d, min_rate: %d, max_rate: %d\n", mac_buf_ap, mac_buf_client, entry->signal, entry->freq, entry->counter, entry->vht_capabilities, entry->min_supp_datarate, entry->max_supp_datarate); -#endif } void print_auth_entry(auth_entry *entry) { -#ifndef DAWN_NO_OUTPUT char mac_buf_ap[20]; char mac_buf_client[20]; char mac_buf_target[20]; @@ -1463,51 +1564,46 @@ void print_auth_entry(auth_entry *entry) { "bssid_addr: %s, client_addr: %s, signal: %d, freq: " "%d\n", mac_buf_ap, mac_buf_client, entry->signal, entry->freq); -#endif } void print_client_entry(client *entry) { -#ifndef DAWN_NO_OUTPUT char mac_buf_ap[20]; char mac_buf_client[20]; sprintf(mac_buf_ap, MACSTR, MAC2STR(entry->bssid_addr.u8)); sprintf(mac_buf_client, MACSTR, MAC2STR(entry->client_addr.u8)); - dawnlog(LOG_INFO, "bssid_addr: %s, client_addr: %s, freq: %d, ht_supported: %d, vht_supported: %d, ht: %d, vht: %d, kick: %d\n", + dawnlog(LOG_INFO,"bssid_addr: %s, client_addr: %s, freq: %d, ht_supported: %d, vht_supported: %d, ht: %d, vht: %d, kick: %d\n", mac_buf_ap, mac_buf_client, entry->freq, entry->ht_supported, entry->vht_supported, entry->ht, entry->vht, entry->kick_count); -#endif } void print_client_array() { - dawnlog(LOG_INFO, "--------Clients------\n"); - dawnlog(LOG_INFO, "Client Entry Last: %d\n", client_entry_last); + dawnlog(LOG_INFO,"--------Clients------\n"); + dawnlog(LOG_INFO,"Client Entry Last: %d\n", client_entry_last); for (client* i = client_set_bc; i != NULL; i = i->next_entry_bc) { print_client_entry(i); } - dawnlog(LOG_INFO, "------------------\n"); + dawnlog(LOG_INFO,"------------------\n"); } static void print_ap_entry(ap *entry) { -#ifndef DAWN_NO_OUTPUT char mac_buf_ap[20]; sprintf(mac_buf_ap, MACSTR, MAC2STR(entry->bssid_addr.u8)); - dawnlog(LOG_INFO, "ssid: %s, bssid_addr: %s, freq: %d, ht: %d, vht: %d, chan_utilz: %d, col_d: %d, bandwidth: %d, col_count: %d neighbor_report: %s\n", + dawnlog(LOG_INFO,"ssid: %s, bssid_addr: %s, freq: %d, ht: %d, vht: %d, chan_utilz: %d, col_d: %d, bandwidth: %d, col_count: %d neighbor_report: %s\n", entry->ssid, mac_buf_ap, entry->freq, entry->ht_support, entry->vht_support, entry->channel_utilization, entry->collision_domain, entry->bandwidth, ap_get_collision_count(entry->collision_domain), entry->neighbor_report ); -#endif } void print_ap_array() { - dawnlog(LOG_INFO, "--------APs------\n"); + dawnlog(LOG_INFO,"--------APs------\n"); for (ap *i = ap_set; i != NULL; i = i->next_ap) { print_ap_entry(i); } - dawnlog(LOG_INFO, "------------------\n"); + dawnlog(LOG_INFO,"------------------\n"); } void destroy_mutex() { diff --git a/src/test/kick_deep.script b/src/test/kick_deep.script index 4e89139..242371c 100644 --- a/src/test/kick_deep.script +++ b/src/test/kick_deep.script @@ -8,20 +8,20 @@ dawn max_chan_util=0 dawn ap_weight=4 dawn rssi=32 dawn low_rssi=0 -dawn min_kick_count=1 +dawn min_number_to_kick=1 #AP -ap bssid=0A:7B:AA:00:01:00 ht_sup=1 vht_sup=1 util=156 stations=13 ssid=aTestSSID weight=10 neighbors=0A:7B:AA:00:01:00 -ap bssid=02:67:AA:00:02:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=02:67:AA:00:02:00 -ap bssid=14:02:AA:00:03:00 ht_sup=1 vht_sup=1 util=126 stations=9 ssid=aTestSSID weight=10 neighbors=14:02:AA:00:03:00 -ap bssid=1F:36:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=1F:36:AA:00:04:00 -ap bssid=69:E9:AA:00:05:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=69:E9:AA:00:05:00 -ap bssid=6A:97:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=6A:97:AA:00:06:00 -ap bssid=45:63:AA:00:07:00 ht_sup=0 vht_sup=0 util=55 stations=5 ssid=aTestSSID weight=10 neighbors=45:63:AA:00:07:00 -ap bssid=07:1E:AA:00:08:00 ht_sup=1 vht_sup=1 util=88 stations=8 ssid=aTestSSID weight=10 neighbors=07:1E:AA:00:08:00 -ap bssid=45:A2:AA:00:09:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=45:A2:AA:00:09:00 -ap bssid=4C:4D:AA:00:0A:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=4C:4D:AA:00:0A:00 +ap bssid=0A:7B:AA:00:01:00 ht_sup=1 vht_sup=1 util=156 stations=13 ssid=aTestSSID weight=10 neighbors=0A7BAA000100 +ap bssid=02:67:AA:00:02:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=0267AA000200 +ap bssid=14:02:AA:00:03:00 ht_sup=1 vht_sup=1 util=126 stations=9 ssid=aTestSSID weight=10 neighbors=1402AA000300 +ap bssid=1F:36:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=1F36AA000400 +ap bssid=69:E9:AA:00:05:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=69E9AA000500 +ap bssid=6A:97:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=6A97AA000600 +ap bssid=45:63:AA:00:07:00 ht_sup=0 vht_sup=0 util=55 stations=5 ssid=aTestSSID weight=10 neighbors=4563AA000700 +ap bssid=07:1E:AA:00:08:00 ht_sup=1 vht_sup=1 util=88 stations=8 ssid=aTestSSID weight=10 neighbors=071EAA000800 +ap bssid=45:A2:AA:00:09:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=45A2AA000900 +ap bssid=4C:4D:AA:00:0A:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=4C4DAA000A00 #Client client client=50:7B:DD:00:01:00 bssid=45:A2:AA:00:09:00 freq=2500 ht_cap=1 vht_cap=1 diff --git a/src/test/scale_kick_100_3000_b.script b/src/test/scale_kick_100_3000_b.script index 9779088..09b058c 100644 --- a/src/test/scale_kick_100_3000_b.script +++ b/src/test/scale_kick_100_3000_b.script @@ -8,109 +8,109 @@ dawn max_chan_util=0 dawn ap_weight=4 dawn rssi=32 dawn low_rssi=0 -dawn min_kick_count=1 +dawn min_number_to_kick=1 # AP -ap bssid=20:C9:AA:00:01:00 ht_sup=0 vht_sup=0 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=20:C9:AA:00:01:00 -ap bssid=47:90:AA:00:02:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=47:90:AA:00:02:00 -ap bssid=57:BD:AA:00:03:00 ht_sup=0 vht_sup=0 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=57:BD:AA:00:03:00 -ap bssid=23:0F:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=23:0F:AA:00:04:00 -ap bssid=2C:B9:AA:00:05:00 ht_sup=0 vht_sup=0 util=84 stations=7 ssid=aTestSSID weight=10 neighbors=2C:B9:AA:00:05:00 -ap bssid=73:74:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=73:74:AA:00:06:00 -ap bssid=13:0F:AA:00:07:00 ht_sup=0 vht_sup=0 util=20 stations=2 ssid=aTestSSID weight=10 neighbors=13:0F:AA:00:07:00 -ap bssid=77:C0:AA:00:08:00 ht_sup=0 vht_sup=0 util=196 stations=14 ssid=aTestSSID weight=10 neighbors=77:C0:AA:00:08:00 -ap bssid=16:9D:AA:00:09:00 ht_sup=1 vht_sup=1 util=84 stations=6 ssid=aTestSSID weight=10 neighbors=16:9D:AA:00:09:00 -ap bssid=77:99:AA:00:0A:00 ht_sup=1 vht_sup=0 util=70 stations=7 ssid=aTestSSID weight=10 neighbors=77:99:AA:00:0A:00 -ap bssid=01:D2:AA:00:0B:00 ht_sup=0 vht_sup=0 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=01:D2:AA:00:0B:00 -ap bssid=27:B9:AA:00:0C:00 ht_sup=1 vht_sup=1 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=27:B9:AA:00:0C:00 -ap bssid=59:D5:AA:00:0D:00 ht_sup=0 vht_sup=0 util=105 stations=7 ssid=aTestSSID weight=10 neighbors=59:D5:AA:00:0D:00 -ap bssid=7C:37:AA:00:0E:00 ht_sup=1 vht_sup=1 util=99 stations=9 ssid=aTestSSID weight=10 neighbors=7C:37:AA:00:0E:00 -ap bssid=1D:0F:AA:00:0F:00 ht_sup=0 vht_sup=0 util=210 stations=15 ssid=aTestSSID weight=10 neighbors=1D:0F:AA:00:0F:00 -ap bssid=60:AD:AA:00:10:00 ht_sup=1 vht_sup=1 util=80 stations=8 ssid=aTestSSID weight=10 neighbors=60:AD:AA:00:10:00 -ap bssid=3B:81:AA:00:11:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=3B:81:AA:00:11:00 -ap bssid=6A:1B:AA:00:12:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=6A:1B:AA:00:12:00 -ap bssid=61:D6:AA:00:13:00 ht_sup=1 vht_sup=1 util=28 stations=2 ssid=aTestSSID weight=10 neighbors=61:D6:AA:00:13:00 -ap bssid=5B:F3:AA:00:14:00 ht_sup=1 vht_sup=1 util=24 stations=2 ssid=aTestSSID weight=10 neighbors=5B:F3:AA:00:14:00 -ap bssid=7A:92:AA:00:15:00 ht_sup=0 vht_sup=0 util=105 stations=7 ssid=aTestSSID weight=10 neighbors=7A:92:AA:00:15:00 -ap bssid=3D:08:AA:00:16:00 ht_sup=1 vht_sup=0 util=75 stations=5 ssid=aTestSSID weight=10 neighbors=3D:08:AA:00:16:00 -ap bssid=11:C4:AA:00:17:00 ht_sup=1 vht_sup=1 util=20 stations=2 ssid=aTestSSID weight=10 neighbors=11:C4:AA:00:17:00 -ap bssid=21:01:AA:00:18:00 ht_sup=0 vht_sup=0 util=225 stations=15 ssid=aTestSSID weight=10 neighbors=21:01:AA:00:18:00 -ap bssid=27:35:AA:00:19:00 ht_sup=0 vht_sup=0 util=60 stations=4 ssid=aTestSSID weight=10 neighbors=27:35:AA:00:19:00 -ap bssid=22:44:AA:00:1A:00 ht_sup=1 vht_sup=0 util=90 stations=9 ssid=aTestSSID weight=10 neighbors=22:44:AA:00:1A:00 -ap bssid=1B:18:AA:00:1B:00 ht_sup=1 vht_sup=1 util=90 stations=9 ssid=aTestSSID weight=10 neighbors=1B:18:AA:00:1B:00 -ap bssid=28:6D:AA:00:1C:00 ht_sup=0 vht_sup=0 util=121 stations=11 ssid=aTestSSID weight=10 neighbors=28:6D:AA:00:1C:00 -ap bssid=01:39:AA:00:1D:00 ht_sup=1 vht_sup=1 util=50 stations=5 ssid=aTestSSID weight=10 neighbors=01:39:AA:00:1D:00 -ap bssid=37:35:AA:00:1E:00 ht_sup=1 vht_sup=0 util=90 stations=6 ssid=aTestSSID weight=10 neighbors=37:35:AA:00:1E:00 -ap bssid=46:AF:AA:00:1F:00 ht_sup=0 vht_sup=0 util=26 stations=2 ssid=aTestSSID weight=10 neighbors=46:AF:AA:00:1F:00 -ap bssid=21:ED:AA:00:20:00 ht_sup=0 vht_sup=0 util=132 stations=11 ssid=aTestSSID weight=10 neighbors=21:ED:AA:00:20:00 -ap bssid=36:0C:AA:00:21:00 ht_sup=1 vht_sup=0 util=150 stations=10 ssid=aTestSSID weight=10 neighbors=36:0C:AA:00:21:00 -ap bssid=1F:62:AA:00:22:00 ht_sup=1 vht_sup=0 util=60 stations=4 ssid=aTestSSID weight=10 neighbors=1F:62:AA:00:22:00 -ap bssid=06:08:AA:00:23:00 ht_sup=0 vht_sup=0 util=22 stations=2 ssid=aTestSSID weight=10 neighbors=06:08:AA:00:23:00 -ap bssid=5A:57:AA:00:24:00 ht_sup=1 vht_sup=0 util=165 stations=15 ssid=aTestSSID weight=10 neighbors=5A:57:AA:00:24:00 -ap bssid=3E:BB:AA:00:25:00 ht_sup=1 vht_sup=1 util=112 stations=8 ssid=aTestSSID weight=10 neighbors=3E:BB:AA:00:25:00 -ap bssid=3A:70:AA:00:26:00 ht_sup=0 vht_sup=0 util=15 stations=1 ssid=aTestSSID weight=10 neighbors=3A:70:AA:00:26:00 -ap bssid=61:41:AA:00:27:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=61:41:AA:00:27:00 -ap bssid=41:A1:AA:00:28:00 ht_sup=0 vht_sup=0 util=66 stations=6 ssid=aTestSSID weight=10 neighbors=41:A1:AA:00:28:00 -ap bssid=5D:F5:AA:00:29:00 ht_sup=0 vht_sup=0 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=5D:F5:AA:00:29:00 -ap bssid=7A:24:AA:00:2A:00 ht_sup=0 vht_sup=0 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=7A:24:AA:00:2A:00 -ap bssid=05:18:AA:00:2B:00 ht_sup=1 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=05:18:AA:00:2B:00 -ap bssid=10:E2:AA:00:2C:00 ht_sup=0 vht_sup=0 util=90 stations=6 ssid=aTestSSID weight=10 neighbors=10:E2:AA:00:2C:00 -ap bssid=3E:07:AA:00:2D:00 ht_sup=1 vht_sup=0 util=48 stations=4 ssid=aTestSSID weight=10 neighbors=3E:07:AA:00:2D:00 -ap bssid=58:66:AA:00:2E:00 ht_sup=0 vht_sup=0 util=84 stations=6 ssid=aTestSSID weight=10 neighbors=58:66:AA:00:2E:00 -ap bssid=70:EA:AA:00:2F:00 ht_sup=0 vht_sup=0 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=70:EA:AA:00:2F:00 -ap bssid=10:4F:AA:00:30:00 ht_sup=0 vht_sup=0 util=33 stations=3 ssid=aTestSSID weight=10 neighbors=10:4F:AA:00:30:00 -ap bssid=2E:E0:AA:00:31:00 ht_sup=1 vht_sup=1 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=2E:E0:AA:00:31:00 -ap bssid=6D:3B:AA:00:32:00 ht_sup=0 vht_sup=0 util=33 stations=3 ssid=aTestSSID weight=10 neighbors=6D:3B:AA:00:32:00 -ap bssid=44:B5:AA:00:33:00 ht_sup=1 vht_sup=1 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=44:B5:AA:00:33:00 -ap bssid=7D:3D:AA:00:34:00 ht_sup=1 vht_sup=1 util=72 stations=6 ssid=aTestSSID weight=10 neighbors=7D:3D:AA:00:34:00 -ap bssid=04:0E:AA:00:35:00 ht_sup=1 vht_sup=0 util=195 stations=15 ssid=aTestSSID weight=10 neighbors=04:0E:AA:00:35:00 -ap bssid=24:C9:AA:00:36:00 ht_sup=1 vht_sup=0 util=52 stations=4 ssid=aTestSSID weight=10 neighbors=24:C9:AA:00:36:00 -ap bssid=2F:19:AA:00:37:00 ht_sup=0 vht_sup=0 util=75 stations=5 ssid=aTestSSID weight=10 neighbors=2F:19:AA:00:37:00 -ap bssid=10:24:AA:00:38:00 ht_sup=0 vht_sup=0 util=105 stations=7 ssid=aTestSSID weight=10 neighbors=10:24:AA:00:38:00 -ap bssid=12:BE:AA:00:39:00 ht_sup=1 vht_sup=0 util=143 stations=13 ssid=aTestSSID weight=10 neighbors=12:BE:AA:00:39:00 -ap bssid=15:56:AA:00:3A:00 ht_sup=0 vht_sup=0 util=52 stations=4 ssid=aTestSSID weight=10 neighbors=15:56:AA:00:3A:00 -ap bssid=7B:52:AA:00:3B:00 ht_sup=0 vht_sup=0 util=140 stations=14 ssid=aTestSSID weight=10 neighbors=7B:52:AA:00:3B:00 -ap bssid=22:99:AA:00:3C:00 ht_sup=1 vht_sup=0 util=154 stations=11 ssid=aTestSSID weight=10 neighbors=22:99:AA:00:3C:00 -ap bssid=4F:BF:AA:00:3D:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=4F:BF:AA:00:3D:00 -ap bssid=75:49:AA:00:3E:00 ht_sup=1 vht_sup=0 util=30 stations=2 ssid=aTestSSID weight=10 neighbors=75:49:AA:00:3E:00 -ap bssid=3F:3E:AA:00:3F:00 ht_sup=1 vht_sup=1 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=3F:3E:AA:00:3F:00 -ap bssid=75:52:AA:00:40:00 ht_sup=0 vht_sup=0 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=75:52:AA:00:40:00 -ap bssid=0D:7F:AA:00:41:00 ht_sup=1 vht_sup=1 util=143 stations=13 ssid=aTestSSID weight=10 neighbors=0D:7F:AA:00:41:00 -ap bssid=31:26:AA:00:42:00 ht_sup=1 vht_sup=1 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=31:26:AA:00:42:00 -ap bssid=29:5C:AA:00:43:00 ht_sup=0 vht_sup=0 util=48 stations=4 ssid=aTestSSID weight=10 neighbors=29:5C:AA:00:43:00 -ap bssid=16:26:AA:00:44:00 ht_sup=0 vht_sup=0 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=16:26:AA:00:44:00 -ap bssid=5A:0B:AA:00:45:00 ht_sup=1 vht_sup=1 util=22 stations=2 ssid=aTestSSID weight=10 neighbors=5A:0B:AA:00:45:00 -ap bssid=21:95:AA:00:46:00 ht_sup=0 vht_sup=0 util=182 stations=13 ssid=aTestSSID weight=10 neighbors=21:95:AA:00:46:00 -ap bssid=6E:CA:AA:00:47:00 ht_sup=0 vht_sup=0 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=6E:CA:AA:00:47:00 -ap bssid=66:09:AA:00:48:00 ht_sup=0 vht_sup=0 util=121 stations=11 ssid=aTestSSID weight=10 neighbors=66:09:AA:00:48:00 -ap bssid=7D:12:AA:00:49:00 ht_sup=0 vht_sup=0 util=140 stations=10 ssid=aTestSSID weight=10 neighbors=7D:12:AA:00:49:00 -ap bssid=61:5A:AA:00:4A:00 ht_sup=0 vht_sup=0 util=150 stations=15 ssid=aTestSSID weight=10 neighbors=61:5A:AA:00:4A:00 -ap bssid=59:46:AA:00:4B:00 ht_sup=1 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=59:46:AA:00:4B:00 -ap bssid=3F:13:AA:00:4C:00 ht_sup=1 vht_sup=1 util=22 stations=2 ssid=aTestSSID weight=10 neighbors=3F:13:AA:00:4C:00 -ap bssid=15:E2:AA:00:4D:00 ht_sup=1 vht_sup=0 util=60 stations=5 ssid=aTestSSID weight=10 neighbors=15:E2:AA:00:4D:00 -ap bssid=43:5D:AA:00:4E:00 ht_sup=1 vht_sup=1 util=11 stations=1 ssid=aTestSSID weight=10 neighbors=43:5D:AA:00:4E:00 -ap bssid=75:2D:AA:00:4F:00 ht_sup=0 vht_sup=0 util=91 stations=7 ssid=aTestSSID weight=10 neighbors=75:2D:AA:00:4F:00 -ap bssid=3A:78:AA:00:50:00 ht_sup=0 vht_sup=0 util=225 stations=15 ssid=aTestSSID weight=10 neighbors=3A:78:AA:00:50:00 -ap bssid=59:68:AA:00:51:00 ht_sup=0 vht_sup=0 util=182 stations=14 ssid=aTestSSID weight=10 neighbors=59:68:AA:00:51:00 -ap bssid=68:A3:AA:00:52:00 ht_sup=0 vht_sup=0 util=99 stations=9 ssid=aTestSSID weight=10 neighbors=68:A3:AA:00:52:00 -ap bssid=5F:7D:AA:00:53:00 ht_sup=1 vht_sup=0 util=50 stations=5 ssid=aTestSSID weight=10 neighbors=5F:7D:AA:00:53:00 -ap bssid=16:90:AA:00:54:00 ht_sup=1 vht_sup=0 util=70 stations=5 ssid=aTestSSID weight=10 neighbors=16:90:AA:00:54:00 -ap bssid=70:32:AA:00:55:00 ht_sup=1 vht_sup=1 util=195 stations=15 ssid=aTestSSID weight=10 neighbors=70:32:AA:00:55:00 -ap bssid=76:52:AA:00:56:00 ht_sup=1 vht_sup=1 util=143 stations=11 ssid=aTestSSID weight=10 neighbors=76:52:AA:00:56:00 -ap bssid=33:D6:AA:00:57:00 ht_sup=0 vht_sup=0 util=39 stations=3 ssid=aTestSSID weight=10 neighbors=33:D6:AA:00:57:00 -ap bssid=3C:D0:AA:00:58:00 ht_sup=0 vht_sup=0 util=165 stations=11 ssid=aTestSSID weight=10 neighbors=3C:D0:AA:00:58:00 -ap bssid=74:70:AA:00:59:00 ht_sup=0 vht_sup=0 util=135 stations=9 ssid=aTestSSID weight=10 neighbors=74:70:AA:00:59:00 -ap bssid=6B:B1:AA:00:5A:00 ht_sup=0 vht_sup=0 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=6B:B1:AA:00:5A:00 -ap bssid=1A:74:AA:00:5B:00 ht_sup=1 vht_sup=0 util=182 stations=13 ssid=aTestSSID weight=10 neighbors=1A:74:AA:00:5B:00 -ap bssid=67:CE:AA:00:5C:00 ht_sup=1 vht_sup=1 util=15 stations=1 ssid=aTestSSID weight=10 neighbors=67:CE:AA:00:5C:00 -ap bssid=0F:EE:AA:00:5D:00 ht_sup=1 vht_sup=0 util=156 stations=12 ssid=aTestSSID weight=10 neighbors=0F:EE:AA:00:5D:00 -ap bssid=18:24:AA:00:5E:00 ht_sup=1 vht_sup=0 util=132 stations=11 ssid=aTestSSID weight=10 neighbors=18:24:AA:00:5E:00 -ap bssid=76:35:AA:00:5F:00 ht_sup=1 vht_sup=0 util=60 stations=4 ssid=aTestSSID weight=10 neighbors=76:35:AA:00:5F:00 -ap bssid=69:40:AA:00:60:00 ht_sup=0 vht_sup=0 util=180 stations=12 ssid=aTestSSID weight=10 neighbors=69:40:AA:00:60:00 -ap bssid=3A:1A:AA:00:61:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=3A:1A:AA:00:61:00 -ap bssid=31:32:AA:00:62:00 ht_sup=1 vht_sup=1 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=31:32:AA:00:62:00 -ap bssid=32:98:AA:00:63:00 ht_sup=0 vht_sup=0 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=32:98:AA:00:63:00 -ap bssid=0F:FC:AA:00:64:00 ht_sup=1 vht_sup=0 util=26 stations=2 ssid=aTestSSID weight=10 neighbors=0F:FC:AA:00:64:00 +ap bssid=20:C9:AA:00:01:00 ht_sup=0 vht_sup=0 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=20C9AA000100 +ap bssid=47:90:AA:00:02:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=4790AA000200 +ap bssid=57:BD:AA:00:03:00 ht_sup=0 vht_sup=0 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=57BDAA000300 +ap bssid=23:0F:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=230FAA000400 +ap bssid=2C:B9:AA:00:05:00 ht_sup=0 vht_sup=0 util=84 stations=7 ssid=aTestSSID weight=10 neighbors=2CB9AA000500 +ap bssid=73:74:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=7374AA000600 +ap bssid=13:0F:AA:00:07:00 ht_sup=0 vht_sup=0 util=20 stations=2 ssid=aTestSSID weight=10 neighbors=130FAA000700 +ap bssid=77:C0:AA:00:08:00 ht_sup=0 vht_sup=0 util=196 stations=14 ssid=aTestSSID weight=10 neighbors=77C0AA000800 +ap bssid=16:9D:AA:00:09:00 ht_sup=1 vht_sup=1 util=84 stations=6 ssid=aTestSSID weight=10 neighbors=169DAA000900 +ap bssid=77:99:AA:00:0A:00 ht_sup=1 vht_sup=0 util=70 stations=7 ssid=aTestSSID weight=10 neighbors=7799AA000A00 +ap bssid=01:D2:AA:00:0B:00 ht_sup=0 vht_sup=0 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=01D2AA000B00 +ap bssid=27:B9:AA:00:0C:00 ht_sup=1 vht_sup=1 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=27B9AA000C00 +ap bssid=59:D5:AA:00:0D:00 ht_sup=0 vht_sup=0 util=105 stations=7 ssid=aTestSSID weight=10 neighbors=59D5AA000D00 +ap bssid=7C:37:AA:00:0E:00 ht_sup=1 vht_sup=1 util=99 stations=9 ssid=aTestSSID weight=10 neighbors=7C37AA000E00 +ap bssid=1D:0F:AA:00:0F:00 ht_sup=0 vht_sup=0 util=210 stations=15 ssid=aTestSSID weight=10 neighbors=1D0FAA000F00 +ap bssid=60:AD:AA:00:10:00 ht_sup=1 vht_sup=1 util=80 stations=8 ssid=aTestSSID weight=10 neighbors=60ADAA001000 +ap bssid=3B:81:AA:00:11:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=3B81AA001100 +ap bssid=6A:1B:AA:00:12:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=6A1BAA001200 +ap bssid=61:D6:AA:00:13:00 ht_sup=1 vht_sup=1 util=28 stations=2 ssid=aTestSSID weight=10 neighbors=61D6AA001300 +ap bssid=5B:F3:AA:00:14:00 ht_sup=1 vht_sup=1 util=24 stations=2 ssid=aTestSSID weight=10 neighbors=5BF3AA001400 +ap bssid=7A:92:AA:00:15:00 ht_sup=0 vht_sup=0 util=105 stations=7 ssid=aTestSSID weight=10 neighbors=7A92AA001500 +ap bssid=3D:08:AA:00:16:00 ht_sup=1 vht_sup=0 util=75 stations=5 ssid=aTestSSID weight=10 neighbors=3D08AA001600 +ap bssid=11:C4:AA:00:17:00 ht_sup=1 vht_sup=1 util=20 stations=2 ssid=aTestSSID weight=10 neighbors=11C4AA001700 +ap bssid=21:01:AA:00:18:00 ht_sup=0 vht_sup=0 util=225 stations=15 ssid=aTestSSID weight=10 neighbors=2101AA001800 +ap bssid=27:35:AA:00:19:00 ht_sup=0 vht_sup=0 util=60 stations=4 ssid=aTestSSID weight=10 neighbors=2735AA001900 +ap bssid=22:44:AA:00:1A:00 ht_sup=1 vht_sup=0 util=90 stations=9 ssid=aTestSSID weight=10 neighbors=2244AA001A00 +ap bssid=1B:18:AA:00:1B:00 ht_sup=1 vht_sup=1 util=90 stations=9 ssid=aTestSSID weight=10 neighbors=1B18AA001B00 +ap bssid=28:6D:AA:00:1C:00 ht_sup=0 vht_sup=0 util=121 stations=11 ssid=aTestSSID weight=10 neighbors=286DAA001C00 +ap bssid=01:39:AA:00:1D:00 ht_sup=1 vht_sup=1 util=50 stations=5 ssid=aTestSSID weight=10 neighbors=0139AA001D00 +ap bssid=37:35:AA:00:1E:00 ht_sup=1 vht_sup=0 util=90 stations=6 ssid=aTestSSID weight=10 neighbors=3735AA001E00 +ap bssid=46:AF:AA:00:1F:00 ht_sup=0 vht_sup=0 util=26 stations=2 ssid=aTestSSID weight=10 neighbors=46AFAA001F00 +ap bssid=21:ED:AA:00:20:00 ht_sup=0 vht_sup=0 util=132 stations=11 ssid=aTestSSID weight=10 neighbors=21EDAA002000 +ap bssid=36:0C:AA:00:21:00 ht_sup=1 vht_sup=0 util=150 stations=10 ssid=aTestSSID weight=10 neighbors=360CAA002100 +ap bssid=1F:62:AA:00:22:00 ht_sup=1 vht_sup=0 util=60 stations=4 ssid=aTestSSID weight=10 neighbors=1F62AA002200 +ap bssid=06:08:AA:00:23:00 ht_sup=0 vht_sup=0 util=22 stations=2 ssid=aTestSSID weight=10 neighbors=0608AA002300 +ap bssid=5A:57:AA:00:24:00 ht_sup=1 vht_sup=0 util=165 stations=15 ssid=aTestSSID weight=10 neighbors=5A57AA002400 +ap bssid=3E:BB:AA:00:25:00 ht_sup=1 vht_sup=1 util=112 stations=8 ssid=aTestSSID weight=10 neighbors=3EBBAA002500 +ap bssid=3A:70:AA:00:26:00 ht_sup=0 vht_sup=0 util=15 stations=1 ssid=aTestSSID weight=10 neighbors=3A70AA002600 +ap bssid=61:41:AA:00:27:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=6141AA002700 +ap bssid=41:A1:AA:00:28:00 ht_sup=0 vht_sup=0 util=66 stations=6 ssid=aTestSSID weight=10 neighbors=41A1AA002800 +ap bssid=5D:F5:AA:00:29:00 ht_sup=0 vht_sup=0 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=5DF5AA002900 +ap bssid=7A:24:AA:00:2A:00 ht_sup=0 vht_sup=0 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=7A24AA002A00 +ap bssid=05:18:AA:00:2B:00 ht_sup=1 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=0518AA002B00 +ap bssid=10:E2:AA:00:2C:00 ht_sup=0 vht_sup=0 util=90 stations=6 ssid=aTestSSID weight=10 neighbors=10E2AA002C00 +ap bssid=3E:07:AA:00:2D:00 ht_sup=1 vht_sup=0 util=48 stations=4 ssid=aTestSSID weight=10 neighbors=3E07AA002D00 +ap bssid=58:66:AA:00:2E:00 ht_sup=0 vht_sup=0 util=84 stations=6 ssid=aTestSSID weight=10 neighbors=5866AA002E00 +ap bssid=70:EA:AA:00:2F:00 ht_sup=0 vht_sup=0 util=98 stations=7 ssid=aTestSSID weight=10 neighbors=70EAAA002F00 +ap bssid=10:4F:AA:00:30:00 ht_sup=0 vht_sup=0 util=33 stations=3 ssid=aTestSSID weight=10 neighbors=104FAA003000 +ap bssid=2E:E0:AA:00:31:00 ht_sup=1 vht_sup=1 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=2EE0AA003100 +ap bssid=6D:3B:AA:00:32:00 ht_sup=0 vht_sup=0 util=33 stations=3 ssid=aTestSSID weight=10 neighbors=6D3BAA003200 +ap bssid=44:B5:AA:00:33:00 ht_sup=1 vht_sup=1 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=44B5AA003300 +ap bssid=7D:3D:AA:00:34:00 ht_sup=1 vht_sup=1 util=72 stations=6 ssid=aTestSSID weight=10 neighbors=7D3DAA003400 +ap bssid=04:0E:AA:00:35:00 ht_sup=1 vht_sup=0 util=195 stations=15 ssid=aTestSSID weight=10 neighbors=040EAA003500 +ap bssid=24:C9:AA:00:36:00 ht_sup=1 vht_sup=0 util=52 stations=4 ssid=aTestSSID weight=10 neighbors=24C9AA003600 +ap bssid=2F:19:AA:00:37:00 ht_sup=0 vht_sup=0 util=75 stations=5 ssid=aTestSSID weight=10 neighbors=2F19AA003700 +ap bssid=10:24:AA:00:38:00 ht_sup=0 vht_sup=0 util=105 stations=7 ssid=aTestSSID weight=10 neighbors=1024AA003800 +ap bssid=12:BE:AA:00:39:00 ht_sup=1 vht_sup=0 util=143 stations=13 ssid=aTestSSID weight=10 neighbors=12BEAA003900 +ap bssid=15:56:AA:00:3A:00 ht_sup=0 vht_sup=0 util=52 stations=4 ssid=aTestSSID weight=10 neighbors=1556AA003A00 +ap bssid=7B:52:AA:00:3B:00 ht_sup=0 vht_sup=0 util=140 stations=14 ssid=aTestSSID weight=10 neighbors=7B52AA003B00 +ap bssid=22:99:AA:00:3C:00 ht_sup=1 vht_sup=0 util=154 stations=11 ssid=aTestSSID weight=10 neighbors=2299AA003C00 +ap bssid=4F:BF:AA:00:3D:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=4FBFAA003D00 +ap bssid=75:49:AA:00:3E:00 ht_sup=1 vht_sup=0 util=30 stations=2 ssid=aTestSSID weight=10 neighbors=7549AA003E00 +ap bssid=3F:3E:AA:00:3F:00 ht_sup=1 vht_sup=1 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=3F3EAA003F00 +ap bssid=75:52:AA:00:40:00 ht_sup=0 vht_sup=0 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=7552AA004000 +ap bssid=0D:7F:AA:00:41:00 ht_sup=1 vht_sup=1 util=143 stations=13 ssid=aTestSSID weight=10 neighbors=0D7FAA004100 +ap bssid=31:26:AA:00:42:00 ht_sup=1 vht_sup=1 util=100 stations=10 ssid=aTestSSID weight=10 neighbors=3126AA004200 +ap bssid=29:5C:AA:00:43:00 ht_sup=0 vht_sup=0 util=48 stations=4 ssid=aTestSSID weight=10 neighbors=295CAA004300 +ap bssid=16:26:AA:00:44:00 ht_sup=0 vht_sup=0 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=1626AA004400 +ap bssid=5A:0B:AA:00:45:00 ht_sup=1 vht_sup=1 util=22 stations=2 ssid=aTestSSID weight=10 neighbors=5A0BAA004500 +ap bssid=21:95:AA:00:46:00 ht_sup=0 vht_sup=0 util=182 stations=13 ssid=aTestSSID weight=10 neighbors=2195AA004600 +ap bssid=6E:CA:AA:00:47:00 ht_sup=0 vht_sup=0 util=120 stations=10 ssid=aTestSSID weight=10 neighbors=6ECAAA004700 +ap bssid=66:09:AA:00:48:00 ht_sup=0 vht_sup=0 util=121 stations=11 ssid=aTestSSID weight=10 neighbors=6609AA004800 +ap bssid=7D:12:AA:00:49:00 ht_sup=0 vht_sup=0 util=140 stations=10 ssid=aTestSSID weight=10 neighbors=7D12AA004900 +ap bssid=61:5A:AA:00:4A:00 ht_sup=0 vht_sup=0 util=150 stations=15 ssid=aTestSSID weight=10 neighbors=615AAA004A00 +ap bssid=59:46:AA:00:4B:00 ht_sup=1 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=5946AA004B00 +ap bssid=3F:13:AA:00:4C:00 ht_sup=1 vht_sup=1 util=22 stations=2 ssid=aTestSSID weight=10 neighbors=3F13AA004C00 +ap bssid=15:E2:AA:00:4D:00 ht_sup=1 vht_sup=0 util=60 stations=5 ssid=aTestSSID weight=10 neighbors=15E2AA004D00 +ap bssid=43:5D:AA:00:4E:00 ht_sup=1 vht_sup=1 util=11 stations=1 ssid=aTestSSID weight=10 neighbors=435DAA004E00 +ap bssid=75:2D:AA:00:4F:00 ht_sup=0 vht_sup=0 util=91 stations=7 ssid=aTestSSID weight=10 neighbors=752DAA004F00 +ap bssid=3A:78:AA:00:50:00 ht_sup=0 vht_sup=0 util=225 stations=15 ssid=aTestSSID weight=10 neighbors=3A78AA005000 +ap bssid=59:68:AA:00:51:00 ht_sup=0 vht_sup=0 util=182 stations=14 ssid=aTestSSID weight=10 neighbors=5968AA005100 +ap bssid=68:A3:AA:00:52:00 ht_sup=0 vht_sup=0 util=99 stations=9 ssid=aTestSSID weight=10 neighbors=68A3AA005200 +ap bssid=5F:7D:AA:00:53:00 ht_sup=1 vht_sup=0 util=50 stations=5 ssid=aTestSSID weight=10 neighbors=5F7DAA005300 +ap bssid=16:90:AA:00:54:00 ht_sup=1 vht_sup=0 util=70 stations=5 ssid=aTestSSID weight=10 neighbors=1690AA005400 +ap bssid=70:32:AA:00:55:00 ht_sup=1 vht_sup=1 util=195 stations=15 ssid=aTestSSID weight=10 neighbors=7032AA005500 +ap bssid=76:52:AA:00:56:00 ht_sup=1 vht_sup=1 util=143 stations=11 ssid=aTestSSID weight=10 neighbors=7652AA005600 +ap bssid=33:D6:AA:00:57:00 ht_sup=0 vht_sup=0 util=39 stations=3 ssid=aTestSSID weight=10 neighbors=33D6AA005700 +ap bssid=3C:D0:AA:00:58:00 ht_sup=0 vht_sup=0 util=165 stations=11 ssid=aTestSSID weight=10 neighbors=3CD0AA005800 +ap bssid=74:70:AA:00:59:00 ht_sup=0 vht_sup=0 util=135 stations=9 ssid=aTestSSID weight=10 neighbors=7470AA005900 +ap bssid=6B:B1:AA:00:5A:00 ht_sup=0 vht_sup=0 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=6BB1AA005A00 +ap bssid=1A:74:AA:00:5B:00 ht_sup=1 vht_sup=0 util=182 stations=13 ssid=aTestSSID weight=10 neighbors=1A74AA005B00 +ap bssid=67:CE:AA:00:5C:00 ht_sup=1 vht_sup=1 util=15 stations=1 ssid=aTestSSID weight=10 neighbors=67CEAA005C00 +ap bssid=0F:EE:AA:00:5D:00 ht_sup=1 vht_sup=0 util=156 stations=12 ssid=aTestSSID weight=10 neighbors=0FEEAA005D00 +ap bssid=18:24:AA:00:5E:00 ht_sup=1 vht_sup=0 util=132 stations=11 ssid=aTestSSID weight=10 neighbors=1824AA005E00 +ap bssid=76:35:AA:00:5F:00 ht_sup=1 vht_sup=0 util=60 stations=4 ssid=aTestSSID weight=10 neighbors=7635AA005F00 +ap bssid=69:40:AA:00:60:00 ht_sup=0 vht_sup=0 util=180 stations=12 ssid=aTestSSID weight=10 neighbors=6940AA006000 +ap bssid=3A:1A:AA:00:61:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=3A1AAA006100 +ap bssid=31:32:AA:00:62:00 ht_sup=1 vht_sup=1 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=3132AA006200 +ap bssid=32:98:AA:00:63:00 ht_sup=0 vht_sup=0 util=65 stations=5 ssid=aTestSSID weight=10 neighbors=3298AA006300 +ap bssid=0F:FC:AA:00:64:00 ht_sup=1 vht_sup=0 util=26 stations=2 ssid=aTestSSID weight=10 neighbors=0FFCAA006400 # Device diff --git a/src/test/scale_test_A.script b/src/test/scale_test_A.script index 4e89139..242371c 100644 --- a/src/test/scale_test_A.script +++ b/src/test/scale_test_A.script @@ -8,20 +8,20 @@ dawn max_chan_util=0 dawn ap_weight=4 dawn rssi=32 dawn low_rssi=0 -dawn min_kick_count=1 +dawn min_number_to_kick=1 #AP -ap bssid=0A:7B:AA:00:01:00 ht_sup=1 vht_sup=1 util=156 stations=13 ssid=aTestSSID weight=10 neighbors=0A:7B:AA:00:01:00 -ap bssid=02:67:AA:00:02:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=02:67:AA:00:02:00 -ap bssid=14:02:AA:00:03:00 ht_sup=1 vht_sup=1 util=126 stations=9 ssid=aTestSSID weight=10 neighbors=14:02:AA:00:03:00 -ap bssid=1F:36:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=1F:36:AA:00:04:00 -ap bssid=69:E9:AA:00:05:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=69:E9:AA:00:05:00 -ap bssid=6A:97:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=6A:97:AA:00:06:00 -ap bssid=45:63:AA:00:07:00 ht_sup=0 vht_sup=0 util=55 stations=5 ssid=aTestSSID weight=10 neighbors=45:63:AA:00:07:00 -ap bssid=07:1E:AA:00:08:00 ht_sup=1 vht_sup=1 util=88 stations=8 ssid=aTestSSID weight=10 neighbors=07:1E:AA:00:08:00 -ap bssid=45:A2:AA:00:09:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=45:A2:AA:00:09:00 -ap bssid=4C:4D:AA:00:0A:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=4C:4D:AA:00:0A:00 +ap bssid=0A:7B:AA:00:01:00 ht_sup=1 vht_sup=1 util=156 stations=13 ssid=aTestSSID weight=10 neighbors=0A7BAA000100 +ap bssid=02:67:AA:00:02:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=0267AA000200 +ap bssid=14:02:AA:00:03:00 ht_sup=1 vht_sup=1 util=126 stations=9 ssid=aTestSSID weight=10 neighbors=1402AA000300 +ap bssid=1F:36:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=1F36AA000400 +ap bssid=69:E9:AA:00:05:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=69E9AA000500 +ap bssid=6A:97:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=6A97AA000600 +ap bssid=45:63:AA:00:07:00 ht_sup=0 vht_sup=0 util=55 stations=5 ssid=aTestSSID weight=10 neighbors=4563AA000700 +ap bssid=07:1E:AA:00:08:00 ht_sup=1 vht_sup=1 util=88 stations=8 ssid=aTestSSID weight=10 neighbors=071EAA000800 +ap bssid=45:A2:AA:00:09:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=45A2AA000900 +ap bssid=4C:4D:AA:00:0A:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=4C4DAA000A00 #Client client client=50:7B:DD:00:01:00 bssid=45:A2:AA:00:09:00 freq=2500 ht_cap=1 vht_cap=1 diff --git a/src/test/simple_kick.script b/src/test/simple_kick.script index eaf9165..586e8ed 100644 --- a/src/test/simple_kick.script +++ b/src/test/simple_kick.script @@ -1,7 +1,7 @@ dawn default -dawn min_kick_count=2 -ap bssid=11:22:33:44:55:66 neighbors=11:22:33:44:55:66 -ap bssid=22:33:44:55:66:77 neighbors=22:33:44:55:66:77 +dawn min_number_to_kick=2 +ap bssid=11:22:33:44:55:66 neighbors=112233445566 +ap bssid=22:33:44:55:66:77 neighbors=223344556677 client bssid=11:22:33:44:55:66 client=ff:ee:dd:cc:bb:aa ap_show client_show diff --git a/src/test/test_storage.c b/src/test/test_storage.c index d9af69e..2eca7ce 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, ap *a, int id) { printf("send_beacon_report() was called...\n"); } @@ -22,20 +22,25 @@ int send_set_probe(struct dawn_mac client_addr) return 0; } -int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, char* dest_ap, uint32_t duration) +int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, uint32_t duration) { int ret = 0; printf("wnm_disassoc_imminent() was called...\n"); - if (dest_ap != NULL) + if (neighbor_list != NULL) { // Fake a client being disassociated and then rejoining on the recommended neoghbor client *mc = client_array_get_client(client_addr); mc = client_array_delete(mc, true); - hwaddr_aton(dest_ap, mc->bssid_addr.u8); + // Originally, there was only one AP, not a list of them; that AP is at the tail of the list + // Use it to keep the results the same as before + while (neighbor_list && neighbor_list->next) + neighbor_list = neighbor_list->next; + for (int n=0; n < ETH_ALEN; n++) + sscanf(neighbor_list->nr + n*2, "%2hhx", mc->bssid_addr.u8 + n); insert_client_to_array(mc, 0); - printf("BSS TRANSITION TO %s\n", dest_ap); + printf("BSS TRANSITION TO " NR_MACSTR "\n", NR_MAC2STR(neighbor_list->nr)); // Tell caller not to change the arrays any further ret = 1; @@ -148,8 +153,8 @@ static int array_auto_helper(int action, int i0, int i1) while (cont) { struct dawn_mac this_mac; - *((uint64_t*)(&this_mac.u8)) = 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) { case HELPER_AP: @@ -170,7 +175,7 @@ static int array_auto_helper(int action, int i0, int i1) time_moves_on(); } else - ap_array_delete(ap_array_get_ap(this_mac)); + ap_array_delete(ap_array_get_ap(this_mac, NULL)); break; case HELPER_CLIENT: ; // Empty statement to allow label before declaration @@ -296,6 +301,15 @@ static int load_int(int* v, char* s) return ret; } +static int load_int_band(int* v, char* s); +static int load_int_band(int* v, char* s) +{ + int ret = 0; + sscanf(s, "%" "d", v); + v[1] = v[0]; + return ret; +} + static int load_string(size_t l, char* v, char* s); static int load_string(size_t l, char* v, char* s) { @@ -320,6 +334,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) @@ -597,20 +649,34 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) if (!strcmp(fn, "default")) { - dawn_metric.ap_weight = 0; // Sum component - dawn_metric.ht_support = 10; // Sum component - dawn_metric.vht_support = 100; // Sum component - dawn_metric.no_ht_support = 0; // Sum component - dawn_metric.no_vht_support = 0; // Sum component - dawn_metric.rssi = 10; // Sum component - dawn_metric.low_rssi = -500; // Sum component - dawn_metric.freq = 100; // Sum component - dawn_metric.chan_util = 0; // Sum component - dawn_metric.max_chan_util = -500; // Sum component - dawn_metric.rssi_val = -60; - dawn_metric.low_rssi_val = -80; - dawn_metric.chan_util_val = 140; - dawn_metric.max_chan_util_val = 170; + dawn_metric.ap_weight[0] = 0; // Sum component + dawn_metric.ap_weight[1] = 0; // Sum component + dawn_metric.ht_support[0] = 10; // Sum component + dawn_metric.ht_support[1] = 10; // Sum component + dawn_metric.vht_support[0] = 100; // Sum component + dawn_metric.vht_support[1] = 100; // Sum component + dawn_metric.no_ht_support[0] = 0; // Sum component + dawn_metric.no_ht_support[1] = 0; // Sum component + dawn_metric.no_vht_support[0] = 0; // Sum component + dawn_metric.no_vht_support[1] = 0; // Sum component + dawn_metric.rssi[0] = 10; // Sum component + dawn_metric.rssi[1] = 10; // Sum component + dawn_metric.low_rssi[0] = -500; // Sum component + dawn_metric.low_rssi[1] = -500; // Sum component + dawn_metric.initial_score[0] = 0; // Sum component + dawn_metric.initial_score[1] = 100; // Sum component + dawn_metric.chan_util[0] = 0; // Sum component + dawn_metric.chan_util[1] = 0; // Sum component + dawn_metric.max_chan_util[0] = -500; // Sum component + dawn_metric.max_chan_util[1] = -500; // Sum component + dawn_metric.rssi_val[0] = -60; + dawn_metric.rssi_val[1] = -60; + dawn_metric.low_rssi_val[0] = -80; + dawn_metric.low_rssi_val[1] = -80; + dawn_metric.chan_util_val[0] = 140; + dawn_metric.chan_util_val[1] = 140; + dawn_metric.max_chan_util_val[0] = 170; + dawn_metric.max_chan_util_val[1] = 170; dawn_metric.min_probe_count = 2; dawn_metric.bandwidth_threshold = 6; dawn_metric.use_station_count = 1; @@ -621,29 +687,32 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) dawn_metric.deny_auth_reason = 1; dawn_metric.deny_assoc_reason = 17; dawn_metric.use_driver_recog = 1; - dawn_metric.min_kick_count = 3; + dawn_metric.min_number_to_kick = 3; dawn_metric.chan_util_avg_period = 3; dawn_metric.set_hostapd_nr = 1; dawn_metric.kicking = 0; - dawn_metric.op_class = 0; dawn_metric.duration = 0; - dawn_metric.mode = 0; - dawn_metric.scan_channel = 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; } - else if (!strncmp(fn, "ap_weight=", 10)) load_int(&dawn_metric.ap_weight, fn + 10); - else if (!strncmp(fn, "ht_support=", 11)) load_int(&dawn_metric.ht_support, fn + 11); - else if (!strncmp(fn, "vht_support=", 12)) load_int(&dawn_metric.vht_support, fn + 12); - else if (!strncmp(fn, "no_ht_support=", 14)) load_int(&dawn_metric.no_ht_support, fn + 14); - else if (!strncmp(fn, "no_vht_support=", 15)) load_int(&dawn_metric.no_vht_support, fn + 15); - else if (!strncmp(fn, "rssi=", 5)) load_int(&dawn_metric.rssi, fn + 5); - else if (!strncmp(fn, "low_rssi=", 9)) load_int(&dawn_metric.low_rssi, fn + 9); - else if (!strncmp(fn, "freq=", 5)) load_int(&dawn_metric.freq, fn + 5); - else if (!strncmp(fn, "chan_util=", 10)) load_int(&dawn_metric.chan_util, fn + 10); - else if (!strncmp(fn, "max_chan_util=", 14)) load_int(&dawn_metric.max_chan_util, fn + 14); - else if (!strncmp(fn, "rssi_val=", 9)) load_int(&dawn_metric.rssi_val, fn + 9); - else if (!strncmp(fn, "low_rssi_val=", 13)) load_int(&dawn_metric.low_rssi_val, fn + 13); - else if (!strncmp(fn, "chan_util_val=", 14)) load_int(&dawn_metric.chan_util_val, fn + 14); - else if (!strncmp(fn, "max_chan_util_val=", 18)) load_int(&dawn_metric.max_chan_util_val, fn + 18); + else if (!strncmp(fn, "ap_weight=", 10)) load_int_band(dawn_metric.ap_weight, fn + 10); + else if (!strncmp(fn, "ht_support=", 11)) load_int_band(dawn_metric.ht_support, fn + 11); + else if (!strncmp(fn, "vht_support=", 12)) load_int_band(dawn_metric.vht_support, fn + 12); + else if (!strncmp(fn, "no_ht_support=", 14)) load_int_band(dawn_metric.no_ht_support, fn + 14); + else if (!strncmp(fn, "no_vht_support=", 15)) load_int_band(dawn_metric.no_vht_support, fn + 15); + else if (!strncmp(fn, "rssi=", 5)) load_int_band(dawn_metric.rssi, fn + 5); + else if (!strncmp(fn, "low_rssi=", 9)) load_int_band(dawn_metric.low_rssi, fn + 9); + else if (!strncmp(fn, "freq=", 5)) load_int(&dawn_metric.initial_score[1], fn + 5); + else if (!strncmp(fn, "chan_util=", 10)) load_int_band(dawn_metric.chan_util, fn + 10); + else if (!strncmp(fn, "max_chan_util=", 14)) load_int_band(dawn_metric.max_chan_util, fn + 14); + else if (!strncmp(fn, "rssi_val=", 9)) load_int_band(dawn_metric.rssi_val, fn + 9); + else if (!strncmp(fn, "low_rssi_val=", 13)) load_int_band(dawn_metric.low_rssi_val, fn + 13); + else if (!strncmp(fn, "chan_util_val=", 14)) load_int_band(dawn_metric.chan_util_val, fn + 14); + else if (!strncmp(fn, "max_chan_util_val=", 18)) load_int_band(dawn_metric.max_chan_util_val, fn + 18); else if (!strncmp(fn, "min_probe_count=", 16)) load_int(&dawn_metric.min_probe_count, fn + 16); else if (!strncmp(fn, "bandwidth_threshold=", 20)) load_int(&dawn_metric.bandwidth_threshold, fn + 20); else if (!strncmp(fn, "use_station_count=", 18)) load_int(&dawn_metric.use_station_count, fn + 18); @@ -654,14 +723,12 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) else if (!strncmp(fn, "deny_auth_reason=", 17)) load_int(&dawn_metric.deny_auth_reason, fn + 17); else if (!strncmp(fn, "deny_assoc_reason=", 18)) load_int(&dawn_metric.deny_assoc_reason, fn + 18); else if (!strncmp(fn, "use_driver_recog=", 17)) load_int(&dawn_metric.use_driver_recog, fn + 17); - else if (!strncmp(fn, "min_kick_count=", 15)) load_int(&dawn_metric.min_kick_count, fn + 15); + else if (!strncmp(fn, "min_number_to_kick=", 19)) load_int(&dawn_metric.min_number_to_kick, fn + 19); else if (!strncmp(fn, "chan_util_avg_period=", 21)) load_int(&dawn_metric.chan_util_avg_period, fn + 21); else if (!strncmp(fn, "set_hostapd_nr=", 15)) load_int(&dawn_metric.set_hostapd_nr, fn + 15); 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, "scan_channel=", 13)) load_int(&dawn_metric.scan_channel, fn + 13); + else if (!strncmp(fn, "rrm_mode=", 9)) dawn_metric.rrm_mode_mask = parse_rrm_mode(dawn_metric.rrm_mode_order, fn + 9); else { printf("ERROR: Loading DAWN control metrics, but don't recognise assignment \"%s\"\n", fn); ret = 1; @@ -706,7 +773,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) ap0->time = faketime; ap0->station_count = 0; memset(ap0->ssid, '*', SSID_MAX_LEN); - ap0->ssid[SSID_MAX_LEN - 1] = '\0'; + ap0->ssid[SSID_MAX_LEN] = '\0'; ap0->neighbor_report[0] = 0; ap0->collision_domain = 0; ap0->bandwidth = 0; @@ -947,7 +1014,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) hwaddr_aton(argv[1], kick_mac.u8); load_u32(&kick_id, argv[2]); - while ((kick_clients(ap_array_get_ap(kick_mac), kick_id) != 0) && safety_count--); + while ((kick_clients(ap_array_get_ap(kick_mac, NULL), kick_id) != 0) && safety_count--); } } else if (strcmp(*argv, "better_ap_available") == 0) @@ -966,6 +1033,8 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) load_u32(&autokick, argv[3]); char nb[NEIGHBOR_REPORT_LEN] = "TAMPER EVIDENT NEIGHBOR REPORT INITIALISATION STRING"; + struct kicking_nr neighbor = {0}; + struct kicking_nr *neighbor_list = &neighbor; if (curr_arg + 5 <= argc) { @@ -979,12 +1048,12 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) { strcpy(nb, argv[4]); } - - tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, nb); + strncpy(neighbor.nr, nb, NEIGHBOR_REPORT_LEN); + tr = better_ap_available(ap_array_get_ap(bssid_mac, NULL), client_mac, &neighbor_list); } else { - tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, NULL); + tr = better_ap_available(ap_array_get_ap(bssid_mac, NULL), client_mac, NULL); } printf("better_ap_available returned %d (with neighbour report %s)\n", tr, nb); @@ -1009,7 +1078,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) } else { - ap* ap_entry = ap_array_get_ap(pr0->bssid_addr); + ap* ap_entry = ap_array_get_ap(pr0->bssid_addr, NULL); int this_metric = eval_probe_metric(pr0, ap_entry); printf("eval_probe_metric: Returned %d\n", this_metric); diff --git a/src/utils/dawn_iwinfo.c b/src/utils/dawn_iwinfo.c index 3ad3918..32595e8 100644 --- a/src/utils/dawn_iwinfo.c +++ b/src/utils/dawn_iwinfo.c @@ -72,8 +72,6 @@ int compare_essid_iwinfo(struct dawn_mac bssid_addr, struct dawn_mac bssid_addr_ } closedir(dirp); - printf("Comparing: %s with %s\n", essid, essid_to_compare); - if (essid == NULL || essid_to_compare == NULL) { return -1; } @@ -120,11 +118,9 @@ int get_bandwidth(const char *ifname, struct dawn_mac client_addr, float *rx_rat iw = iwinfo_backend(ifname); if (iw->assoclist(ifname, buf, &len)) { - fprintf(stdout, "No information available\n"); iwinfo_finish(); return 0; } else if (len <= 0) { - fprintf(stdout, "No station connected\n"); iwinfo_finish(); return 0; } @@ -177,11 +173,15 @@ int get_rssi(const char *ifname, struct dawn_mac client_addr) { iw = iwinfo_backend(ifname); if (iw->assoclist(ifname, buf, &len)) { +#ifndef DAWN_NO_OUTPUT fprintf(stdout, "No information available\n"); +#endif iwinfo_finish(); return INT_MIN; } else if (len <= 0) { +#ifndef DAWN_NO_OUTPUT fprintf(stdout, "No station connected\n"); +#endif iwinfo_finish(); return INT_MIN; } @@ -233,11 +233,15 @@ int get_expected_throughput(const char *ifname, struct dawn_mac client_addr) { iw = iwinfo_backend(ifname); if (iw->assoclist(ifname, buf, &len)) { +#ifndef DAWN_NO_OUTPUT fprintf(stdout, "No information available\n"); +#endif iwinfo_finish(); return INT_MIN; } else if (len <= 0) { +#ifndef DAWN_NO_OUTPUT fprintf(stdout, "No station connected\n"); +#endif iwinfo_finish(); return INT_MIN; } @@ -281,8 +285,7 @@ int get_ssid(const char *ifname, char* ssid, size_t ssidmax) { if (iw->ssid(ifname, buf)) memset(buf, 0, sizeof(buf)); - memcpy(ssid, buf, ssidmax); - strcpy(ssid, buf); + strncpy(ssid, buf, ssidmax); iwinfo_finish(); return 0; } @@ -349,7 +352,6 @@ int support_ht(const char *ifname) { if (iw->htmodelist(ifname, &htmodes)) { - printf("No HT mode information available\n"); iwinfo_finish(); return 0; } @@ -369,7 +371,6 @@ int support_vht(const char *ifname) { if (iw->htmodelist(ifname, &htmodes)) { - fprintf(stderr, "No VHT mode information available\n"); iwinfo_finish(); return 0; } diff --git a/src/utils/dawn_uci.c b/src/utils/dawn_uci.c index 76cffc5..d887215 100644 --- a/src/utils/dawn_uci.c +++ b/src/utils/dawn_uci.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -11,14 +12,17 @@ static struct uci_context *uci_ctx = NULL; static struct uci_package *uci_pkg = NULL; -// why is this not included in uci lib...?! -// found here: https://github.com/br101/pingcheck/blob/master/uci.c -static int uci_lookup_option_int(struct uci_context *uci, struct uci_section *s, - const char *name) { - const char *str = uci_lookup_option_string(uci, s, name); - return str == NULL ? -1 : atoi(str); +static void set_if_present_int(int *ret, struct uci_section *s, const char* option) { + const char *str; + + if (s && (str = uci_lookup_option_string(uci_ctx, s, option))) + *ret = atoi(str); } +#define DAWN_SET_CONFIG_INT(m, s, conf) \ + set_if_present_int(&m.conf, s, #conf) + + void uci_get_hostname(char* hostname) { char path[]= "system.@system[0].hostname"; @@ -52,8 +56,29 @@ void uci_get_hostname(char* hostname) dawn_unregmem(c); } + +static void set_if_present_time_t(time_t *ret, struct uci_section *s, const char* option) { + const char *str; + + if (s && (str = uci_lookup_option_string(uci_ctx, s, option))) + *ret = atoi(str); +} + +#define DAWN_SET_CONFIG_TIME(m, s, conf) \ + set_if_present_time_t(&m.conf, s, #conf) + struct time_config_s uci_get_time_config() { - struct time_config_s ret; + struct time_config_s ret = { + .update_client = 10, + .remove_client = 15, + .remove_probe = 30, + .update_hostapd = 10, + .remove_ap = 460, + .update_tcp_con = 10, + .denied_req_threshold = 30, + .update_chan_util = 5, + .update_beacon_reports = 20, + }; struct uci_element *e; uci_foreach_element(&uci_pkg->sections, e) @@ -61,15 +86,15 @@ struct time_config_s uci_get_time_config() { struct uci_section *s = uci_to_section(e); if (strcmp(s->type, "times") == 0) { - ret.update_client = uci_lookup_option_int(uci_ctx, s, "update_client"); - ret.remove_client = uci_lookup_option_int(uci_ctx, s, "remove_client"); - ret.remove_probe = uci_lookup_option_int(uci_ctx, s, "remove_probe"); - ret.update_hostapd = uci_lookup_option_int(uci_ctx, s, "update_hostapd"); - ret.remove_ap = uci_lookup_option_int(uci_ctx, s, "remove_ap"); - ret.update_tcp_con = uci_lookup_option_int(uci_ctx, s, "update_tcp_con"); - ret.denied_req_threshold = uci_lookup_option_int(uci_ctx, s, "denied_req_threshold"); - ret.update_chan_util = uci_lookup_option_int(uci_ctx, s, "update_chan_util"); - ret.update_beacon_reports = uci_lookup_option_int(uci_ctx, s, "update_beacon_reports"); + DAWN_SET_CONFIG_TIME(ret, s, update_client); + DAWN_SET_CONFIG_TIME(ret, s, remove_client); + DAWN_SET_CONFIG_TIME(ret, s, remove_probe); + DAWN_SET_CONFIG_TIME(ret, s, update_hostapd); + DAWN_SET_CONFIG_TIME(ret, s, remove_ap); + DAWN_SET_CONFIG_TIME(ret, s, update_tcp_con); + DAWN_SET_CONFIG_TIME(ret, s, denied_req_threshold); + DAWN_SET_CONFIG_TIME(ret, s, update_chan_util); + DAWN_SET_CONFIG_TIME(ret, s, update_beacon_reports); return ret; } } @@ -77,57 +102,228 @@ struct time_config_s uci_get_time_config() { return ret; } -struct probe_metric_s uci_get_dawn_metric() { - struct probe_metric_s ret; - struct uci_element *e; - uci_foreach_element(&uci_pkg->sections, e) - { - struct uci_section *s = uci_to_section(e); +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; +} - if (strcmp(s->type, "metric") == 0) { - ret.ap_weight = uci_lookup_option_int(uci_ctx, s, "ap_weight"); - ret.kicking = uci_lookup_option_int(uci_ctx, s, "kicking"); - ret.ht_support = uci_lookup_option_int(uci_ctx, s, "ht_support"); - ret.vht_support = uci_lookup_option_int(uci_ctx, s, "vht_support"); - ret.no_ht_support = uci_lookup_option_int(uci_ctx, s, "no_ht_support"); - ret.no_vht_support = uci_lookup_option_int(uci_ctx, s, "no_vht_support"); - ret.rssi = uci_lookup_option_int(uci_ctx, s, "rssi"); - ret.freq = uci_lookup_option_int(uci_ctx, s, "freq"); - ret.rssi_val = uci_lookup_option_int(uci_ctx, s, "rssi_val"); - ret.chan_util = uci_lookup_option_int(uci_ctx, s, "chan_util"); - ret.max_chan_util = uci_lookup_option_int(uci_ctx, s, "max_chan_util"); - ret.chan_util_val = uci_lookup_option_int(uci_ctx, s, "chan_util_val"); - ret.max_chan_util_val = uci_lookup_option_int(uci_ctx, s, "max_chan_util_val"); - ret.min_probe_count = uci_lookup_option_int(uci_ctx, s, "min_probe_count"); - ret.low_rssi = uci_lookup_option_int(uci_ctx, s, "low_rssi"); - ret.low_rssi_val = uci_lookup_option_int(uci_ctx, s, "low_rssi_val"); - ret.bandwidth_threshold = uci_lookup_option_int(uci_ctx, s, "bandwidth_threshold"); - ret.use_station_count = uci_lookup_option_int(uci_ctx, s, "use_station_count"); - ret.eval_probe_req = uci_lookup_option_int(uci_ctx, s, "eval_probe_req"); - ret.eval_auth_req = uci_lookup_option_int(uci_ctx, s, "eval_auth_req"); - ret.eval_assoc_req = uci_lookup_option_int(uci_ctx, s, "eval_assoc_req"); - ret.deny_auth_reason = uci_lookup_option_int(uci_ctx, s, "deny_auth_reason"); - ret.deny_assoc_reason = uci_lookup_option_int(uci_ctx, s, "deny_assoc_reason"); - ret.max_station_diff = uci_lookup_option_int(uci_ctx, s, "max_station_diff"); - ret.use_driver_recog = uci_lookup_option_int(uci_ctx, s, "use_driver_recog"); - ret.min_kick_count = uci_lookup_option_int(uci_ctx, s, "min_number_to_kick"); - ret.chan_util_avg_period = uci_lookup_option_int(uci_ctx, s, "chan_util_avg_period"); - 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.scan_channel = uci_lookup_option_int(uci_ctx, s, "scan_channel"); - return ret; +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 struct mac_entry_s *insert_neighbor_mac(struct mac_entry_s *head, const char* mac) { + struct mac_entry_s *new; + + if (!(new = dawn_malloc(sizeof (struct mac_entry_s)))) { + fprintf(stderr, "Warning: Failed to create neighbor entry for '%s'\n", mac); + return head; + } + memset(new, 0, sizeof (struct mac_entry_s)); + if (hwaddr_aton(mac, new->mac.u8) != 0) { + fprintf(stderr, "Warning: Failed to parse MAC from '%s'\n", mac); + dawn_free(new); + return head; + } + new->next_mac = head; + return new; +} + +static void free_neighbor_mac_list(struct mac_entry_s *list) { + struct mac_entry_s *ptr = list; + while (list) { + ptr = list; + list = list->next_mac; + dawn_free(ptr); + } +} + +static struct mac_entry_s* uci_lookup_mac_list(struct uci_option *o) { + struct uci_element *e; + struct mac_entry_s *head = NULL; + char *str; + + if (o == NULL) + return NULL; + + // hostapd inserts the new neigbor reports at the top of the list. + // Therefore, we must also do this backwares somewhere. Let's do it + // here instead of when sending the list through ubus. + switch (o->type) { + case UCI_TYPE_LIST: + uci_foreach_element(&o->v.list, e) + head = insert_neighbor_mac(head, e->name); + break; + case UCI_TYPE_STRING: + if (!(str = strdup (o->v.string))) + return NULL; + for (char *mac = strtok(str, " "); mac; mac = strtok(NULL, " ")) + head = insert_neighbor_mac(head, mac); + free(str); + } + return head; +} + +static struct uci_section *uci_find_metric_section(const char *name) { + struct uci_section *s; + struct uci_element *e; + + uci_foreach_element(&uci_pkg->sections, e) { + s = uci_to_section(e); + if (strcmp(s->type, "metric") == 0 && + ((!name && s->anonymous) || strcmp(e->name, name) == 0)) { + return s; + } + } + return NULL; +} + +#define DAWN_SET_BANDS_CONFIG_INT(m, global_s, band_s, conf) \ + do for (int band = 0; band < __DAWN_BAND_MAX; band++) { \ + if (global_s) \ + set_if_present_int(&m.conf[band], global_s, #conf); \ + if (band_s[band]) \ + set_if_present_int(&m.conf[band], band_s[band], #conf); \ + } while (0) + +struct probe_metric_s uci_get_dawn_metric() { + struct probe_metric_s ret = { + .kicking = 0, + .min_probe_count = 0, + .use_station_count = 1, + .eval_auth_req = 0, + .eval_assoc_req = 0, + .deny_auth_reason = 1, + .deny_assoc_reason = 17, + .eval_probe_req = 0, + .min_number_to_kick = 3, + .set_hostapd_nr = 1, + .max_station_diff = 1, + .bandwidth_threshold = 6, + .use_driver_recog = 1, + .chan_util_avg_period = 3, + .duration = 0, + .rrm_mode_mask = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | + WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | + WLAN_RRM_CAPS_BEACON_REPORT_TABLE, + .rrm_mode_order = { WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE, + WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE, + WLAN_RRM_CAPS_BEACON_REPORT_TABLE }, + .ap_weight = { 0, 0 }, + .ht_support = { 0, 0 }, + .vht_support = { 0, 0 }, + .no_ht_support = { 0, 0 }, + .no_vht_support = { 0, 0 }, + .rssi = { 10, 10 }, + .rssi_val = { -60, -60 }, + .initial_score = { 0, 100 }, + .chan_util = { 0, 0 }, + .max_chan_util = { -500, -500 }, + .chan_util_val = { 140, 140 }, + .max_chan_util_val = { 170, 170 }, + .low_rssi = { -500, -500 }, + .low_rssi_val = { -80, -80 }, + }; + struct uci_section *global_s, *band_s[__DAWN_BAND_MAX]; + struct uci_option *global_neighbors = NULL, *neighbors; + + if (!(global_s = uci_find_metric_section("global"))) { + if (!(global_s = uci_find_metric_section(NULL))) { + fprintf(stderr, "Warning: config metric global section not found! Using defaults.\n"); + } else { + fprintf(stderr, "Warning: config metric global section not found. " + "Using first unnamed config metric.\n" + "Consider naming a 'global' metric section to avoid ambiguity.\n"); + } + } + if (global_s) { + // True global configuration + DAWN_SET_CONFIG_INT(ret, global_s, kicking); + DAWN_SET_CONFIG_INT(ret, global_s, kicking_threshold); + DAWN_SET_CONFIG_INT(ret, global_s, min_probe_count); + DAWN_SET_CONFIG_INT(ret, global_s, use_station_count); + DAWN_SET_CONFIG_INT(ret, global_s, eval_auth_req); + DAWN_SET_CONFIG_INT(ret, global_s, eval_assoc_req); + DAWN_SET_CONFIG_INT(ret, global_s, deny_auth_reason); + DAWN_SET_CONFIG_INT(ret, global_s, deny_assoc_reason); + DAWN_SET_CONFIG_INT(ret, global_s, eval_probe_req); + DAWN_SET_CONFIG_INT(ret, global_s, min_number_to_kick); + DAWN_SET_CONFIG_INT(ret, global_s, set_hostapd_nr); + DAWN_SET_CONFIG_INT(ret, global_s, max_station_diff); + DAWN_SET_CONFIG_INT(ret, global_s, bandwidth_threshold); + DAWN_SET_CONFIG_INT(ret, global_s, use_driver_recog); + DAWN_SET_CONFIG_INT(ret, global_s, chan_util_avg_period); + DAWN_SET_CONFIG_INT(ret, global_s, duration); + ret.rrm_mode_mask = parse_rrm_mode(ret.rrm_mode_order, + uci_lookup_option_string(uci_ctx, global_s, "rrm_mode")); + global_neighbors = uci_lookup_option(uci_ctx, global_s, "neighbors"); + } + for (int band = 0; band < __DAWN_BAND_MAX; band++) { + band_s[band] = uci_find_metric_section(band_config_name[band]); + neighbors = band_s[band] ? uci_lookup_option(uci_ctx, band_s[band], "neighbors") : NULL; + ret.neighbors[band] = uci_lookup_mac_list(neighbors ? : global_neighbors); + } + + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, initial_score); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, ap_weight); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, ht_support); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, vht_support); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, no_ht_support); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, no_vht_support); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, rssi); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, rssi_val); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, chan_util); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, max_chan_util); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, chan_util_val); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, max_chan_util_val); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, low_rssi); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, low_rssi_val); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, rssi_weight); + DAWN_SET_BANDS_CONFIG_INT(ret, global_s, band_s, rssi_center); return ret; } struct network_config_s uci_get_dawn_network() { - struct network_config_s ret; - memset(&ret, 0, sizeof(ret)); + struct network_config_s ret = { + .broadcast_ip = "", + .broadcast_port = 1025, + .server_ip = "", + .tcp_port = 1026, + .network_option = 2, + .shared_key = "Niiiiiiiiiiiiiik", + .iv = "Niiiiiiiiiiiiiik", + .use_symm_enc = 1, + .collision_domain = -1, + .bandwidth = -1, + }; struct uci_element *e; uci_foreach_element(&uci_pkg->sections, e) @@ -136,21 +332,28 @@ struct network_config_s uci_get_dawn_network() { if (strcmp(s->type, "network") == 0) { const char* str_broadcast = uci_lookup_option_string(uci_ctx, s, "broadcast_ip"); - strncpy(ret.broadcast_ip, str_broadcast, MAX_IP_LENGTH); + if (str_broadcast) + strncpy(ret.broadcast_ip, str_broadcast, MAX_IP_LENGTH); - ret.broadcast_port = uci_lookup_option_int(uci_ctx, s, "broadcast_port"); + const char* str_server_ip = uci_lookup_option_string(uci_ctx, s, "server_ip"); + if(str_server_ip) + strncpy(ret.server_ip, str_server_ip, MAX_IP_LENGTH); + + DAWN_SET_CONFIG_INT(ret, s, broadcast_port); const char* str_shared_key = uci_lookup_option_string(uci_ctx, s, "shared_key"); - strncpy(ret.shared_key, str_shared_key, MAX_KEY_LENGTH); + if (str_shared_key) + strncpy(ret.shared_key, str_shared_key, MAX_KEY_LENGTH); const char* str_iv = uci_lookup_option_string(uci_ctx, s, "iv"); - strncpy(ret.iv, str_iv, MAX_KEY_LENGTH); + if (str_iv) + strncpy(ret.iv, str_iv, MAX_KEY_LENGTH); - ret.network_option = uci_lookup_option_int(uci_ctx, s, "network_option"); - ret.tcp_port = uci_lookup_option_int(uci_ctx, s, "tcp_port"); - ret.use_symm_enc = uci_lookup_option_int(uci_ctx, s, "use_symm_enc"); - ret.collision_domain = uci_lookup_option_int(uci_ctx, s, "collision_domain"); - ret.bandwidth = uci_lookup_option_int(uci_ctx, s, "bandwidth"); + DAWN_SET_CONFIG_INT(ret, s, network_option); + DAWN_SET_CONFIG_INT(ret, s, tcp_port); + DAWN_SET_CONFIG_INT(ret, s, use_symm_enc); + DAWN_SET_CONFIG_INT(ret, s, collision_domain); + DAWN_SET_CONFIG_INT(ret, s, bandwidth); return ret; } } @@ -190,6 +393,14 @@ bool uci_get_dawn_sort_order() { int uci_reset() { + struct uci_context *ctx = uci_ctx; + + if (!ctx) { + ctx = uci_alloc_context(); + dawn_regmem(ctx); + uci_ctx = ctx; + } + uci_pkg = uci_lookup_package(ctx, "dawn"); uci_unload(uci_ctx, uci_pkg); dawn_unregmem(uci_pkg); uci_load(uci_ctx, "dawn", &uci_pkg); @@ -228,6 +439,9 @@ int uci_init() { } int uci_clear() { + for (int band = 0; band < __DAWN_BAND_MAX; band++) + free_neighbor_mac_list(dawn_metric.neighbors[band]); + if (uci_pkg != NULL) { uci_unload(uci_ctx, uci_pkg); dawn_unregmem(uci_pkg); diff --git a/src/utils/memory_utils.c b/src/utils/memory_utils.c index 9067bb1..03614a6 100644 --- a/src/utils/memory_utils.c +++ b/src/utils/memory_utils.c @@ -88,7 +88,6 @@ void* dawn_memory_register(enum dawn_memop type, char* file, int line, size_t si } else { - //printf("mem-audit: registering new memory (%c@%s:%d)...\n", type_c, file, line); this_log = malloc(sizeof(struct mem_list)); if (this_log == NULL) @@ -147,7 +146,6 @@ char type_c = '?'; if (*mem != NULL && (*mem)->ptr == ptr) { - //printf("mem-audit: unregistering memory (%c@%s:%d)...\n", type_c, file, line); struct mem_list* tmp = *mem; *mem = tmp->next_mem; free(tmp); diff --git a/src/utils/msghandler.c b/src/utils/msghandler.c index c59e2ac..daf1210 100644 --- a/src/utils/msghandler.c +++ b/src/utils/msghandler.c @@ -51,8 +51,8 @@ static const struct blobmsg_policy prob_policy[__PROB_MAX] = { [PROB_TARGET_ADDR] = {.name = "target", .type = BLOBMSG_TYPE_STRING}, [PROB_SIGNAL] = {.name = "signal", .type = BLOBMSG_TYPE_INT32}, [PROB_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32}, - [PROB_HT_CAPABILITIES] = {.name = "ht_capabilities", .type = BLOBMSG_TYPE_TABLE}, - [PROB_VHT_CAPABILITIES] = {.name = "vht_capabilities", .type = BLOBMSG_TYPE_TABLE}, + [PROB_HT_CAPABILITIES] = {.name = "ht_capabilities", .type = BLOBMSG_TYPE_TABLE}, //ToDo: Change to int8? + [PROB_VHT_CAPABILITIES] = {.name = "vht_capabilities", .type = BLOBMSG_TYPE_TABLE}, //ToDo: Change to int8? [PROB_RCPI] = {.name = "rcpi", .type = BLOBMSG_TYPE_INT32}, [PROB_RSNI] = {.name = "rsni", .type = BLOBMSG_TYPE_INT32}, }; @@ -148,7 +148,6 @@ probe_entry *parse_to_probe_req(struct blob_attr* msg) { struct blob_attr* tb[__PROB_MAX]; probe_entry* prob_req = dawn_malloc(sizeof(probe_entry)); - if (prob_req == NULL) { fprintf(stderr, "dawn_malloc of probe_entry failed!\n"); @@ -229,8 +228,6 @@ int handle_deauth_req(struct blob_attr* msg) { pthread_mutex_unlock(&client_array_mutex); - printf("[WC] Deauth: %s\n", "deauth"); - return 0; } @@ -261,7 +258,9 @@ int handle_network_msg(char* msg) { method = blobmsg_data(tb[NETWORK_METHOD]); data = blobmsg_data(tb[NETWORK_DATA]); +#ifndef DAWN_NO_OUTPUT printf("Network Method new: %s : %s\n", method, msg); +#endif blob_buf_init(&data_buf, 0); blobmsg_add_json_from_string(&data_buf, data); @@ -295,11 +294,15 @@ int handle_network_msg(char* msg) { parse_to_clients(data_buf.head, 0, 0); } else if (strncmp(method, "deauth", 5) == 0) { +#ifndef DAWN_NO_OUTPUT printf("METHOD DEAUTH\n"); +#endif handle_deauth_req(data_buf.head); } else if (strncmp(method, "setprobe", 5) == 0) { +#ifndef DAWN_NO_OUTPUT printf("HANDLING SET PROBE!\n"); +#endif handle_set_probe(data_buf.head); } else if (strncmp(method, "addmac", 5) == 0) { @@ -309,7 +312,9 @@ int handle_network_msg(char* msg) { parse_add_mac_to_file(data_buf.head); } else if (strncmp(method, "uci", 2) == 0) { +#ifndef DAWN_NO_OUTPUT printf("HANDLING UCI!\n"); +#endif handle_uci_config(data_buf.head); } else if (strncmp(method, "beacon-report", 12) == 0) { @@ -323,36 +328,22 @@ int handle_network_msg(char* msg) { } else { +#ifndef DAWN_NO_OUTPUT printf("No method fonud for: %s\n", method); +#endif } return 0; } -static uint8_t dump_rrm_data(void* data, int len, int type) //modify from examples/blobmsg-example.c in libubox -{ - uint32_t ret = 0; - switch (type) { - case BLOBMSG_TYPE_INT32: - ret = *(uint32_t*)data; - break; - default: - fprintf(stderr, "wrong type of rrm array\n"); - } - return (uint8_t)ret; -} - static uint8_t -dump_rrm_table(struct blob_attr* head, int len) //modify from examples/blobmsg-example.c in libubox +dump_rrm_data(struct blob_attr* head) { - struct blob_attr* attr; - uint8_t ret = 0; - - __blob_for_each_attr(attr, head, len) { - ret = dump_rrm_data(blobmsg_data(attr), blobmsg_data_len(attr), blob_id(attr)); - return ret;// get the first rrm byte + if (blob_id(head) != BLOBMSG_TYPE_INT32) { + fprintf(stderr, "wrong type of rrm array.\n"); + return 0; } - return ret; + return (uint8_t)blobmsg_get_u32(head); } // TOOD: Refactor this! @@ -407,8 +398,8 @@ dump_client(struct blob_attr** tb, struct dawn_mac client_addr, const char* bssi } /* RRM Caps */ if (tb[CLIENT_RRM]) { - client_entry->rrm_enabled_capa = dump_rrm_table(blobmsg_data(tb[CLIENT_RRM]), - blobmsg_data_len(tb[CLIENT_RRM]));// get the first byte from rrm array + // get the first byte from rrm array + client_entry->rrm_enabled_capa = dump_rrm_data(blobmsg_data(tb[CLIENT_RRM])); //ap_entry.ap_weight = blobmsg_get_u32(tb[CLIENT_TABLE_RRM]); } else { @@ -536,8 +527,10 @@ int parse_to_clients(struct blob_attr* msg, int do_kick, uint32_t id) { } + ap_entry->op_class = ap_entry->channel = 0; if (tb[CLIENT_TABLE_NEIGHBOR]) { strncpy(ap_entry->neighbor_report, blobmsg_get_string(tb[CLIENT_TABLE_NEIGHBOR]), NEIGHBOR_REPORT_LEN); + sscanf(ap_entry->neighbor_report + NR_OP_CLASS, "%2x%2x", &ap_entry->op_class, &ap_entry->channel); } else { ap_entry->neighbor_report[0] = '\0'; @@ -568,25 +561,13 @@ int parse_to_clients(struct blob_attr* msg, int do_kick, uint32_t id) { } enum { + UCI_CONFIG_VERSION, UCI_TABLE_METRIC, UCI_TABLE_TIMES, __UCI_TABLE_MAX }; enum { - UCI_HT_SUPPORT, - UCI_VHT_SUPPORT, - UCI_NO_HT_SUPPORT, - UCI_NO_VHT_SUPPORT, - UCI_RSSI, - UCI_LOW_RSSI, - UCI_FREQ, - UCI_CHAN_UTIL, - UCI_MAX_CHAN_UTIL, - UCI_RSSI_VAL, - UCI_LOW_RSSI_VAL, - UCI_CHAN_UTIL_VAL, - UCI_MAX_CHAN_UTIL_VAL, UCI_MIN_PROBE_COUNT, UCI_BANDWIDTH_THRESHOLD, UCI_USE_STATION_COUNT, @@ -595,17 +576,38 @@ enum { UCI_EVAL_AUTH_REQ, UCI_EVAL_ASSOC_REQ, UCI_KICKING, + UCI_KICKING_THRESHOLD, UCI_DENY_AUTH_REASON, UCI_DENY_ASSOC_REASON, UCI_USE_DRIVER_RECOG, UCI_MIN_NUMBER_TO_KICK, UCI_CHAN_UTIL_AVG_PERIOD, UCI_SET_HOSTAPD_NR, - UCI_OP_CLASS, UCI_DURATION, - UCI_MODE, - UCI_SCAN_CHANNEL, - __UCI_METIC_MAX + UCI_RRM_MODE, + UCI_BAND_METRICS, + __UCI_METRIC_MAX +}; + +enum { + UCI_BAND, + UCI_INITIAL_SCORE, + UCI_AP_WEIGHT, + UCI_HT_SUPPORT, + UCI_VHT_SUPPORT, + UCI_NO_HT_SUPPORT, + UCI_NO_VHT_SUPPORT, + UCI_RSSI, + UCI_LOW_RSSI, + UCI_CHAN_UTIL, + UCI_MAX_CHAN_UTIL, + UCI_RSSI_VAL, + UCI_LOW_RSSI_VAL, + UCI_CHAN_UTIL_VAL, + UCI_MAX_CHAN_UTIL_VAL, + UCI_RSSI_WEIGHT, + UCI_RSSI_CENTER, + __UCI_BAND_METRIC_MAX }; enum { @@ -622,24 +624,12 @@ enum { }; static const struct blobmsg_policy uci_table_policy[__UCI_TABLE_MAX] = { + [UCI_CONFIG_VERSION ] = {.name = "version", .type = BLOBMSG_TYPE_STRING}, [UCI_TABLE_METRIC] = {.name = "metric", .type = BLOBMSG_TYPE_TABLE}, [UCI_TABLE_TIMES] = {.name = "times", .type = BLOBMSG_TYPE_TABLE} }; -static const struct blobmsg_policy uci_metric_policy[__UCI_METIC_MAX] = { - [UCI_HT_SUPPORT] = {.name = "ht_support", .type = BLOBMSG_TYPE_INT32}, - [UCI_VHT_SUPPORT] = {.name = "vht_support", .type = BLOBMSG_TYPE_INT32}, - [UCI_NO_HT_SUPPORT] = {.name = "no_ht_support", .type = BLOBMSG_TYPE_INT32}, - [UCI_NO_VHT_SUPPORT] = {.name = "no_vht_support", .type = BLOBMSG_TYPE_INT32}, - [UCI_RSSI] = {.name = "rssi", .type = BLOBMSG_TYPE_INT32}, - [UCI_LOW_RSSI] = {.name = "low_rssi", .type = BLOBMSG_TYPE_INT32}, - [UCI_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32}, - [UCI_CHAN_UTIL] = {.name = "chan_util", .type = BLOBMSG_TYPE_INT32}, - [UCI_MAX_CHAN_UTIL] = {.name = "max_chan_util", .type = BLOBMSG_TYPE_INT32}, - [UCI_RSSI_VAL] = {.name = "rssi_val", .type = BLOBMSG_TYPE_INT32}, - [UCI_LOW_RSSI_VAL] = {.name = "low_rssi_val", .type = BLOBMSG_TYPE_INT32}, - [UCI_CHAN_UTIL_VAL] = {.name = "chan_util_val", .type = BLOBMSG_TYPE_INT32}, - [UCI_MAX_CHAN_UTIL_VAL] = {.name = "max_chan_util_val", .type = BLOBMSG_TYPE_INT32}, +static const struct blobmsg_policy uci_metric_policy[__UCI_METRIC_MAX] = { [UCI_MIN_PROBE_COUNT] = {.name = "min_probe_count", .type = BLOBMSG_TYPE_INT32}, [UCI_BANDWIDTH_THRESHOLD] = {.name = "bandwidth_threshold", .type = BLOBMSG_TYPE_INT32}, [UCI_USE_STATION_COUNT] = {.name = "use_station_count", .type = BLOBMSG_TYPE_INT32}, @@ -648,16 +638,34 @@ static const struct blobmsg_policy uci_metric_policy[__UCI_METIC_MAX] = { [UCI_EVAL_AUTH_REQ] = {.name = "eval_auth_req", .type = BLOBMSG_TYPE_INT32}, [UCI_EVAL_ASSOC_REQ] = {.name = "eval_assoc_req", .type = BLOBMSG_TYPE_INT32}, [UCI_KICKING] = {.name = "kicking", .type = BLOBMSG_TYPE_INT32}, + [UCI_KICKING_THRESHOLD] = {.name = "kicking_threshold", .type = BLOBMSG_TYPE_INT32}, [UCI_DENY_AUTH_REASON] = {.name = "deny_auth_reason", .type = BLOBMSG_TYPE_INT32}, [UCI_DENY_ASSOC_REASON] = {.name = "deny_assoc_reason", .type = BLOBMSG_TYPE_INT32}, [UCI_USE_DRIVER_RECOG] = {.name = "use_driver_recog", .type = BLOBMSG_TYPE_INT32}, [UCI_MIN_NUMBER_TO_KICK] = {.name = "min_number_to_kick", .type = BLOBMSG_TYPE_INT32}, [UCI_CHAN_UTIL_AVG_PERIOD] = {.name = "chan_util_avg_period", .type = BLOBMSG_TYPE_INT32}, [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_BAND_METRICS] = {.name = "band_metrics", .type = BLOBMSG_TYPE_TABLE}, +}; + +static const struct blobmsg_policy uci_band_metric_policy[__UCI_METRIC_MAX] = { + [UCI_INITIAL_SCORE] = {.name = "initial_score", .type = BLOBMSG_TYPE_INT32}, + [UCI_HT_SUPPORT] = {.name = "ht_support", .type = BLOBMSG_TYPE_INT32}, + [UCI_VHT_SUPPORT] = {.name = "vht_support", .type = BLOBMSG_TYPE_INT32}, + [UCI_NO_HT_SUPPORT] = {.name = "no_ht_support", .type = BLOBMSG_TYPE_INT32}, + [UCI_NO_VHT_SUPPORT] = {.name = "no_vht_support", .type = BLOBMSG_TYPE_INT32}, + [UCI_RSSI] = {.name = "rssi", .type = BLOBMSG_TYPE_INT32}, + [UCI_RSSI_VAL] = {.name = "rssi_val", .type = BLOBMSG_TYPE_INT32}, + [UCI_LOW_RSSI] = {.name = "low_rssi", .type = BLOBMSG_TYPE_INT32}, + [UCI_LOW_RSSI_VAL] = {.name = "low_rssi_val", .type = BLOBMSG_TYPE_INT32}, + [UCI_CHAN_UTIL] = {.name = "chan_util", .type = BLOBMSG_TYPE_INT32}, + [UCI_MAX_CHAN_UTIL] = {.name = "max_chan_util", .type = BLOBMSG_TYPE_INT32}, + [UCI_CHAN_UTIL_VAL] = {.name = "chan_util_val", .type = BLOBMSG_TYPE_INT32}, + [UCI_MAX_CHAN_UTIL_VAL] = {.name = "max_chan_util_val", .type = BLOBMSG_TYPE_INT32}, + [UCI_RSSI_WEIGHT] = {.name = "rssi_weight", .type = BLOBMSG_TYPE_INT32}, + [UCI_RSSI_CENTER] = {.name = "rssi_center", .type = BLOBMSG_TYPE_INT32}, }; static const struct blobmsg_policy uci_times_policy[__UCI_TIMES_MAX] = { @@ -677,103 +685,141 @@ static int handle_uci_config(struct blob_attr* msg) { struct blob_attr* tb[__UCI_TABLE_MAX]; blobmsg_parse(uci_table_policy, __UCI_TABLE_MAX, tb, blob_data(msg), blob_len(msg)); - struct blob_attr* tb_metric[__UCI_METIC_MAX]; - blobmsg_parse(uci_metric_policy, __UCI_METIC_MAX, tb_metric, blobmsg_data(tb[UCI_TABLE_METRIC]), blobmsg_len(tb[UCI_TABLE_METRIC])); + const char *version_string = blobmsg_get_string(tb[UCI_CONFIG_VERSION]); + if (version_string == NULL || strcmp(version_string, DAWN_CONFIG_VERSION)) { + fprintf(stderr, "Ignoring network config message with incompatible version string '%s'.\n", + version_string ? : ""); + return -1; + } + + struct blob_attr* tb_metric[__UCI_METRIC_MAX]; + blobmsg_parse(uci_metric_policy, __UCI_METRIC_MAX, tb_metric, blobmsg_data(tb[UCI_TABLE_METRIC]), blobmsg_len(tb[UCI_TABLE_METRIC])); // TODO: Magic number? char cmd_buffer[1024]; - sprintf(cmd_buffer, "dawn.@metric[0].ht_support=%d", blobmsg_get_u32(tb_metric[UCI_HT_SUPPORT])); + + sprintf(cmd_buffer, "%s", "dawn.global=metric"); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].vht_support=%d", blobmsg_get_u32(tb_metric[UCI_VHT_SUPPORT])); + sprintf(cmd_buffer, "dawn.global.min_probe_count=%d", blobmsg_get_u32(tb_metric[UCI_MIN_PROBE_COUNT])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].no_ht_support=%d", blobmsg_get_u32(tb_metric[UCI_NO_HT_SUPPORT])); + sprintf(cmd_buffer, "dawn.global.bandwidth_threshold=%d", blobmsg_get_u32(tb_metric[UCI_BANDWIDTH_THRESHOLD])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].no_vht_support=%d", blobmsg_get_u32(tb_metric[UCI_NO_VHT_SUPPORT])); + sprintf(cmd_buffer, "dawn.global.use_station_count=%d", blobmsg_get_u32(tb_metric[UCI_USE_STATION_COUNT])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].rssi=%d", blobmsg_get_u32(tb_metric[UCI_RSSI])); + sprintf(cmd_buffer, "dawn.global.max_station_diff=%d", blobmsg_get_u32(tb_metric[UCI_MAX_STATION_DIFF])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].low_rssi=%d", blobmsg_get_u32(tb_metric[UCI_LOW_RSSI])); + sprintf(cmd_buffer, "dawn.global.eval_probe_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_PROBE_REQ])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].freq=%d", blobmsg_get_u32(tb_metric[UCI_FREQ])); + sprintf(cmd_buffer, "dawn.global.eval_auth_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_AUTH_REQ])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].chan_util=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL])); + sprintf(cmd_buffer, "dawn.global.eval_assoc_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_ASSOC_REQ])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].rssi_val=%d", blobmsg_get_u32(tb_metric[UCI_RSSI_VAL])); + sprintf(cmd_buffer, "dawn.global.kicking=%d", blobmsg_get_u32(tb_metric[UCI_KICKING])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].low_rssi_val=%d", blobmsg_get_u32(tb_metric[UCI_LOW_RSSI_VAL])); + sprintf(cmd_buffer, "dawn.global.kicking_threshold=%d", blobmsg_get_u32(tb_metric[UCI_KICKING_THRESHOLD])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].chan_util_val=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL_VAL])); + sprintf(cmd_buffer, "dawn.global.deny_auth_reason=%d", blobmsg_get_u32(tb_metric[UCI_DENY_AUTH_REASON])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].max_chan_util=%d", blobmsg_get_u32(tb_metric[UCI_MAX_CHAN_UTIL])); + sprintf(cmd_buffer, "dawn.global.deny_assoc_reason=%d", blobmsg_get_u32(tb_metric[UCI_DENY_ASSOC_REASON])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].max_chan_util_val=%d", blobmsg_get_u32(tb_metric[UCI_MAX_CHAN_UTIL_VAL])); + sprintf(cmd_buffer, "dawn.global.use_driver_recog=%d", blobmsg_get_u32(tb_metric[UCI_USE_DRIVER_RECOG])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].min_probe_count=%d", blobmsg_get_u32(tb_metric[UCI_MIN_PROBE_COUNT])); + sprintf(cmd_buffer, "dawn.global.min_number_to_kick=%d", blobmsg_get_u32(tb_metric[UCI_MIN_NUMBER_TO_KICK])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].bandwidth_threshold=%d", blobmsg_get_u32(tb_metric[UCI_BANDWIDTH_THRESHOLD])); + sprintf(cmd_buffer, "dawn.global.chan_util_avg_period=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL_AVG_PERIOD])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].use_station_count=%d", blobmsg_get_u32(tb_metric[UCI_USE_STATION_COUNT])); + sprintf(cmd_buffer, "dawn.global.set_hostapd_nr=%d", blobmsg_get_u32(tb_metric[UCI_SET_HOSTAPD_NR])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].max_station_diff=%d", blobmsg_get_u32(tb_metric[UCI_MAX_STATION_DIFF])); + sprintf(cmd_buffer, "dawn.global.duration=%d", blobmsg_get_u32(tb_metric[UCI_DURATION])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].eval_probe_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_PROBE_REQ])); + sprintf(cmd_buffer, "dawn.global.rrm_mode=%s", blobmsg_get_string(tb_metric[UCI_RRM_MODE])); uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].eval_auth_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_AUTH_REQ])); - uci_set_network(cmd_buffer); + struct blob_attr *tb_band_metric[__UCI_BAND_METRIC_MAX], *attr; + int band_len = blobmsg_len(tb_metric[UCI_BAND_METRICS]); + struct blob_attr *band_data = blobmsg_data(tb_metric[UCI_BAND_METRICS]); + __blob_for_each_attr(attr, band_data, band_len) { + struct blobmsg_hdr *hdr = blob_data(attr); + const char *band_name = (const char *)hdr->name; + int band; - sprintf(cmd_buffer, "dawn.@metric[0].evalcd_assoc_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_ASSOC_REQ])); - uci_set_network(cmd_buffer); + blobmsg_parse(uci_band_metric_policy, __UCI_BAND_METRIC_MAX, tb_band_metric, + blobmsg_data(attr), blobmsg_len(attr)); - sprintf(cmd_buffer, "dawn.@metric[0].kicking=%d", blobmsg_get_u32(tb_metric[UCI_KICKING])); - uci_set_network(cmd_buffer); + for (band = 0; band < __DAWN_BAND_MAX; band++) { + if (!strcmp(band_name, band_config_name[band])) + break; + } + if (band == __DAWN_BAND_MAX) { + fprintf(stderr, "handle_uci_config: Warning: unknown band '%s'.\n", band_name); + continue; // Should we write the metrics of an unknown band to the config file? + } - sprintf(cmd_buffer, "dawn.@metric[0].deny_auth_reason=%d", blobmsg_get_u32(tb_metric[UCI_DENY_AUTH_REASON])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s=metric", band_name); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].deny_assoc_reason=%d", blobmsg_get_u32(tb_metric[UCI_DENY_ASSOC_REASON])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.initial_score=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_INITIAL_SCORE])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].use_driver_recog=%d", blobmsg_get_u32(tb_metric[UCI_USE_DRIVER_RECOG])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.ht_support=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_HT_SUPPORT])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].min_number_to_kick=%d", blobmsg_get_u32(tb_metric[UCI_MIN_NUMBER_TO_KICK])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.vht_support=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_VHT_SUPPORT])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].chan_util_avg_period=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL_AVG_PERIOD])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.no_ht_support=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_NO_HT_SUPPORT])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].set_hostapd_nr=%d", blobmsg_get_u32(tb_metric[UCI_SET_HOSTAPD_NR])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.no_vht_support=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_NO_VHT_SUPPORT])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].op_class=%d", blobmsg_get_u32(tb_metric[UCI_OP_CLASS])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.rssi=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_RSSI])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].duration=%d", blobmsg_get_u32(tb_metric[UCI_DURATION])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.rssi_val=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_RSSI_VAL])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].mode=%d", blobmsg_get_u32(tb_metric[UCI_MODE])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.low_rssi_val=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_LOW_RSSI_VAL])); + uci_set_network(cmd_buffer); - sprintf(cmd_buffer, "dawn.@metric[0].scan_channel=%d", blobmsg_get_u32(tb_metric[UCI_SCAN_CHANNEL])); - uci_set_network(cmd_buffer); + sprintf(cmd_buffer, "dawn.%s.low_rssi=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_LOW_RSSI])); + uci_set_network(cmd_buffer); + + sprintf(cmd_buffer, "dawn.%s.chan_util=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_CHAN_UTIL])); + uci_set_network(cmd_buffer); + + sprintf(cmd_buffer, "dawn.%s.chan_util_val=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_CHAN_UTIL_VAL])); + uci_set_network(cmd_buffer); + + sprintf(cmd_buffer, "dawn.%s.max_chan_util=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_MAX_CHAN_UTIL])); + uci_set_network(cmd_buffer); + + sprintf(cmd_buffer, "dawn.%s.max_chan_util_val=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_MAX_CHAN_UTIL_VAL])); + uci_set_network(cmd_buffer); + + sprintf(cmd_buffer, "dawn.%s.rssi_weight=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_RSSI_WEIGHT])); + uci_set_network(cmd_buffer); + + sprintf(cmd_buffer, "dawn.%s.rssi_center=%d", band_name, blobmsg_get_u32(tb_band_metric[UCI_RSSI_CENTER])); + uci_set_network(cmd_buffer); + } struct blob_attr* tb_times[__UCI_TIMES_MAX]; blobmsg_parse(uci_times_policy, __UCI_TIMES_MAX, tb_times, blobmsg_data(tb[UCI_TABLE_TIMES]), blobmsg_len(tb[UCI_TABLE_TIMES])); diff --git a/src/utils/ubus.c b/src/utils/ubus.c index 0c35592..739acf6 100644 --- a/src/utils/ubus.c +++ b/src/utils/ubus.c @@ -19,16 +19,6 @@ static struct ubus_context *ctx = NULL; -static struct blob_buf b; -static struct blob_buf b_send_network; -static struct blob_buf b_probe; -static struct blob_buf b_domain; -static struct blob_buf b_notify; -static struct blob_buf b_clients; -static struct blob_buf b_umdns; -static struct blob_buf b_beacon; -static struct blob_buf b_nr; - void update_clients(struct uloop_timeout *t); void update_tcp_connections(struct uloop_timeout *t); @@ -45,7 +35,7 @@ struct uloop_timeout client_timer = { struct uloop_timeout hostapd_timer = { .cb = update_hostapd_sockets }; -struct uloop_timeout umdns_timer = { +struct uloop_timeout tcp_con_timer = { .cb = update_tcp_connections }; struct uloop_timeout channel_utilization_timer = { @@ -96,7 +86,7 @@ struct hostapd_sock_entry { char iface_name[MAX_INTERFACE_NAME]; char hostname[HOST_NAME_MAX]; struct dawn_mac bssid_addr; - char ssid[SSID_MAX_LEN]; + char ssid[SSID_MAX_LEN + 1]; uint8_t ht_support; uint8_t vht_support; uint64_t last_channel_time; @@ -104,6 +94,7 @@ struct hostapd_sock_entry { int chan_util_samples_sum; int chan_util_num_sample_periods; int chan_util_average; //TODO: Never evaluated? + int band; // add neighbor report string /* @@ -145,6 +136,7 @@ enum { BEACON_REP_BSSID, BEACON_REP_ANTENNA_ID, BEACON_REP_PARENT_TSF, + BEACON_REP_SSID, __BEACON_REP_MAX, }; @@ -160,6 +152,7 @@ static const struct blobmsg_policy beacon_rep_policy[__BEACON_REP_MAX] = { [BEACON_REP_BSSID] = {.name = "bssid", .type = BLOBMSG_TYPE_STRING}, [BEACON_REP_ANTENNA_ID] = {.name = "antenna-id", .type = BLOBMSG_TYPE_INT16}, [BEACON_REP_PARENT_TSF] = {.name = "parent-tsf", .type = BLOBMSG_TYPE_INT16}, + [BEACON_REP_SSID] = {.name = "ssid", .type = BLOBMSG_TYPE_STRING}, }; enum { @@ -192,26 +185,26 @@ static const struct blobmsg_policy rrm_array_policy[__RRM_MAX] = { }; /* Function Definitions */ -static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj, +static int hostapd_notify(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); static int ubus_get_clients(); static int -add_mac(struct ubus_context *ctx, struct ubus_object *obj, +add_mac(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); -static int reload_config(struct ubus_context *ctx, struct ubus_object *obj, +static int reload_config(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); -static int get_hearing_map(struct ubus_context *ctx, struct ubus_object *obj, +static int get_hearing_map(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); -static int get_network(struct ubus_context *ctx, struct ubus_object *obj, +static int get_network(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); @@ -225,7 +218,7 @@ void subscribe_to_new_interfaces(const char *hostapd_sock_path); bool subscriber_to_interface(const char *ifname); -bool subscribe(struct hostapd_sock_entry *hostapd_entry); +bool subscribe(struct ubus_context *ctx_local, struct hostapd_sock_entry *hostapd_entry); int parse_to_beacon_rep(struct blob_attr *msg); @@ -272,7 +265,7 @@ static int decide_function(probe_entry *prob_req, int req_type) { // TODO: Bug? This results in copious "Neigbor-Report is NULL" messages! // find own probe entry and calculate score - ap* this_ap = ap_array_get_ap(prob_req->bssid_addr); + ap* this_ap = ap_array_get_ap(prob_req->bssid_addr, prob_req->ssid); if (this_ap != NULL && better_ap_available(this_ap, prob_req->client_addr, NULL)) { return 0; } @@ -330,7 +323,8 @@ int parse_to_beacon_rep(struct blob_attr *msg) { return -1; } - ap *ap_entry_rep = ap_array_get_ap(msg_bssid); + const uint8_t *ssid = (const uint8_t*)blobmsg_get_string(tb[BEACON_REP_SSID]); + ap *ap_entry_rep = ap_array_get_ap(msg_bssid, ssid); // no client from network!! if (ap_entry_rep == NULL) { @@ -345,12 +339,11 @@ int parse_to_beacon_rep(struct blob_attr *msg) { // HACKY WORKAROUND! - printf("Try update RCPI and RSNI for beacon report!\n"); if(!probe_array_update_rcpi_rsni(msg_bssid, msg_client, rcpi, rsni, true)) { - printf("Beacon: No Probe Entry Existing!\n"); probe_entry* beacon_rep = dawn_malloc(sizeof(probe_entry)); + probe_entry* beacon_rep_updated = NULL; if (beacon_rep == NULL) { fprintf(stderr, "dawn_malloc of probe_entry failed!\n"); @@ -360,6 +353,8 @@ int parse_to_beacon_rep(struct blob_attr *msg) { beacon_rep->next_probe = NULL; beacon_rep->bssid_addr = msg_bssid; beacon_rep->client_addr = msg_client; + strncpy((char*)beacon_rep->ssid, (char*)ssid, SSID_MAX_LEN); + beacon_rep->ssid[SSID_MAX_LEN] = '\0'; beacon_rep->counter = dawn_metric.min_probe_count; hwaddr_aton(blobmsg_data(tb[BEACON_REP_ADDR]), beacon_rep->target_addr.u8); // TODO: What is this for? beacon_rep->signal = 0; @@ -369,17 +364,17 @@ int parse_to_beacon_rep(struct blob_attr *msg) { beacon_rep->ht_capabilities = false; // that is very problematic!!! beacon_rep->vht_capabilities = false; // that is very problematic!!! - printf("Inserting to array!\n"); // TODO: kept original code order here - send on network first to simplify? - if (beacon_rep != insert_to_array(beacon_rep, false, false, true, time(0))) // use 802.11k values // TODO: Change 0 to false? + beacon_rep_updated = insert_to_array(beacon_rep, false, false, true, time(0)); + if (beacon_rep != beacon_rep_updated) // use 802.11k values // TODO: Change 0 to false? { // insert found an existing entry, rather than linking in our new one - ubus_send_probe_via_network(beacon_rep); + ubus_send_probe_via_network(beacon_rep_updated); dawn_free(beacon_rep); } else - ubus_send_probe_via_network(beacon_rep); + ubus_send_probe_via_network(beacon_rep_updated); } return 0; } @@ -388,15 +383,19 @@ int handle_auth_req(struct blob_attr* msg) { int ret = WLAN_STATUS_SUCCESS; bool discard_entry = true; +#ifndef DAWN_NO_OUTPUT print_probe_array(); +#endif auth_entry *auth_req = dawn_malloc(sizeof(struct auth_entry_s)); if (auth_req == NULL) return -1; parse_to_auth_req(msg, auth_req); +#ifndef DAWN_NO_OUTPUT printf("Auth entry: "); print_auth_entry(auth_req); +#endif if (!mac_in_maclist(auth_req->client_addr)) { pthread_mutex_lock(&probe_array_mutex); @@ -407,21 +406,12 @@ bool discard_entry = true; // block if entry was not already found in probe database if (tmp == NULL || !decide_function(tmp, REQ_TYPE_AUTH)) { - if (tmp != NULL) - { - printf("Entry found\n"); - printf("Deny authentication!\n"); - } - if (dawn_metric.use_driver_recog) { if (auth_req == insert_to_denied_req_array(auth_req, 1, time(0))) discard_entry = false; } ret = dawn_metric.deny_auth_reason; } - else - // maybe send here that the client is connected? - printf("Allow authentication!\n"); } if (discard_entry) @@ -434,14 +424,18 @@ static int handle_assoc_req(struct blob_attr *msg) { int ret = WLAN_STATUS_SUCCESS; int discard_entry = true; +#ifndef DAWN_NO_OUTPUT print_probe_array(); +#endif auth_entry* auth_req = dawn_malloc(sizeof(struct auth_entry_s)); if (auth_req == NULL) return -1; parse_to_assoc_req(msg, auth_req); +#ifndef DAWN_NO_OUTPUT printf("Association entry: "); print_auth_entry(auth_req); +#endif if (!mac_in_maclist(auth_req->client_addr)) { pthread_mutex_lock(&probe_array_mutex); @@ -452,21 +446,12 @@ int discard_entry = true; // block if entry was not already found in probe database if (tmp == NULL || !decide_function(tmp, REQ_TYPE_ASSOC)) { - if (tmp != NULL) - { - printf("Entry found\n"); - print_probe_entry(tmp); - } - - printf("Deny associtation!\n"); if (dawn_metric.use_driver_recog) { if (auth_req == insert_to_denied_req_array(auth_req, 1, time(0))) discard_entry = false; } return dawn_metric.deny_assoc_reason; } - else - printf("Allow association!\n"); } if (discard_entry) @@ -476,38 +461,32 @@ int discard_entry = true; } static int handle_probe_req(struct blob_attr *msg) { + // MUSTDO: Untangle dawn_malloc() and linking of probe_entry probe_entry* probe_req = parse_to_probe_req(msg); - if (probe_req == NULL) - // TODO: Is this right? SHould we do something else? - return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - else { - // we get the same probe_req back if it is added to the list - // or the one actually used if it is an update to existing - // use 802.11k values - if (probe_req != insert_to_array(probe_req, true, true, false, time(0))) - { - ubus_send_probe_via_network(probe_req); + probe_entry* probe_req_updated = NULL; + + if (probe_req != NULL) { + probe_req_updated = insert_to_array(probe_req, true, true, false, time(0)); + // If insert finds an existing entry, rather than linking in our new one, + // send new probe req because we want to stay synced. + // If not, probe_req and probe_req_updated should be equivalent + if (probe_req != probe_req_updated) dawn_free(probe_req); - } - else - ubus_send_probe_via_network(probe_req); + ubus_send_probe_via_network(probe_req_updated); - //send_blob_attr_via_network(msg, "probe"); - - if (!decide_function(probe_req, REQ_TYPE_PROBE)) { + if (!decide_function(probe_req_updated, REQ_TYPE_PROBE)) { return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; // no reason needed... } } + // TODO: Return for dawn_malloc() failure? return WLAN_STATUS_SUCCESS; } static int handle_beacon_rep(struct blob_attr *msg) { if (parse_to_beacon_rep(msg) == 0) { - printf("Inserting beacon Report!\n"); // insert_to_array(beacon_rep, 1); - printf("Sending via network!\n"); // send_blob_attr_via_network(msg, "beacon-report"); } return 0; @@ -522,16 +501,19 @@ int send_blob_attr_via_network(struct blob_attr* msg, char* method) { char *data_str; char *str; + struct blob_buf b = {0}; + data_str = blobmsg_format_json(msg, true); dawn_regmem(data_str); - blob_buf_init(&b_send_network, 0); - blobmsg_add_string(&b_send_network, "method", method); - blobmsg_add_string(&b_send_network, "data", data_str); + blob_buf_init(&b, 0); + blobmsg_add_string(&b, "method", method); + blobmsg_add_string(&b, "data", data_str); - str = blobmsg_format_json(b_send_network.head, true); + str = blobmsg_format_json(b.head, true); dawn_regmem(str); - if (network_config.network_option == 2) { + if (network_config.network_option == 2 + || network_config.network_option == 3) { send_tcp(str); } else { if (network_config.use_symm_enc) { @@ -541,24 +523,27 @@ int send_blob_attr_via_network(struct blob_attr* msg, char* method) { } } - dawn_free(str); dawn_free(data_str); + dawn_free(str); + blob_buf_free(&b); return 0; } -static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj, +static int hostapd_notify(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { -// TODO: Churns a lot of unnecessary memory - remove for now -#if 0 char *str; + int ret = 0; + struct blob_buf b = {0}; + str = blobmsg_format_json(msg, true); dawn_regmem(str); +#ifndef DAWN_NO_OUTPUT printf("Method new: %s : %s\n", method, str); - dawn_free(str); #endif + dawn_free(str); struct hostapd_sock_entry *entry; struct ubus_subscriber *subscriber; @@ -567,27 +552,30 @@ static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj, entry = container_of(subscriber, struct hostapd_sock_entry, subscriber); struct blob_attr *cur; int rem; - blob_buf_init(&b_notify, 0); + blob_buf_init(&b, 0); blobmsg_for_each_attr(cur, msg, rem){ - blobmsg_add_blob(&b_notify, cur); + blobmsg_add_blob(&b, cur); } - blobmsg_add_macaddr(&b_notify, "bssid", entry->bssid_addr); - blobmsg_add_string(&b_notify, "ssid", entry->ssid); + blobmsg_add_macaddr(&b, "bssid", entry->bssid_addr); + blobmsg_add_string(&b, "ssid", entry->ssid); if (strncmp(method, "probe", 5) == 0) { - return handle_probe_req(b_notify.head); + ret = handle_probe_req(b.head); } else if (strncmp(method, "auth", 4) == 0) { - return handle_auth_req(b_notify.head); + ret = handle_auth_req(b.head); } else if (strncmp(method, "assoc", 5) == 0) { - return handle_assoc_req(b_notify.head); + ret = handle_assoc_req(b.head); } else if (strncmp(method, "deauth", 6) == 0) { - send_blob_attr_via_network(b_notify.head, "deauth"); - return handle_deauth_req(b_notify.head); + send_blob_attr_via_network(b.head, "deauth"); + ret = handle_deauth_req(b.head); } else if (strncmp(method, "beacon-report", 12) == 0) { - return handle_beacon_rep(b_notify.head); + ret = handle_beacon_rep(b.head); } - return 0; + + blob_buf_free(&b); + + return ret; } int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) { @@ -599,7 +587,6 @@ int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) { fprintf(stderr, "Failed to connect to ubus\n"); return -1; } else { - printf("Connected to ubus\n"); dawn_regmem(ctx); } @@ -625,9 +612,10 @@ int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) { ubus_add_oject(); - if (network_config.network_option == 2) + if (network_config.network_option == 2 + || network_config.network_option == 3) { - start_umdns_update(); + start_tcp_con_update(); if(run_server(network_config.tcp_port)) uloop_timeout_set(&usock_timer, 1 * 1000); } @@ -644,8 +632,18 @@ int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) { return 0; } +static int get_band_from_bssid(struct dawn_mac bssid) { + ap *a; + for (a = ap_set; a; a = a->next_ap) { + if (mac_is_equal_bb(a->bssid_addr, bssid)) + return get_band(a->freq); + } + return -1; +} + static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_attr *msg) { struct hostapd_sock_entry *sub, *entry = NULL; + struct blob_buf b = {0}; if (!msg) return; @@ -659,44 +657,50 @@ static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_ if (entry == NULL) { fprintf(stderr, "Failed to find interface!\n"); + blob_buf_free(&b); return; } if (!entry->subscribed) { fprintf(stderr, "Interface %s is not subscribed!\n", entry->iface_name); + blob_buf_free(&b); return; } char *data_str = blobmsg_format_json(msg, 1); dawn_regmem(data_str); - blob_buf_init(&b_domain, 0); - blobmsg_add_json_from_string(&b_domain, data_str); - blobmsg_add_u32(&b_domain, "collision_domain", network_config.collision_domain); - blobmsg_add_u32(&b_domain, "bandwidth", network_config.bandwidth); + blob_buf_init(&b, 0); + blobmsg_add_json_from_string(&b, data_str); + blobmsg_add_u32(&b, "collision_domain", network_config.collision_domain); + blobmsg_add_u32(&b, "bandwidth", network_config.bandwidth); - blobmsg_add_macaddr(&b_domain, "bssid", entry->bssid_addr); - blobmsg_add_string(&b_domain, "ssid", entry->ssid); - blobmsg_add_u8(&b_domain, "ht_supported", entry->ht_support); - blobmsg_add_u8(&b_domain, "vht_supported", entry->vht_support); + blobmsg_add_macaddr(&b, "bssid", entry->bssid_addr); + blobmsg_add_string(&b, "ssid", entry->ssid); + blobmsg_add_u8(&b, "ht_supported", entry->ht_support); + blobmsg_add_u8(&b, "vht_supported", entry->vht_support); - blobmsg_add_u32(&b_domain, "ap_weight", dawn_metric.ap_weight); + if (entry->band < 0) + entry->band = get_band_from_bssid(entry->bssid_addr); + if (entry->band >= 0) + blobmsg_add_u32(&b, "ap_weight", dawn_metric.ap_weight[entry->band]); //int channel_util = get_channel_utilization(entry->iface_name, &entry->last_channel_time, &entry->last_channel_time_busy); - blobmsg_add_u32(&b_domain, "channel_utilization", entry->chan_util_average); + blobmsg_add_u32(&b, "channel_utilization", entry->chan_util_average); - blobmsg_add_string(&b_domain, "neighbor_report", entry->neighbor_report); + blobmsg_add_string(&b, "neighbor_report", entry->neighbor_report); - blobmsg_add_string(&b_domain, "iface", entry->iface_name); - blobmsg_add_string(&b_domain, "hostname", entry->hostname); + blobmsg_add_string(&b, "iface", entry->iface_name); + blobmsg_add_string(&b, "hostname", entry->hostname); - send_blob_attr_via_network(b_domain.head, "clients"); + send_blob_attr_via_network(b.head, "clients"); // TODO: Have we just bit-packed data to send to something locally to unpack it again? Performance / scalability? - parse_to_clients(b_domain.head, 1, req->peer); + parse_to_clients(b.head, 1, req->peer); print_client_array(); print_ap_array(); dawn_free(data_str); + blob_buf_free(&b); } static int ubus_get_clients() { @@ -705,8 +709,10 @@ static int ubus_get_clients() { list_for_each_entry(sub, &hostapd_sock_list, list) { if (sub->subscribed) { - blob_buf_init(&b_clients, 0); - ubus_invoke(ctx, sub->id, "get_clients", b_clients.head, ubus_get_clients_cb, NULL, timeout * 1000); + struct blob_buf b = {0}; + blob_buf_init(&b, 0); + ubus_invoke(ctx, sub->id, "get_clients", b.head, ubus_get_clients_cb, NULL, timeout * 1000); + blob_buf_free(&b); } } return 0; @@ -740,9 +746,8 @@ static void ubus_get_rrm_cb(struct ubus_request *req, int type, struct blob_attr { if(i==2) { - char* neighborreport = blobmsg_get_string(blobmsg_data(attr)); + char* neighborreport = blobmsg_get_string(attr); strcpy(entry->neighbor_report,neighborreport); - printf("Copied Neighborreport: %s,\n", entry->neighbor_report); } i++; } @@ -751,11 +756,14 @@ static void ubus_get_rrm_cb(struct ubus_request *req, int type, struct blob_attr static int ubus_get_rrm() { int timeout = 1; struct hostapd_sock_entry *sub; + list_for_each_entry(sub, &hostapd_sock_list, list) { if (sub->subscribed) { + struct blob_buf b = {0}; blob_buf_init(&b, 0); ubus_invoke(ctx, sub->id, "rrm_nr_get_own", b.head, ubus_get_rrm_cb, NULL, timeout * 1000); + blob_buf_free(&b); } } return 0; @@ -795,48 +803,70 @@ 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) -{ - printf("Crafting Beacon Report\n"); - int timeout = 1; - blob_buf_init(&b_beacon, 0); - blobmsg_add_macaddr(&b_beacon, "addr", client); - 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); - printf("Adding string\n"); - blobmsg_add_string(&b_beacon, "ssid", ""); +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; +} - printf("Invoking beacon report!\n"); - ubus_invoke(ctx, id, "rrm_beacon_req", b_beacon.head, NULL, NULL, timeout * 1000); +void ubus_send_beacon_report(client *c, ap *a, int id) +{ + struct blob_buf b = {0}; + int timeout = 1; + + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "addr", c->client_addr); + blobmsg_add_u32(&b, "op_class", a->op_class); + blobmsg_add_u32(&b, "channel", a->channel); + blobmsg_add_u32(&b, "duration", dawn_metric.duration); + blobmsg_add_u32(&b, "mode", get_mode_from_capability(c->rrm_enabled_capa)); + blobmsg_add_string(&b, "ssid", (char*)a->ssid); + + ubus_invoke(ctx, id, "rrm_beacon_req", b.head, NULL, NULL, timeout * 1000); + blob_buf_free(&b); } void update_beacon_reports(struct uloop_timeout *t) { + ap *a; + if(!timeout_config.update_beacon_reports) // if 0 just return { return; } - printf("Sending beacon report!\n"); struct hostapd_sock_entry *sub; list_for_each_entry(sub, &hostapd_sock_list, list) { - if (sub->subscribed) { - printf("Sending beacon report Sub!\n"); - send_beacon_reports(sub->bssid_addr, sub->id); + if (sub->subscribed && (a = ap_array_get_ap(sub->bssid_addr, (uint8_t*)sub->ssid))) { + send_beacon_reports(a, sub->id); } } uloop_timeout_set(&beacon_reports_timer, timeout_config.update_beacon_reports * 1000); } void update_tcp_connections(struct uloop_timeout *t) { - ubus_call_umdns(); - uloop_timeout_set(&umdns_timer, timeout_config.update_tcp_con * 1000); + if (strcmp(network_config.server_ip, "")) + { + // nothing happens if tcp connection is already established + add_tcp_conncection(network_config.server_ip, network_config.tcp_port); + } + if (network_config.network_option == 2) // mdns enabled? + { + ubus_call_umdns(); + } + uloop_timeout_set(&tcp_con_timer, timeout_config.update_tcp_con * 1000); } -void start_umdns_update() { +void start_tcp_con_update() { // update connections - uloop_timeout_add(&umdns_timer); // callback = update_tcp_connections + uloop_timeout_add(&tcp_con_timer); // callback = update_tcp_connections } void update_hostapd_sockets(struct uloop_timeout *t) { @@ -846,21 +876,23 @@ void update_hostapd_sockets(struct uloop_timeout *t) { void ubus_set_nr(){ struct hostapd_sock_entry *sub; - + int timeout = 1; list_for_each_entry(sub, &hostapd_sock_list, list) { if (sub->subscribed) { - int timeout = 1; - blob_buf_init(&b_nr, 0); - ap_get_nr(&b_nr, sub->bssid_addr); - ubus_invoke(ctx, sub->id, "rrm_nr_set", b_nr.head, NULL, NULL, timeout * 1000); + struct blob_buf b = {0}; + blob_buf_init(&b, 0); + ap_get_nr(&b, sub->bssid_addr, sub->ssid); + ubus_invoke(ctx, sub->id, "rrm_nr_set", b.head, NULL, NULL, timeout * 1000); + blob_buf_free(&b); } } } void del_client_all_interfaces(const struct dawn_mac client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) { struct hostapd_sock_entry *sub; + struct blob_buf b = {0}; blob_buf_init(&b, 0); blobmsg_add_macaddr(&b, "addr", client_addr); @@ -875,10 +907,12 @@ void del_client_all_interfaces(const struct dawn_mac client_addr, uint32_t reaso ubus_invoke(ctx, sub->id, "del_client", b.head, NULL, NULL, timeout * 1000); } } + blob_buf_free(&b); } void del_client_interface(uint32_t id, const struct dawn_mac client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) { struct hostapd_sock_entry *sub; + struct blob_buf b = {0}; blob_buf_init(&b, 0); blobmsg_add_macaddr(&b, "addr", client_addr); @@ -894,23 +928,25 @@ void del_client_interface(uint32_t id, const struct dawn_mac client_addr, uint32 ubus_invoke(ctx, id, "del_client", b.head, NULL, NULL, timeout * 1000); } } - + blob_buf_free(&b); } -int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, char *dest_ap, uint32_t duration) { +int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, uint32_t duration) { struct hostapd_sock_entry *sub; + struct blob_buf b = {0}; blob_buf_init(&b, 0); blobmsg_add_macaddr(&b, "addr", client_addr); blobmsg_add_u32(&b, "duration", duration); blobmsg_add_u8(&b, "abridged", 1); // prefer aps in neighborlist - // ToDo: maybe exchange to a list of aps void* nbs = blobmsg_open_array(&b, "neighbors"); - if (dest_ap != NULL) - { - blobmsg_add_string(&b, NULL, dest_ap); - printf("BSS TRANSITION TO %s\n", dest_ap); + while(neighbor_list != NULL) { +#ifndef DAWN_NO_OUTPUT + printf("BSS TRANSITION NEIGHBOR " NR_MACSTR ", Score=%d\n", NR_MAC2STR(neighbor_list->nr), neighbor_list->score); +#endif + blobmsg_add_string(&b, NULL, neighbor_list->nr); + neighbor_list = neighbor_list->next; } blobmsg_close_array(&b, nbs); @@ -922,6 +958,8 @@ int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, char * } } + blob_buf_free(&b); + return 0; } @@ -938,20 +976,23 @@ static void ubus_umdns_cb(struct ubus_request *req, int type, struct blob_attr * } struct blob_attr *attr; - struct blobmsg_hdr *hdr; int len = blobmsg_data_len(tb[DAWN_UMDNS_TABLE]); __blob_for_each_attr(attr, blobmsg_data(tb[DAWN_UMDNS_TABLE]), len) { - hdr = blob_data(attr); +#ifndef DAWN_NO_OUTPUT + struct blobmsg_hdr *hdr = blob_data(attr); + printf("Hostname: %s\n", hdr->name); +#endif struct blob_attr *tb_dawn[__DAWN_UMDNS_MAX]; blobmsg_parse(dawn_umdns_policy, __DAWN_UMDNS_MAX, tb_dawn, blobmsg_data(attr), blobmsg_len(attr)); - printf("Hostname: %s\n", hdr->name); if (tb_dawn[DAWN_UMDNS_IPV4] && tb_dawn[DAWN_UMDNS_PORT]) { +#ifndef DAWN_NO_OUTPUT printf("IPV4: %s\n", blobmsg_get_string(tb_dawn[DAWN_UMDNS_IPV4])); printf("Port: %d\n", blobmsg_get_u32(tb_dawn[DAWN_UMDNS_PORT])); +#endif } else { return; } @@ -961,32 +1002,40 @@ static void ubus_umdns_cb(struct ubus_request *req, int type, struct blob_attr * int ubus_call_umdns() { u_int32_t id; + struct blob_buf b = {0}; + if (ubus_lookup_id(ctx, "umdns", &id)) { fprintf(stderr, "Failed to look up test object for %s\n", "umdns"); return -1; } int timeout = 1; - blob_buf_init(&b_umdns, 0); - ubus_invoke(ctx, id, "update", b_umdns.head, NULL, NULL, timeout * 1000); - ubus_invoke(ctx, id, "browse", b_umdns.head, ubus_umdns_cb, NULL, timeout * 1000); + blob_buf_init(&b, 0); + ubus_invoke(ctx, id, "update", b.head, NULL, NULL, timeout * 1000); + ubus_invoke(ctx, id, "browse", b.head, ubus_umdns_cb, NULL, timeout * 1000); + blob_buf_free(&b); return 0; } //TODO: ADD STUFF HERE!!!! int ubus_send_probe_via_network(struct probe_entry_s *probe_entry) { // TODO: probe_entry is also a typedef - fix? - blob_buf_init(&b_probe, 0); - blobmsg_add_macaddr(&b_probe, "bssid", probe_entry->bssid_addr); - blobmsg_add_macaddr(&b_probe, "address", probe_entry->client_addr); - blobmsg_add_macaddr(&b_probe, "target", probe_entry->target_addr); - blobmsg_add_u32(&b_probe, "signal", probe_entry->signal); - blobmsg_add_u32(&b_probe, "freq", probe_entry->freq); + struct blob_buf b = {0}; - blobmsg_add_u32(&b_probe, "rcpi", probe_entry->rcpi); - blobmsg_add_u32(&b_probe, "rsni", probe_entry->rsni); + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "bssid", probe_entry->bssid_addr); + blobmsg_add_macaddr(&b, "address", probe_entry->client_addr); + blobmsg_add_macaddr(&b, "target", probe_entry->target_addr); + blobmsg_add_u32(&b, "signal", probe_entry->signal); + blobmsg_add_u32(&b, "freq", probe_entry->freq); - if (probe_entry->ht_capabilities) + blobmsg_add_u32(&b, "rcpi", probe_entry->rcpi); + blobmsg_add_u32(&b, "rsni", probe_entry->rsni); + + blobmsg_add_u32(&b, "ht_capabilities", probe_entry->ht_capabilities); + blobmsg_add_u32(&b, "vht_capabilities", probe_entry->vht_capabilities); + + /*if (probe_entry->ht_capabilities) { void *ht_cap = blobmsg_open_table(&b, "ht_capabilities"); blobmsg_close_table(&b, ht_cap); @@ -995,19 +1044,25 @@ int ubus_send_probe_via_network(struct probe_entry_s *probe_entry) { // TODO: p if (probe_entry->vht_capabilities) { void *vht_cap = blobmsg_open_table(&b, "vht_capabilities"); blobmsg_close_table(&b, vht_cap); - } + }*/ - send_blob_attr_via_network(b_probe.head, "probe"); + send_blob_attr_via_network(b.head, "probe"); + + blob_buf_free(&b); return 0; } int send_set_probe(struct dawn_mac client_addr) { - blob_buf_init(&b_probe, 0); - blobmsg_add_macaddr(&b_probe, "bssid", client_addr); - blobmsg_add_macaddr(&b_probe, "address", client_addr); + struct blob_buf b = {0}; - send_blob_attr_via_network(b_probe.head, "setprobe"); + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "bssid", client_addr); + blobmsg_add_macaddr(&b, "address", client_addr); + + send_blob_attr_via_network(b.head, "setprobe"); + + blob_buf_free(&b); return 0; } @@ -1042,19 +1097,15 @@ int parse_add_mac_to_file(struct blob_attr *msg) { struct blob_attr *tb[__ADD_DEL_MAC_MAX]; struct blob_attr *attr; - printf("Parsing MAC!\n"); - blobmsg_parse(add_del_policy, __ADD_DEL_MAC_MAX, tb, blob_data(msg), blob_len(msg)); if (!tb[MAC_ADDR]) return UBUS_STATUS_INVALID_ARGUMENT; int len = blobmsg_data_len(tb[MAC_ADDR]); - printf("Length of array maclist: %d\n", len); __blob_for_each_attr(attr, blobmsg_data(tb[MAC_ADDR]), len) { - printf("Iteration through MAC-list\n"); struct dawn_mac addr; hwaddr_aton(blobmsg_data(attr), addr.u8); @@ -1068,7 +1119,7 @@ int parse_add_mac_to_file(struct blob_attr *msg) { return 0; } -static int add_mac(struct ubus_context *ctx, struct ubus_object *obj, +static int add_mac(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { parse_add_mac_to_file(msg); @@ -1079,17 +1130,12 @@ static int add_mac(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -int send_add_mac(struct dawn_mac client_addr) { - blob_buf_init(&b, 0); - blobmsg_add_macaddr(&b, "addr", client_addr); - send_blob_attr_via_network(b.head, "addmac"); - return 0; -} - -static int reload_config(struct ubus_context *ctx, struct ubus_object *obj, +static int reload_config(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { int ret; + struct blob_buf b = {0}; + blob_buf_init(&b, 0); uci_reset(); dawn_metric = uci_get_dawn_metric(); @@ -1101,34 +1147,45 @@ static int reload_config(struct ubus_context *ctx, struct ubus_object *obj, uloop_timeout_add(&beacon_reports_timer); // callback = update_beacon_reports uci_send_via_network(); - ret = ubus_send_reply(ctx, req, b.head); + ret = ubus_send_reply(ctx_local, req, b.head); if (ret) fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret)); + + blob_buf_free(&b); + return 0; } -static int get_hearing_map(struct ubus_context *ctx, struct ubus_object *obj, +static int get_hearing_map(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { int ret; + struct blob_buf b = {0}; + blob_buf_init(&b, 0); build_hearing_map_sort_client(&b); - ret = ubus_send_reply(ctx, req, b.head); + ret = ubus_send_reply(ctx_local, req, b.head); if (ret) fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret)); + blob_buf_free(&b); + return 0; } -static int get_network(struct ubus_context *ctx, struct ubus_object *obj, +static int get_network(struct ubus_context *ctx_local, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { int ret; + struct blob_buf b = {0}; + blob_buf_init(&b, 0); build_network_overview(&b); - ret = ubus_send_reply(ctx, req, b.head); + ret = ubus_send_reply(ctx_local, req, b.head); if (ret) fprintf(stderr, "Failed to send reply: %s\n", ubus_strerror(ret)); + blob_buf_free(&b); + return 0; } @@ -1145,18 +1202,22 @@ static void respond_to_notify(uint32_t id) { // Maybe we need to disable on shutdown... // But it is not possible when we disable the notify that other daemons are running that relay on this notify... int ret; + struct blob_buf b = {0}; + int timeout = 1; blob_buf_init(&b, 0); blobmsg_add_u32(&b, "notify_response", 1); - int timeout = 1; ret = ubus_invoke(ctx, id, "notify_response", b.head, NULL, NULL, timeout * 1000); if (ret) fprintf(stderr, "Failed to invoke: %s\n", ubus_strerror(ret)); + + blob_buf_free(&b); } static void enable_rrm(uint32_t id) { int ret; + struct blob_buf b = {0}; blob_buf_init(&b, 0); blobmsg_add_u8(&b, "neighbor_report", 1); @@ -1167,16 +1228,16 @@ static void enable_rrm(uint32_t id) { ret = ubus_invoke(ctx, id, "bss_mgmt_enable", b.head, NULL, NULL, timeout * 1000); if (ret) fprintf(stderr, "Failed to invoke: %s\n", ubus_strerror(ret)); + + blob_buf_free(&b); } -static void hostapd_handle_remove(struct ubus_context *ctx, +static void hostapd_handle_remove(struct ubus_context *ctx_local, struct ubus_subscriber *s, uint32_t id) { - fprintf(stdout, "Object %08x went away\n", id); struct hostapd_sock_entry *hostapd_sock = container_of(s, struct hostapd_sock_entry, subscriber); if (hostapd_sock->id != id) { - printf("ID is not the same!\n"); return; } @@ -1185,7 +1246,7 @@ static void hostapd_handle_remove(struct ubus_context *ctx, } -bool subscribe(struct hostapd_sock_entry *hostapd_entry) { +bool subscribe(struct ubus_context *ctx_local, struct hostapd_sock_entry *hostapd_entry) { char subscribe_name[sizeof("hostapd.") + MAX_INTERFACE_NAME + 1]; if (hostapd_entry->subscribed) @@ -1193,13 +1254,13 @@ bool subscribe(struct hostapd_sock_entry *hostapd_entry) { sprintf(subscribe_name, "hostapd.%s", hostapd_entry->iface_name); - if (ubus_lookup_id(ctx, subscribe_name, &hostapd_entry->id)) { + if (ubus_lookup_id(ctx_local, subscribe_name, &hostapd_entry->id)) { fprintf(stdout, "Failed to lookup ID!"); subscription_wait(&hostapd_entry->wait_handler); return false; } - if (ubus_subscribe(ctx, &hostapd_entry->subscriber, hostapd_entry->id)) { + if (ubus_subscribe(ctx_local, &hostapd_entry->subscriber, hostapd_entry->id)) { fprintf(stdout, "Failed to register subscriber!"); subscription_wait(&hostapd_entry->wait_handler); return false; @@ -1209,21 +1270,21 @@ bool subscribe(struct hostapd_sock_entry *hostapd_entry) { get_bssid(hostapd_entry->iface_name, hostapd_entry->bssid_addr.u8); get_ssid(hostapd_entry->iface_name, hostapd_entry->ssid, (SSID_MAX_LEN) * sizeof(char)); + hostapd_entry->ssid[SSID_MAX_LEN] = '\0'; hostapd_entry->ht_support = (uint8_t) support_ht(hostapd_entry->iface_name); hostapd_entry->vht_support = (uint8_t) support_vht(hostapd_entry->iface_name); + hostapd_entry->band = -1; respond_to_notify(hostapd_entry->id); enable_rrm(hostapd_entry->id); ubus_get_rrm(); - printf("Subscribed to: %s\n", hostapd_entry->iface_name); - return true; } static void -wait_cb(struct ubus_context *ctx, struct ubus_event_handler *ev_handler, +wait_cb(struct ubus_context *ctx_local, struct ubus_event_handler *ev_handler, const char *type, struct blob_attr *msg) { static const struct blobmsg_policy wait_policy = { "path", BLOBMSG_TYPE_STRING @@ -1232,7 +1293,7 @@ wait_cb(struct ubus_context *ctx, struct ubus_event_handler *ev_handler, struct blob_attr *attr; const char *path; struct hostapd_sock_entry *sub = container_of(ev_handler, - struct hostapd_sock_entry, wait_handler); + struct hostapd_sock_entry, wait_handler); if (strcmp(type, "ubus.object.add")) return; @@ -1250,7 +1311,7 @@ wait_cb(struct ubus_context *ctx, struct ubus_event_handler *ev_handler, if (strcmp(sub->iface_name, path + 1)) return; - subscribe(sub); + subscribe(ctx_local, sub); } bool subscriber_to_interface(const char *ifname) { @@ -1276,7 +1337,7 @@ bool subscriber_to_interface(const char *ifname) { list_add(&hostapd_entry->list, &hostapd_sock_list); - return subscribe(hostapd_entry); + return subscribe(ctx, hostapd_entry); } void subscribe_to_new_interfaces(const char *hostapd_sock_path) { @@ -1315,27 +1376,36 @@ 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; + void *metric, *times, *band_table, *band_entry; + struct blob_buf b = {0}; blob_buf_init(&b, 0); + blobmsg_add_string(&b, "version", DAWN_CONFIG_VERSION); metric = blobmsg_open_table(&b, "metric"); - blobmsg_add_u32(&b, "ht_support", dawn_metric.ht_support); - blobmsg_add_u32(&b, "vht_support", dawn_metric.vht_support); - blobmsg_add_u32(&b, "no_ht_support", dawn_metric.no_ht_support); - blobmsg_add_u32(&b, "no_vht_support", dawn_metric.no_vht_support); - blobmsg_add_u32(&b, "rssi", dawn_metric.rssi); - blobmsg_add_u32(&b, "low_rssi", dawn_metric.low_rssi); - blobmsg_add_u32(&b, "freq", dawn_metric.freq); - blobmsg_add_u32(&b, "chan_util", dawn_metric.chan_util); - - blobmsg_add_u32(&b, "max_chan_util", dawn_metric.max_chan_util); - blobmsg_add_u32(&b, "rssi_val", dawn_metric.rssi_val); - blobmsg_add_u32(&b, "low_rssi_val", dawn_metric.low_rssi_val); - blobmsg_add_u32(&b, "chan_util_val", dawn_metric.chan_util_val); - blobmsg_add_u32(&b, "max_chan_util_val", dawn_metric.max_chan_util_val); blobmsg_add_u32(&b, "min_probe_count", dawn_metric.min_probe_count); blobmsg_add_u32(&b, "bandwidth_threshold", dawn_metric.bandwidth_threshold); blobmsg_add_u32(&b, "use_station_count", dawn_metric.use_station_count); @@ -1344,16 +1414,39 @@ int uci_send_via_network() blobmsg_add_u32(&b, "eval_auth_req", dawn_metric.eval_auth_req); blobmsg_add_u32(&b, "eval_assoc_req", dawn_metric.eval_assoc_req); blobmsg_add_u32(&b, "kicking", dawn_metric.kicking); + blobmsg_add_u32(&b, "kicking_threshold", dawn_metric.kicking_threshold); blobmsg_add_u32(&b, "deny_auth_reason", dawn_metric.deny_auth_reason); blobmsg_add_u32(&b, "deny_assoc_reason", dawn_metric.deny_assoc_reason); blobmsg_add_u32(&b, "use_driver_recog", dawn_metric.use_driver_recog); - blobmsg_add_u32(&b, "min_number_to_kick", dawn_metric.min_kick_count); + blobmsg_add_u32(&b, "min_number_to_kick", dawn_metric.min_number_to_kick); blobmsg_add_u32(&b, "chan_util_avg_period", dawn_metric.chan_util_avg_period); 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_u32(&b, "scan_channel", dawn_metric.scan_channel); + blobmsg_add_string(&b, "rrm_mode", get_rrm_mode_string(dawn_metric.rrm_mode_order)); + band_table = blobmsg_open_table(&b, "band_metrics"); + + for (int band=0; band < __DAWN_BAND_MAX; band++) { + band_entry = blobmsg_open_table(&b, band_config_name[band]); + blobmsg_add_u32(&b, "initial_score", dawn_metric.initial_score[band]); + blobmsg_add_u32(&b, "ap_weight", dawn_metric.ap_weight[band]); + blobmsg_add_u32(&b, "ht_support", dawn_metric.ht_support[band]); + blobmsg_add_u32(&b, "vht_support", dawn_metric.vht_support[band]); + blobmsg_add_u32(&b, "no_ht_support", dawn_metric.no_ht_support[band]); + blobmsg_add_u32(&b, "no_vht_support", dawn_metric.no_vht_support[band]); + blobmsg_add_u32(&b, "rssi", dawn_metric.rssi[band]); + blobmsg_add_u32(&b, "rssi_val", dawn_metric.rssi_val[band]); + blobmsg_add_u32(&b, "low_rssi", dawn_metric.low_rssi[band]); + blobmsg_add_u32(&b, "low_rssi_val", dawn_metric.low_rssi_val[band]); + blobmsg_add_u32(&b, "chan_util", dawn_metric.chan_util[band]); + blobmsg_add_u32(&b, "max_chan_util", dawn_metric.max_chan_util[band]); + blobmsg_add_u32(&b, "chan_util_val", dawn_metric.chan_util_val[band]); + blobmsg_add_u32(&b, "max_chan_util_val", dawn_metric.max_chan_util_val[band]); + blobmsg_add_u32(&b, "rssi_weight", dawn_metric.rssi_weight[band]); + blobmsg_add_u32(&b, "rssi_center", dawn_metric.rssi_center[band]); + blobmsg_close_table(&b, band_entry); + } + blobmsg_close_table(&b, band_table); + blobmsg_close_table(&b, metric); times = blobmsg_open_table(&b, "times"); @@ -1370,11 +1463,12 @@ int uci_send_via_network() send_blob_attr_via_network(b.head, "uci"); + blob_buf_free(&b); + return 0; } int build_hearing_map_sort_client(struct blob_buf *b) { - print_probe_array(); pthread_mutex_lock(&probe_array_mutex); void *client_list, *ap_list, *ssid_list; @@ -1382,8 +1476,6 @@ int build_hearing_map_sort_client(struct blob_buf *b) { char client_mac_buf[20]; bool same_ssid = false; - blob_buf_init(b, 0); - for (ap* m = ap_set; m != NULL; m = m->next_ap) { // MUSTDO: Ensure SSID / BSSID ordering. Lost when switched to linked list! // Scan AP list to find first of each SSID @@ -1391,7 +1483,7 @@ int build_hearing_map_sort_client(struct blob_buf *b) { ssid_list = blobmsg_open_table(b, (char*)m->ssid); probe_entry* i = probe_set; while (i != NULL) { - ap *ap_entry_i = ap_array_get_ap(i->bssid_addr); + ap *ap_entry_i = ap_array_get_ap(i->bssid_addr, m->ssid); if (ap_entry_i == NULL) { i = i->next_probe; @@ -1410,7 +1502,7 @@ int build_hearing_map_sort_client(struct blob_buf *b) { k != NULL && mac_is_equal_bb(k->client_addr, i->client_addr); k = k->next_probe) { - ap *ap_k = ap_array_get_ap(k->bssid_addr); + ap *ap_k = ap_array_get_ap(k->bssid_addr, m->ssid); if (ap_k == NULL || strcmp((char*)ap_k->ssid, (char*)m->ssid) != 0) { continue; @@ -1462,8 +1554,6 @@ int build_network_overview(struct blob_buf *b) { char client_mac_buf[20]; struct hostapd_sock_entry *sub; - blob_buf_init(b, 0); - bool add_ssid = true; for (ap* m = ap_set; m != NULL; m = m->next_ap) { if(add_ssid) @@ -1546,39 +1636,65 @@ int build_network_overview(struct blob_buf *b) { add_ssid = true; } } + return 0; } +static void blobmsg_add_nr(struct blob_buf *b_local, ap *i) { + void* nr_entry = blobmsg_open_array(b_local, NULL); + char mac_buf[20]; + sprintf(mac_buf, MACSTRLOWER, MAC2STR(i->bssid_addr.u8)); + blobmsg_add_string(b_local, NULL, mac_buf); + + blobmsg_add_string(b_local, NULL, (char *) i->ssid); + blobmsg_add_string(b_local, NULL, i->neighbor_report); + blobmsg_close_array(b_local, nr_entry); +} + +static int mac_is_in_entry_list(const struct dawn_mac mac, const struct mac_entry_s *list) { + for (const struct mac_entry_s *i = list; i; i = i->next_mac) + if (mac_is_equal_bb(i->mac, mac)) + return 1; + return 0; +} + // TODO: Does all APs constitute neighbor report? How about using list of AP connected // clients can also see (from probe_set) to give more (physically) local set? -int ap_get_nr(struct blob_buf *b_local, struct dawn_mac own_bssid_addr) { +// Here, we let the user configure a list of preferred APs that clients can see, and then +// add the rest of all APs. hostapd inserts this list backwards, so we must start with +// the regular APs, then add the preferred ones, which are already ordered backwards. +int ap_get_nr(struct blob_buf *b_local, struct dawn_mac own_bssid_addr, const char *ssid) { - pthread_mutex_lock(&ap_array_mutex); - ap *i; + ap *i, *own_ap; + struct mac_entry_s *preferred_list, *n; void* nbs = blobmsg_open_array(b_local, "list"); + own_ap = ap_array_get_ap(own_bssid_addr, (uint8_t*)ssid); + if (!own_ap) + return -1; + for (int band = 0; band < __DAWN_BAND_MAX; band++) { + preferred_list = dawn_metric.neighbors[band]; + if (own_ap->freq <= max_band_freq[band]) + break; + } + pthread_mutex_lock(&ap_array_mutex); for (i = ap_set; i != NULL; i = i->next_ap) { - if (mac_is_equal_bb(own_bssid_addr, i->bssid_addr)) { - continue; //TODO: Skip own entry?! + if (i != own_ap && !strncmp((char *)i->ssid, ssid, SSID_MAX_LEN) && + !mac_is_in_entry_list(i->bssid_addr, preferred_list)) + { + blobmsg_add_nr(b_local, i); } + } + pthread_mutex_unlock(&ap_array_mutex); - void* nr_entry = blobmsg_open_array(b_local, NULL); - - char mac_buf[20]; - sprintf(mac_buf, MACSTRLOWER, MAC2STR(i->bssid_addr.u8)); - blobmsg_add_string(b_local, NULL, mac_buf); - - blobmsg_add_string(b_local, NULL, (char *) i->ssid); - blobmsg_add_string(b_local, NULL, i->neighbor_report); - blobmsg_close_array(b_local, nr_entry); - + for (n = preferred_list; n; n = n->next_mac) { + if ((i = ap_array_get_ap(n->mac, (uint8_t*)ssid))) + blobmsg_add_nr(b_local, i); } blobmsg_close_array(b_local, nbs); - pthread_mutex_unlock(&ap_array_mutex); - return 0; } @@ -1596,9 +1712,13 @@ void uloop_add_data_cbs() { // Or not needed as test harness not threaded? void remove_probe_array_cb(struct uloop_timeout* t) { pthread_mutex_lock(&probe_array_mutex); +#ifndef DAWN_NO_OUTPUT printf("[Thread] : Removing old probe entries!\n"); +#endif remove_old_probe_entries(time(0), timeout_config.remove_probe); +#ifndef DAWN_NO_OUTPUT printf("[Thread] : Removing old entries finished!\n"); +#endif pthread_mutex_unlock(&probe_array_mutex); uloop_timeout_set(&probe_timeout, timeout_config.remove_probe * 1000); } @@ -1607,7 +1727,9 @@ void remove_probe_array_cb(struct uloop_timeout* t) { // Or not needed as test harness not threaded? void remove_client_array_cb(struct uloop_timeout* t) { pthread_mutex_lock(&client_array_mutex); +#ifndef DAWN_NO_OUTPUT printf("[Thread] : Removing old client entries!\n"); +#endif remove_old_client_entries(time(0), timeout_config.update_client); pthread_mutex_unlock(&client_array_mutex); uloop_timeout_set(&client_timeout, timeout_config.update_client * 1000); @@ -1617,7 +1739,9 @@ void remove_client_array_cb(struct uloop_timeout* t) { // Or not needed as test harness not threaded? void remove_ap_array_cb(struct uloop_timeout* t) { pthread_mutex_lock(&ap_array_mutex); +#ifndef DAWN_NO_OUTPUT printf("[ULOOP] : Removing old ap entries!\n"); +#endif remove_old_ap_entries(time(0), timeout_config.remove_ap); pthread_mutex_unlock(&ap_array_mutex); uloop_timeout_set(&ap_timeout, timeout_config.remove_ap * 1000); @@ -1627,10 +1751,23 @@ void remove_ap_array_cb(struct uloop_timeout* t) { // Or not needed as test harness not threaded? void denied_req_array_cb(struct uloop_timeout* t) { pthread_mutex_lock(&denied_array_mutex); +#ifndef DAWN_NO_OUTPUT printf("[ULOOP] : Processing denied authentication!\n"); +#endif remove_old_denied_req_entries(time(0), timeout_config.denied_req_threshold, true); pthread_mutex_unlock(&denied_array_mutex); uloop_timeout_set(&denied_req_timeout, timeout_config.denied_req_threshold * 1000); } + +int send_add_mac(struct dawn_mac client_addr) { + struct blob_buf b = {0}; + + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "addr", client_addr); + send_blob_attr_via_network(b.head, "addmac"); + blob_buf_free(&b); + + return 0; +}