mirror of
				https://git.kernel.org/pub/scm/network/wireless/iwd.git
				synced 2025-10-31 13:17:25 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			190 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			4.3 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"
 | |
| #include "src/module.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);
 | |
| }
 | |
| 
 | |
| static int blacklist_init(void)
 | |
| {
 | |
| 	const struct l_settings *config = iwd_get_config();
 | |
| 
 | |
| 	if (!l_settings_get_uint64(config, "Blacklist", "InitialTimeout",
 | |
| 					&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",
 | |
| 					"Multiplier",
 | |
| 					&blacklist_multiplier))
 | |
| 		blacklist_multiplier = BLACKLIST_DEFAULT_MULTIPLIER;
 | |
| 
 | |
| 	if (!l_settings_get_uint64(config, "Blacklist",
 | |
| 					"MaximumTimeout",
 | |
| 					&blacklist_max_timeout))
 | |
| 		blacklist_max_timeout = BLACKLIST_DEFAULT_MAX_TIMEOUT;
 | |
| 
 | |
| 	blacklist_max_timeout *= 1000000;
 | |
| 
 | |
| 	blacklist = l_queue_new();
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void blacklist_exit(void)
 | |
| {
 | |
| 	l_queue_destroy(blacklist, l_free);
 | |
| }
 | |
| 
 | |
| IWD_MODULE(blacklist, blacklist_init, blacklist_exit)
 | 
