2019-01-25 00:29:13 +01:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2019-05-19 20:01:22 +02:00
|
|
|
static int blacklist_init(void)
|
2019-01-25 00:29:13 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2019-05-19 20:01:22 +02:00
|
|
|
if (!l_settings_get_uint64(config, "Blacklist",
|
|
|
|
"bss_blacklist_max_time",
|
2019-01-25 00:29:13 +01:00
|
|
|
&blacklist_max_timeout))
|
|
|
|
blacklist_max_timeout = BLACKLIST_DEFAULT_MAX_TIMEOUT;
|
|
|
|
|
|
|
|
blacklist_max_timeout *= 1000000;
|
|
|
|
|
|
|
|
blacklist = l_queue_new();
|
2019-05-19 20:01:22 +02:00
|
|
|
|
|
|
|
return 0;
|
2019-01-25 00:29:13 +01:00
|
|
|
}
|
|
|
|
|
2019-05-19 20:01:22 +02:00
|
|
|
static void blacklist_exit(void)
|
2019-01-25 00:29:13 +01:00
|
|
|
{
|
|
|
|
l_queue_destroy(blacklist, l_free);
|
|
|
|
}
|
2019-05-19 20:01:22 +02:00
|
|
|
|
|
|
|
IWD_MODULE(blacklist, blacklist_init, blacklist_exit)
|