From 8064e568994f629112daf838ce15629b590f7913 Mon Sep 17 00:00:00 2001 From: Ian Clowes Date: Mon, 31 Jan 2022 11:42:32 +0000 Subject: [PATCH] scoring: improve scoring algorithm - Simplify how score is tracked - Streamline some code paths for scoring evaluation to reduce data searches, etc - Allow more entries to be considered for AP NR [cleanup commit message] Signed-off-by: Nick Hainke --- src/include/datastorage.h | 2 +- src/include/ubus.h | 2 +- src/storage/datastorage.c | 106 +++++++-------- src/test/test_storage.c | 4 +- src/utils/ubus.c | 274 +++++++++++++++++++------------------- 5 files changed, 193 insertions(+), 195 deletions(-) diff --git a/src/include/datastorage.h b/src/include/datastorage.h index d920bbf..6a83554 100644 --- a/src/include/datastorage.h +++ b/src/include/datastorage.h @@ -352,7 +352,7 @@ struct kicking_nr { }; // ---------------- Functions ------------------- -int better_ap_available(ap *kicking_ap, struct dawn_mac client_addr, struct kicking_nr** neighbor_report); +int better_ap_available(ap *kicking_ap, probe_entry *own_probe, int own_score, 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/ubus.h b/src/include/ubus.h index edba7b8..0de634b 100644 --- a/src/include/ubus.h +++ b/src/include/ubus.h @@ -131,7 +131,7 @@ 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, struct kicking_nr* neighbor_list, uint32_t duration); +int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, int threshold, uint32_t duration); /** * Send control message to all hosts to add the mac to a don't control list. diff --git a/src/storage/datastorage.c b/src/storage/datastorage.c index ab6c5fc..154a6dd 100644 --- a/src/storage/datastorage.c +++ b/src/storage/datastorage.c @@ -267,14 +267,10 @@ static int compare_station_count(ap* ap_entry_own, ap* ap_entry_to_compare, stru dawnlog_debug("Comparing station is already connected! Decrease counter!\n"); sta_count_to_compare--; } + dawnlog_info("Comparing own station count %d to %d\n", sta_count, sta_count_to_compare); - 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; + return sta_count - sta_count_to_compare; } static void remove_kicking_nr_list(struct kicking_nr *nr_list) { @@ -359,38 +355,21 @@ static void insert_kicking_nr_by_score(struct kicking_nr** nrlist, ap* nr_ap, i return; } -int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicking_nr **neighbor_report) { + +int better_ap_available(ap *kicking_ap, probe_entry *own_probe, int own_score, struct kicking_nr **neighbor_report) { dawnlog_debug_func("Entering..."); dawn_mutex_require(&ap_array_mutex); dawn_mutex_require(&probe_array_mutex); - // This remains set to the current AP of client for rest of function - dawn_mutex_require(&probe_array_mutex); - probe_entry* own_probe = probe_array_get_entry(client_mac, kicking_ap->bssid_addr); - int own_score = -1; - if (own_probe != NULL) { - own_score = eval_probe_metric(own_probe, kicking_ap); //TODO: Should the -2 return be handled? - dawnlog_trace("Current AP score = %d for:\n", own_score); - print_probe_entry(DAWNLOG_TRACE, own_probe); - } - // no entry for own ap - may happen if DAWN is started after client has connected, and then "sleeps" so sends no BEACON / PROBE - else { - dawnlog_info("Current AP " MACSTR " for client " MACSTR " not found in probe array!\n", MAC2STR(kicking_ap->bssid_addr.u8), MAC2STR(client_mac.u8)); - print_probe_array(); - return -1; - } - - int max_score = own_score; - dawn_mutex_require(&ap_array_mutex); - dawn_mutex_require(&probe_array_mutex); - int kick = 0; + int tgt_score = own_score + dawn_metric.kicking_threshold; + int better_ap_found = 0; int ap_count = 0; // Now go through all probe entries for this client looking for better score dawn_mutex_require(&probe_array_mutex); - probe_entry* i = probe_array_find_first_entry(client_mac, dawn_mac_null, false); + probe_entry* i = probe_array_find_first_entry(own_probe->client_addr, dawn_mac_null, false); - while (i != NULL && mac_is_equal_bb(i->client_addr, client_mac)) { + while (i != NULL && mac_is_equal_bb(i->client_addr, own_probe->client_addr)) { if (i == own_probe) { dawnlog_trace("Own Score! Skipping!\n"); i = i->next_probe; @@ -422,24 +401,24 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicki int ap_outcome = 0; // No kicking // Find better score... - // FIXME: Do we mean to use 'kick' like this here? It is set when we find an AP with bigger score - // then any more have to also be 'kicking_threshold' bigger - if (score_to_compare > max_score + (kick ? 0 : dawn_metric.kicking_threshold)) { + if (score_to_compare > tgt_score) { ap_outcome = 2; // Add and prune - max_score = score_to_compare; + // TODO: Should we adjust this, or just stick with original "better than current AP" target? + tgt_score = score_to_compare; } - // if AP have same value but station count might improve it... + // Give a few marks for candidate AP having fewer clients than current // TODO: Is absolute number meaningful when AP have diffeent capacity? - else if (score_to_compare == max_score && dawn_metric.use_station_count > 0 ) { - int compare = compare_station_count(kicking_ap, candidate_ap, client_mac); - if (compare > 0) { + // TODO: This test doesn't really make sense if we have adjusted target score to best found so far + else if (score_to_compare == tgt_score && dawn_metric.use_station_count > 0 ) { + int compare = compare_station_count(kicking_ap, candidate_ap, own_probe->client_addr); + if (compare > dawn_metric.max_station_diff) { ap_outcome = 2; // Add and prune } - else if (compare == 0 && kick) { + else if (compare == 0) { ap_outcome = 1; // Add but no prune } } - else if (score_to_compare >= max_score && kick) { + else if (score_to_compare == tgt_score) { ap_outcome = 1; // Add but no prune } @@ -449,10 +428,22 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicki } else { - dawnlog_trace("Better AP after full evaluation - add to NR (%s pruning)\n", ap_outcome == 2 ? "with" : "without"); - // NR is NULL if we're only testing for a better AP without actually using it + dawnlog_trace("Better AP after full evaluation\n"); + better_ap_found = 1; + } + + // NR is NULL if we're only testing for a better AP without actually using it + if (better_ap_found && neighbor_report == NULL) + { + // Short circuit loop if we're only finding a better AP without actually using it + i = NULL; + } + else + { + // Always add the NR as we use it to adjust the "own AP" semi-static NR as well if (neighbor_report != NULL) { + dawnlog_trace("Add to NR (%s pruning)\n", ap_outcome == 2 ? "with" : "without"); // FIXME: Do we need to prune this list as we build it? trying new approach to send N best entries to hostapd // if (ap_outcome == 2) // prune_kicking_nr_list(neighbor_report, score_to_compare - dawn_metric.kicking_threshold); @@ -460,25 +451,14 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicki insert_kicking_nr_by_score(neighbor_report, candidate_ap, score_to_compare); } - // If we find a single candidate then we will be kicking - kick = 1; - } - - // Short circuit loop if we're only finding a better AP without actually using it - if (kick && neighbor_report == NULL) - { - i = NULL; - } - else - { i = i->next_probe; } } if (neighbor_report != NULL) - dawnlog_info("Client " MACSTR ": Compared %d alternate AP candidates\n", MAC2STR(client_mac.u8), ap_count); + dawnlog_info("Client " MACSTR ": Compared %d alternate AP candidates\n", MAC2STR(own_probe->client_addr.u8), ap_count); - return kick; + return better_ap_found; } int kick_clients(struct dawn_mac bssid_mac, uint32_t id) { @@ -506,12 +486,26 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) { struct kicking_nr *kick_nr_list = NULL; int do_kick = 0; + int own_score = 0; if (mac_find_entry(j->client_addr)) { dawnlog_info("Client " MACSTR ": Suppressing check due to MAC list entry\n", MAC2STR(j->client_addr.u8)); } else { - do_kick = better_ap_available(kicking_ap, j->client_addr, &kick_nr_list); + dawn_mutex_require(&probe_array_mutex); + probe_entry* own_probe = probe_array_get_entry(j->client_addr, kicking_ap->bssid_addr); + if (own_probe == NULL) { + // no entry for own ap - may happen if DAWN is started after client has connected, and then "sleeps" so sends no BEACON / PROBE + dawnlog_info("Current AP " MACSTR " for client " MACSTR " not found in probe array!\n", MAC2STR(kicking_ap->bssid_addr.u8), MAC2STR(j->client_addr.u8)); + print_probe_array(); + } + else { + own_score = eval_probe_metric(own_probe, kicking_ap); + dawnlog_trace("Current AP score = %d for:\n", own_score); + print_probe_entry(DAWNLOG_TRACE, own_probe); + + do_kick = better_ap_available(kicking_ap, own_probe, own_score, &kick_nr_list); + } } // If we found any candidates (even if too low to kick to) add the highest scoring one to local AP NR set @@ -570,7 +564,7 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) { // don't deauth station? <- deauth is better! // maybe we can use handovers... //del_client_interface(id, client_array[j].client_addr, NO_MORE_STAS, 1, 1000); - int sync_kick = wnm_disassoc_imminent(id, j->client_addr, kick_nr_list, 12); + int sync_kick = wnm_disassoc_imminent(id, j->client_addr, kick_nr_list, own_score + dawn_metric.kicking_threshold, 12); // Synchronous kick is a test harness feature to indicate arrays have been updated, so don't change further if (sync_kick) diff --git a/src/test/test_storage.c b/src/test/test_storage.c index 4f1bfaa..fe19d0d 100644 --- a/src/test/test_storage.c +++ b/src/test/test_storage.c @@ -34,7 +34,7 @@ int send_set_probe(struct dawn_mac client_addr) return 0; } -int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, uint32_t duration) +int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, int threshold, uint32_t duration) { int ret = 0; @@ -892,7 +892,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity) struct kicking_nr *neighbor_list = NULL; - tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, with_nr ? &neighbor_list : NULL); + tr = better_ap_available(ap_array_get_ap(bssid_mac), probe_array_get_entry(client_mac, bssid_mac), 100, with_nr ? &neighbor_list : NULL); printf("better_ap_available returned %d (with neighbour report %s)\n", tr, neighbor_list ? neighbor_list->nr_ap->neighbor_report : "NONE"); } diff --git a/src/utils/ubus.c b/src/utils/ubus.c index 623e0b0..a36131e 100644 --- a/src/utils/ubus.c +++ b/src/utils/ubus.c @@ -328,78 +328,79 @@ static probe_entry* parse_to_beacon_rep(struct blob_attr *msg) { } int handle_auth_req(struct blob_attr* msg) { -int ret = WLAN_STATUS_SUCCESS; -bool discard_entry = true; - dawnlog_debug_func("Entering..."); + // Allow if we can't evalute an active reason to deny + int ret = WLAN_STATUS_SUCCESS; + client_req_entry *auth_req = dawn_malloc(sizeof(struct client_req_entry_s)); if (auth_req == NULL) { dawnlog_error("Memory allocation of auth req failed!"); - return ret; // Allow if we can't evalute a reason to deny } + else + { + parse_to_client_req(msg, auth_req); - parse_to_client_req(msg, auth_req); + dawnlog_debug("Auth entry: "); + print_client_req_entry(DAWNLOG_DEBUG, auth_req); - dawnlog_debug("Auth entry: "); - print_client_req_entry(DAWNLOG_DEBUG, auth_req); + if (dawn_metric.eval_auth_req <= 0) { + dawnlog_trace(MACSTR " Allow authentication due to not evaluating requests", MAC2STR(auth_req->client_addr.u8)); + } + else if (mac_find_entry(auth_req->client_addr)) { + dawnlog_trace(MACSTR " Allow authentication due to whitelisted MAC", MAC2STR(auth_req->client_addr.u8)); + } + else { + dawn_mutex_lock(&probe_array_mutex); - if (dawn_metric.eval_auth_req <= 0) { - dawnlog_trace(MACSTR " Allow authentication due to not evaluating requests", MAC2STR(auth_req->client_addr.u8)); - } - else if (mac_find_entry(auth_req->client_addr)) { - dawnlog_trace(MACSTR " Allow authentication due to mac_find_entry()", MAC2STR(auth_req->client_addr.u8)); - } - else { - dawn_mutex_lock(&probe_array_mutex); - - if (dawnlog_showing(DAWNLOG_DEBUG)) - print_probe_array(); - - probe_entry *tmp = probe_array_get_entry(auth_req->client_addr, auth_req->bssid_addr); + if (dawnlog_showing(DAWNLOG_DEBUG)) + print_probe_array(); dawn_mutex_require(&probe_array_mutex); + probe_entry* own_probe = probe_array_get_entry(auth_req->client_addr, auth_req->bssid_addr); - /*** Deprecated function decide_function() removed here ***/ - int deny_request = 0; - - // block if entry was not already found in probe database - if (tmp == NULL) { - dawnlog_trace(MACSTR " Deny authentication due to no probe entry", MAC2STR(auth_req->client_addr.u8)); - deny_request = 1; - } - else if (tmp->counter < dawn_metric.min_probe_count) { - dawnlog_trace(MACSTR " Deny authentication due to low probe count", MAC2STR(auth_req->client_addr.u8)); - deny_request = 1; - } - else - { - dawn_mutex_lock(&ap_array_mutex); - - dawn_mutex_require(&ap_array_mutex); - ap* this_ap = ap_array_get_ap(tmp->bssid_addr); - if (this_ap != NULL && better_ap_available(this_ap, tmp->client_addr, NULL) > 0) { - dawnlog_trace(MACSTR " Deny authentication due to better AP available", MAC2STR(auth_req->client_addr.u8)); - deny_request = 1; + // block if entry was not already found in probe database + if (own_probe == NULL) { + dawnlog_trace(MACSTR " Deny authentication due to no probe entry", MAC2STR(auth_req->client_addr.u8)); + ret = dawn_metric.deny_auth_reason; + } + else if (own_probe->counter < dawn_metric.min_probe_count) { + dawnlog_trace(MACSTR " Deny authentication due to low probe count", MAC2STR(auth_req->client_addr.u8)); + ret = dawn_metric.deny_auth_reason; } else - // maybe send here that the client is connected? - dawnlog_trace(MACSTR " Allow authentication!\n", MAC2STR(auth_req->client_addr.u8)); + { + dawn_mutex_lock(&ap_array_mutex); - dawn_mutex_unlock(&ap_array_mutex); - } - /*** End of decide_function() rework ***/ + dawn_mutex_require(&ap_array_mutex); + ap* this_ap = ap_array_get_ap(auth_req->bssid_addr); + if (this_ap == NULL) + { + dawnlog_trace(MACSTR " Allow authentication due to no AP entry", MAC2STR(auth_req->client_addr.u8)); + } + else + { + int own_score = eval_probe_metric(own_probe, this_ap); + dawnlog_trace("Current AP score = %d for:\n", own_score); + print_probe_entry(DAWNLOG_TRACE, own_probe); - if (deny_request) { - ret = dawn_metric.deny_auth_reason; + if (better_ap_available(this_ap, own_probe, own_score, NULL) > 0) { + dawnlog_trace(MACSTR " Deny authentication due to better AP available", MAC2STR(auth_req->client_addr.u8)); + ret = dawn_metric.deny_auth_reason; + } + else { + // maybe send here that the client is connected? + dawnlog_trace(MACSTR " Allow authentication request due to AP score\n", MAC2STR(auth_req->client_addr.u8)); + } + } + + dawn_mutex_unlock(&ap_array_mutex); + } + + dawn_mutex_unlock(&probe_array_mutex); } - dawn_mutex_unlock(&probe_array_mutex); - } - - if (discard_entry) - { dawn_free(auth_req); auth_req = NULL; } @@ -408,79 +409,77 @@ bool discard_entry = true; } static int handle_assoc_req(struct blob_attr *msg) { -int ret = WLAN_STATUS_SUCCESS; -int discard_entry = true; - dawnlog_debug_func("Entering..."); + // Allow if we can't evalute an active reason to deny + int ret = WLAN_STATUS_SUCCESS; + client_req_entry* assoc_req = dawn_malloc(sizeof(struct client_req_entry_s)); if (assoc_req == NULL) { dawnlog_error("Memory allocation of assoc req failed!"); - return ret; // Allow if we can't evalute a reason to deny } + else + { + parse_to_client_req(msg, assoc_req); + dawnlog_debug("Association entry: "); + print_client_req_entry(DAWNLOG_DEBUG, assoc_req); - parse_to_client_req(msg, assoc_req); - dawnlog_debug("Association entry: "); - print_client_req_entry(DAWNLOG_DEBUG, assoc_req); + if (dawn_metric.eval_assoc_req <= 0) { + dawnlog_trace(MACSTR " Allow association due to not evaluating requests", MAC2STR(assoc_req->client_addr.u8)); + } + else if (mac_find_entry(assoc_req->client_addr)) { + dawnlog_trace(MACSTR " Allow association due to whitelisted MAC", MAC2STR(assoc_req->client_addr.u8)); + } + else { + dawn_mutex_lock(&probe_array_mutex); - if (dawn_metric.eval_assoc_req <= 0) { - dawnlog_trace(MACSTR " Allow association due to not evaluating requests", MAC2STR(assoc_req->client_addr.u8)); - } - else if (mac_find_entry(assoc_req->client_addr)) { - dawnlog_trace(MACSTR " Allow association due to mac_find_entry()", MAC2STR(assoc_req->client_addr.u8)); - } else { - dawn_mutex_lock(&probe_array_mutex); - - if (dawnlog_showing(DAWNLOG_DEBUG)) - print_probe_array(); - - probe_entry *tmp = probe_array_get_entry(assoc_req->client_addr, assoc_req->bssid_addr); + if (dawnlog_showing(DAWNLOG_DEBUG)) + print_probe_array(); dawn_mutex_require(&probe_array_mutex); + probe_entry* own_probe = probe_array_get_entry(assoc_req->client_addr, assoc_req->bssid_addr); - /*** Deprecated function decide_function() removed here ***/ - int deny_request = 0; - - // block if entry was not already found in probe database - if (tmp == NULL) { - dawnlog_trace(MACSTR " Deny association due to no probe entry found", MAC2STR(assoc_req->client_addr.u8)); - deny_request = 1; - } - else if (tmp->counter < dawn_metric.min_probe_count) { - dawnlog_trace(MACSTR " Deny association due to low probe count", MAC2STR(assoc_req->client_addr.u8)); - deny_request = 1; - } - else - { - // find own probe entry and calculate score - dawn_mutex_lock(&ap_array_mutex); + // block if entry was not already found in probe database + if (own_probe == NULL) { + dawnlog_trace(MACSTR " Deny association due to no probe entry found", MAC2STR(assoc_req->client_addr.u8)); + } + else if (own_probe->counter < dawn_metric.min_probe_count) { + dawnlog_trace(MACSTR " Deny association due to low probe count", MAC2STR(assoc_req->client_addr.u8)); + ret = dawn_metric.deny_auth_reason; + } + else + { + // find own probe entry and calculate score + dawn_mutex_lock(&ap_array_mutex); dawn_mutex_require(&ap_array_mutex); - ap* this_ap = ap_array_get_ap(assoc_req->bssid_addr); - if (this_ap != NULL && better_ap_available(this_ap, assoc_req->client_addr, NULL) > 0) { - dawnlog_trace(MACSTR " Deny association due to better AP available", MAC2STR(assoc_req->client_addr.u8)); - deny_request = 1; - } - else { // TODO: Should we reset probe counter to zero here? Does active client do probe and if so what would a deny lead to? - dawnlog_trace(MACSTR " Allow association!\n", MAC2STR(assoc_req->client_addr.u8)); - } - dawn_mutex_unlock(&ap_array_mutex); - } - /*** End of decide_function() rework ***/ + ap* this_ap = ap_array_get_ap(assoc_req->bssid_addr); + if (this_ap == NULL) + { + dawnlog_trace(MACSTR " Allow association due to no AP entry", MAC2STR(assoc_req->client_addr.u8)); + } + else + { + int own_score = eval_probe_metric(own_probe, this_ap); + dawnlog_trace("Current AP score = %d for:\n", own_score); + print_probe_entry(DAWNLOG_TRACE, own_probe); - if (deny_request) { - if (tmp != NULL) - print_probe_entry(DAWNLOG_DEBUG, tmp); + if (better_ap_available(this_ap, own_probe, own_score, NULL) > 0) { + dawnlog_trace(MACSTR " Deny association due to better AP available", MAC2STR(assoc_req->client_addr.u8)); + ret = dawn_metric.deny_assoc_reason; + } + else { // TODO: Should we reset probe counter to zero here? Does active client do probe and if so what would a deny lead to? + dawnlog_trace(MACSTR " Allow association request due to AP score\n", MAC2STR(assoc_req->client_addr.u8)); + } + } - ret = dawn_metric.deny_assoc_reason; + dawn_mutex_unlock(&ap_array_mutex); + } + + dawn_mutex_unlock(&probe_array_mutex); } - dawn_mutex_unlock(&probe_array_mutex); - } - - if (discard_entry) - { dawn_free(assoc_req); assoc_req = NULL; } @@ -491,29 +490,30 @@ int discard_entry = true; static int handle_probe_req(struct blob_attr* msg) { dawnlog_debug_func("Entering..."); - // MUSTDO: Untangle dawn_malloc() and linking of probe_entry - probe_entry* probe_req = parse_to_probe_req(msg); + // Allow if we can't evalute an active reason to deny + int ret = WLAN_STATUS_SUCCESS; - if (probe_req == NULL) + probe_entry* probe_req_new = parse_to_probe_req(msg); + + if (probe_req_new == NULL) { dawnlog_error("Parse of probe req failed!"); - return WLAN_STATUS_SUCCESS; // Allow if we can't evalute a reason to deny } else { dawn_mutex_lock(&probe_array_mutex); dawn_mutex_require(&probe_array_mutex); - probe_entry* probe_req_updated = insert_to_probe_array(probe_req, true, true, false, time(0)); + probe_entry* probe_req_updated = insert_to_probe_array(probe_req_new, 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) + if (probe_req_new != probe_req_updated) { dawnlog_info("Local PROBE used to update client / BSSID = " MACSTR " / " MACSTR " \n", MAC2STR(probe_req_updated->client_addr.u8), MAC2STR(probe_req_updated->bssid_addr.u8)); - dawn_free(probe_req); - probe_req = NULL; + dawn_free(probe_req_new); + probe_req_new = NULL; } else { @@ -522,46 +522,50 @@ static int handle_probe_req(struct blob_attr* msg) { ubus_send_probe_via_network(probe_req_updated); - /*** Deprecated function decide_function() removed here ***/ - int deny_request = 0; - if (dawn_metric.eval_probe_req <= 0) { dawnlog_trace(MACSTR " Allow probe due to not evaluating requests", MAC2STR(probe_req_updated->client_addr.u8)); } else if (mac_find_entry(probe_req_updated->client_addr)) { - dawnlog_trace(MACSTR " Allow probe due to mac_find_entry()", MAC2STR(probe_req_updated->client_addr.u8)); + dawnlog_trace(MACSTR " Allow probe due to whitelisted MAC", MAC2STR(probe_req_updated->client_addr.u8)); } else if (probe_req_updated->counter < dawn_metric.min_probe_count) { dawnlog_trace(MACSTR " Deny probe due to low probe count", MAC2STR(probe_req_updated->client_addr.u8)); - deny_request = 1; + ret = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; } else { - // find own probe entry and calculate score + // Evaluate whether to allow probe to succeed dawn_mutex_lock(&ap_array_mutex); dawn_mutex_require(&ap_array_mutex); ap* this_ap = ap_array_get_ap(probe_req_updated->bssid_addr); - if (this_ap != NULL && better_ap_available(this_ap, probe_req_updated->client_addr, NULL) > 0) { - dawnlog_trace(MACSTR " Deny probe due to better AP available", MAC2STR(probe_req_updated->client_addr.u8)); - deny_request = 1; + if (this_ap == NULL) + { + dawnlog_trace(MACSTR " Allow probe due to no AP entry", MAC2STR(probe_req_updated->client_addr.u8)); } else { - dawnlog_trace(MACSTR " Allow probe request!", MAC2STR(probe_req_updated->client_addr.u8)); + int own_score = eval_probe_metric(probe_req_updated, this_ap); //TODO: Should the -2 return be handled? + dawnlog_trace("Current AP score = %d for:\n", own_score); + print_probe_entry(DAWNLOG_TRACE, probe_req_updated); + + if (better_ap_available(this_ap, probe_req_updated, own_score, NULL) > 0) { + dawnlog_trace(MACSTR " Deny probe due to better AP available", MAC2STR(probe_req_updated->client_addr.u8)); + ret = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + } + else + { + dawnlog_trace(MACSTR " Allow probe request due to AP score", MAC2STR(probe_req_updated->client_addr.u8)); + } } dawn_mutex_unlock(&ap_array_mutex); } - /*** End of decide_function() rework ***/ - if (deny_request) { - return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; // no reason needed... - } + dawn_mutex_unlock(&probe_array_mutex); } - // TODO: Return for dawn_malloc() failure? - return WLAN_STATUS_SUCCESS; + return ret; } static int handle_beacon_rep(struct blob_attr *msg) { @@ -1146,7 +1150,7 @@ void del_client_interface(uint32_t id, const struct dawn_mac client_addr, uint32 dawn_unregmem(&b); } -int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, uint32_t duration) { +int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct kicking_nr* neighbor_list, int threshold, uint32_t duration) { struct hostapd_sock_entry *sub; struct blob_buf b = {0}; @@ -1162,9 +1166,9 @@ int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct void* nbs = blobmsg_open_array(&b, "neighbors"); - // Add the first N AP, where list order id high->low score + // Add the first N AP that reach threshold, where list order id high->low score int neighbors_added = 0; - while(neighbors_added < dawn_metric.disassoc_nr_length && neighbor_list != NULL) { + while(neighbors_added < dawn_metric.disassoc_nr_length && neighbor_list != NULL && neighbor_list->score >= threshold) { dawnlog_info("BSS TRANSITION NEIGHBOR " NR_MACSTR ", Score=%d\n", NR_MAC2STR(neighbor_list->nr_ap->neighbor_report), neighbor_list->score); blobmsg_add_string(&b, NULL, neighbor_list->nr_ap->neighbor_report); neighbor_list = neighbor_list->next;