3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-24 06:52:37 +01:00
iwd/src/blacklist.c
James Prestwood ed6f5ea55a blacklist: add blacklist.[ch] to build and main
This will allow for blacklisting a BSS if the connection fails. The
actual blacklist module is simple and must be driven by station. All
it does is add BSS addresses, a timestamp, and a timeout to a queue.
Entries can also be removed, or checked if they exist. The blacklist
timeout is configuratble in main.conf, as well as the blacklist
timeout multiplier and maximum timeout. The multiplier is used after
a blacklisted BSS timeout expires but we still fail to connect on the
next connection attempt. We multiply the current timeout by the
multiplier so the BSS remains in the blacklist for a larger growing
amount of time until it reaches the maximum (24 hours by default).
2019-01-24 17:29:15 -06:00

184 lines
4.2 KiB
C

/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ell/ell.h>
#include "src/blacklist.h"
#include "src/util.h"
#include "src/iwd.h"
/*
* The current timeout is multiplied by this value after an entry is blacklisted
* more than once.
*/
#define BLACKLIST_DEFAULT_MULTIPLIER 30
/* Initial timeout for a new blacklist entry */
#define BLACKLIST_DEFAULT_TIMEOUT 60
/* The maximum amount of time a BSS can be blacklisted for */
#define BLACKLIST_DEFAULT_MAX_TIMEOUT 86400
static uint64_t blacklist_multiplier;
static uint64_t blacklist_initial_timeout;
static uint64_t blacklist_max_timeout;
struct blacklist_entry {
uint8_t addr[6];
uint64_t added_time;
uint64_t expire_time;
};
static struct l_queue *blacklist;
static bool check_if_expired(void *data, void *user_data)
{
struct blacklist_entry *entry = data;
uint64_t now = l_get_u64(user_data);
if (l_time_diff(now, entry->added_time) > blacklist_max_timeout) {
l_debug("Removing entry "MAC" on prune", MAC_STR(entry->addr));
l_free(entry);
return true;
}
return false;
}
static void blacklist_prune(void)
{
uint64_t now = l_time_now();
l_queue_foreach_remove(blacklist, check_if_expired, &now);
}
static bool match_addr(const void *a, const void *b)
{
const struct blacklist_entry *entry = a;
const uint8_t *addr = b;
if (!memcmp(entry->addr, addr, 6))
return true;
return false;
}
void blacklist_add_bss(const uint8_t *addr)
{
struct blacklist_entry *entry;
blacklist_prune();
entry = l_queue_find(blacklist, match_addr, addr);
if (entry) {
uint64_t offset = l_time_diff(entry->added_time,
entry->expire_time);
offset *= blacklist_multiplier;
if (offset > blacklist_max_timeout)
offset = blacklist_max_timeout;
entry->expire_time = l_time_offset(entry->added_time, offset);
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);
}
bool blacklist_contains_bss(const uint8_t *addr)
{
bool ret;
uint64_t time_now;
struct blacklist_entry *entry;
blacklist_prune();
entry = l_queue_find(blacklist, match_addr, addr);
if (!entry)
return false;
time_now = l_time_now();
ret = l_time_after(time_now, entry->expire_time) ? false : true;
return ret;
}
void blacklist_remove_bss(const uint8_t *addr)
{
struct blacklist_entry *entry;
blacklist_prune();
entry = l_queue_remove_if(blacklist, match_addr, addr);
if (!entry)
return;
l_free(entry);
}
void blacklist_init(void)
{
const struct l_settings *config = iwd_get_config();
if (!l_settings_get_uint64(config, "Blacklist", "bss_blacklist_time",
&blacklist_initial_timeout))
blacklist_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
/* For easier user configuration the timeout values are in seconds */
blacklist_initial_timeout *= 1000000;
if (!l_settings_get_uint64(config, "Blacklist",
"bss_blacklist_multiplier",
&blacklist_multiplier))
blacklist_multiplier = BLACKLIST_DEFAULT_MULTIPLIER;
if (!l_settings_get_uint64(config, "Blacklist", "bss_blacklist_max_time",
&blacklist_max_timeout))
blacklist_max_timeout = BLACKLIST_DEFAULT_MAX_TIMEOUT;
blacklist_max_timeout *= 1000000;
blacklist = l_queue_new();
}
void blacklist_exit(void)
{
l_queue_destroy(blacklist, l_free);
}