diff --git a/Makefile.am b/Makefile.am index 58d93dd1..157a1087 100644 --- a/Makefile.am +++ b/Makefile.am @@ -200,6 +200,7 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h \ src/sae.h src/sae.c \ src/nl80211util.h src/nl80211util.c \ src/owe.h src/owe.c \ + src/blacklist.h src/blacklist.c \ $(eap_sources) \ $(builtin_sources) src_iwd_LDADD = $(ell_ldadd) -ldl diff --git a/src/blacklist.c b/src/blacklist.c new file mode 100644 index 00000000..2da276f7 --- /dev/null +++ b/src/blacklist.c @@ -0,0 +1,183 @@ +/* + * + * 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 +#endif + +#include + +#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); +} diff --git a/src/blacklist.h b/src/blacklist.h new file mode 100644 index 00000000..8161f4ed --- /dev/null +++ b/src/blacklist.h @@ -0,0 +1,28 @@ +/* + * + * 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 + * + */ + +void blacklist_add_bss(const uint8_t *addr); +bool blacklist_contains_bss(const uint8_t *addr); +void blacklist_remove_bss(const uint8_t *addr); + +void blacklist_init(void); +void blacklist_exit(void); diff --git a/src/main.c b/src/main.c index e0ccbef2..e9f91134 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,7 @@ #include "src/plugin.h" #include "src/simauth.h" #include "src/adhoc.h" +#include "src/blacklist.h" #include "src/backtrace.h" @@ -498,9 +499,11 @@ int main(int argc, char *argv[]) known_networks_init(); sim_auth_init(); plugin_init(plugins, noplugins); + blacklist_init(); exit_status = l_main_run_with_signal(signal_handler, NULL); + blacklist_exit(); plugin_exit(); sim_auth_exit(); known_networks_exit();