@@ -51,10 +51,46 @@ struct blacklist_entry {
uint8_t addr[6];
uint64_t added_time;
uint64_t expire_time;
+ enum blacklist_reason reason;
+};
+
+struct blacklist_search {
+ const uint8_t *addr;
+ enum blacklist_reason reason;
};
static struct l_queue *blacklist;
+static struct blacklist_entry *blacklist_entry_new(const uint8_t *addr,
+ enum blacklist_reason reason)
+{
+ struct blacklist_entry *entry;
+ uint64_t added;
+ uint64_t expires;
+
+ switch (reason) {
+ case BLACKLIST_REASON_CONNECT_FAILED:
+ if (!blacklist_initial_timeout)
+ return NULL;
+
+ added = l_time_now();
+ expires = l_time_offset(added, blacklist_initial_timeout);
+ break;
+ default:
+ l_warn("Unhandled blacklist reason: %u", reason);
+ return NULL;
+ }
+
+ entry = l_new(struct blacklist_entry, 1);
+
+ entry->added_time = added;
+ entry->expire_time = expires;
+ entry->reason = reason;
+ memcpy(entry->addr, addr, 6);
+
+ return entry;
+}
+
static bool check_if_expired(void *data, void *user_data)
{
struct blacklist_entry *entry = data;
@@ -79,24 +115,28 @@ static void blacklist_prune(void)
static bool match_addr(const void *a, const void *b)
{
const struct blacklist_entry *entry = a;
- const uint8_t *addr = b;
+ const struct blacklist_search *search = b;
+
+ if (entry->reason != search->reason)
+ return false;
- if (!memcmp(entry->addr, addr, 6))
+ if (!memcmp(entry->addr, search->addr, 6))
return true;
return false;
}
-void blacklist_add_bss(const uint8_t *addr)
+void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason)
{
struct blacklist_entry *entry;
-
- if (!blacklist_initial_timeout)
- return;
+ struct blacklist_search search = {
+ .addr = addr,
+ .reason = reason
+ };
blacklist_prune();
- entry = l_queue_find(blacklist, match_addr, addr);
+ entry = l_queue_find(blacklist, match_addr, &search);
if (entry) {
uint64_t offset = l_time_diff(entry->added_time,
@@ -112,25 +152,24 @@ void blacklist_add_bss(const uint8_t *addr)
return;
}
- entry = l_new(struct blacklist_entry, 1);
-
- entry->added_time = l_time_now();
- entry->expire_time = l_time_offset(entry->added_time,
- blacklist_initial_timeout);
- memcpy(entry->addr, addr, 6);
-
- l_queue_push_tail(blacklist, entry);
+ entry = blacklist_entry_new(addr, reason);
+ if (entry)
+ l_queue_push_tail(blacklist, entry);
}
-bool blacklist_contains_bss(const uint8_t *addr)
+bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason)
{
bool ret;
uint64_t time_now;
struct blacklist_entry *entry;
+ struct blacklist_search search = {
+ .addr = addr,
+ .reason = reason
+ };
blacklist_prune();
- entry = l_queue_find(blacklist, match_addr, addr);
+ entry = l_queue_find(blacklist, match_addr, &search);
if (!entry)
return false;
@@ -142,13 +181,17 @@ bool blacklist_contains_bss(const uint8_t *addr)
return ret;
}
-void blacklist_remove_bss(const uint8_t *addr)
+void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason)
{
struct blacklist_entry *entry;
+ struct blacklist_search search = {
+ .addr = addr,
+ .reason = reason
+ };
blacklist_prune();
- entry = l_queue_remove_if(blacklist, match_addr, addr);
+ entry = l_queue_remove_if(blacklist, match_addr, &search);
if (!entry)
return;
@@ -20,6 +20,14 @@
*
*/
-void blacklist_add_bss(const uint8_t *addr);
-bool blacklist_contains_bss(const uint8_t *addr);
-void blacklist_remove_bss(const uint8_t *addr);
+enum blacklist_reason {
+ /*
+ * When a BSS is blacklisted using this reason IWD will refuse to
+ * connect to it via autoconnect
+ */
+ BLACKLIST_REASON_CONNECT_FAILED,
+};
+
+void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason);
+bool blacklist_contains_bss(const uint8_t *addr, enum blacklist_reason reason);
+void blacklist_remove_bss(const uint8_t *addr, enum blacklist_reason reason);
@@ -1280,7 +1280,8 @@ struct scan_bss *network_bss_select(struct network *network,
if (l_queue_find(network->blacklist, match_bss, bss))
continue;
- if (blacklist_contains_bss(bss->addr))
+ if (blacklist_contains_bss(bss->addr,
+ BLACKLIST_REASON_CONNECT_FAILED))
continue;
/* OWE Transition BSS */
@@ -2880,7 +2880,8 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
if (network_can_connect_bss(network, bss) < 0)
goto next;
- if (blacklist_contains_bss(bss->addr))
+ if (blacklist_contains_bss(bss->addr,
+ BLACKLIST_REASON_CONNECT_FAILED))
goto next;
rank = bss->rank;
@@ -3400,7 +3401,8 @@ static bool station_retry_with_reason(struct station *station,
break;
}
- blacklist_add_bss(station->connected_bss->addr);
+ blacklist_add_bss(station->connected_bss->addr,
+ BLACKLIST_REASON_CONNECT_FAILED);
/*
* Network blacklist the BSS as well, since the timeout blacklist could
@@ -3471,7 +3473,8 @@ static bool station_retry_with_status(struct station *station,
* obtain that IE, but this should be done in the future.
*/
if (!IS_TEMPORARY_STATUS(status_code))
- blacklist_add_bss(station->connected_bss->addr);
+ blacklist_add_bss(station->connected_bss->addr,
+ BLACKLIST_REASON_CONNECT_FAILED);
/*
* Unconditionally network blacklist the BSS if we are retrying. This
@@ -3566,7 +3569,8 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
switch (result) {
case NETDEV_RESULT_OK:
- blacklist_remove_bss(station->connected_bss->addr);
+ blacklist_remove_bss(station->connected_bss->addr,
+ BLACKLIST_REASON_CONNECT_FAILED);
station_connect_ok(station);
return;
case NETDEV_RESULT_DISCONNECTED: