Patchwork hostapd: reload bss mac files on SIGUSR2

login
register
mail settings
Submitter Antonio Quartulli
Date June 10, 2012, 10:34 p.m.
Message ID <1339367661-6094-1-git-send-email-ordex@autistici.org>
Download mbox | patch
Permalink /patch/164012/
State Superseded
Headers show

Comments

Antonio Quartulli - June 10, 2012, 10:34 p.m.
This patch allows the administrator to modify the provided MAC list for the
BSS ACL mechanism at runtime. In the current implementation no runtime change
is possible: if the MAC list is modified, hostapd has to be restart so
disconnecting all the current clients.

After manually modify the MAC files, the USR2 signal will make hostapd reload
them and possibly disconnect new not allowed stations.

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
 hostapd/config_file.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++
 hostapd/config_file.h |    1 +
 hostapd/main.c        |   14 +++++++
 src/ap/ap_config.h    |    3 +-
 src/ap/hostapd.c      |    3 --
 src/ap/sta_info.c     |   32 ++++++++++++++++
 src/ap/sta_info.h     |    3 ++
 7 files changed, 150 insertions(+), 4 deletions(-)

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index eab8ad4..a52309d 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -19,6 +19,9 @@ 
 #include "radius/radius_client.h"
 #include "ap/wpa_auth.h"
 #include "ap/ap_config.h"
+#include "ap/hostapd.h"
+#include "ap/ap_drv_ops.h"
+#include "ap/sta_info.h"
 #include "config_file.h"
 
 
@@ -1391,8 +1394,12 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 				wpa_printf(MSG_ERROR, "Line %d: unknown "
 					   "macaddr_acl %d",
 					   line, bss->macaddr_acl);
+				bss->accept_mac_filename[0] = '\0';
+				bss->deny_mac_filename[0] = '\0';
 			}
 		} else if (os_strcmp(buf, "accept_mac_file") == 0) {
+			os_strncpy(bss->accept_mac_filename, pos, 256);
+			bss->accept_mac_filename[255] = '\0';
 			if (hostapd_config_read_maclist(pos, &bss->accept_mac,
 							&bss->num_accept_mac))
 			{
@@ -1402,6 +1409,8 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 				errors++;
 			}
 		} else if (os_strcmp(buf, "deny_mac_file") == 0) {
+			os_strncpy(bss->deny_mac_filename, pos, 256);
+			bss->deny_mac_filename[255] = '\0';
 			if (hostapd_config_read_maclist(pos, &bss->deny_mac,
 							&bss->num_deny_mac)) {
 				wpa_printf(MSG_ERROR, "Line %d: Failed to "
@@ -2495,3 +2504,92 @@  int hostapd_set_iface(struct hostapd_config *conf,
 
 	return 0;
 }
+
+static void hostapd_deauth_station(struct hostapd_data *hapd, u8 *addr,
+				   u16 reason)
+{
+	if (hostapd_drv_none(hapd))
+		return;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate " MACSTR,
+		MAC2STR(addr));
+
+	hostapd_drv_sta_deauth(hapd, addr, reason);
+	hostapd_free_sta(hapd, addr, reason);
+}
+
+int hostapd_reload_macfile(struct hostapd_iface *iface)
+{
+	struct hostapd_bss_config *bss;
+	struct sta_info *sta, *prev, *next;
+	size_t i, j;
+
+	wpa_printf(MSG_DEBUG, "Reloading macfiles");
+	for (i = 0; i < iface->num_bss; i++) {
+		bss = iface->bss[i]->conf;
+
+		/* reload accept mac file if any */
+		if (bss->accept_mac_filename[0] != '\0') {
+			wpa_printf(MSG_DEBUG, "Reading %s",
+				   bss->accept_mac_filename);
+			os_free(bss->accept_mac);
+			bss->accept_mac = NULL;
+			bss->num_accept_mac = 0;
+			if (hostapd_config_read_maclist(
+						bss->accept_mac_filename,
+						&bss->accept_mac,
+						&bss->num_accept_mac))
+				wpa_printf(MSG_ERROR, "Failed to read "
+					   "accept_mac_file '%s'",
+					   bss->accept_mac_filename);
+		}
+
+		/* reload deny mac file if any */
+		if (bss->deny_mac_filename[0] != '\0') {
+			wpa_printf(MSG_DEBUG, "Reading %s",
+				   bss->deny_mac_filename);
+			os_free(bss->deny_mac);
+			bss->deny_mac = NULL;
+			bss->num_deny_mac = 0;
+			if (hostapd_config_read_maclist(bss->deny_mac_filename,
+							&bss->deny_mac,
+							&bss->num_deny_mac))
+				wpa_printf(MSG_ERROR, "Failed to read "
+					   "deny_mac_file '%s'",
+					   bss->deny_mac_filename);
+		}
+
+		/* deauthenticate listed stations */
+		if (bss->macaddr_acl == ACCEPT_UNLESS_DENIED)
+			for (j = 0; j < bss->num_deny_mac; j++)
+				hostapd_deauth_station(iface->bss[i],
+					bss->deny_mac[j].addr,
+					WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+		/* deauthenticate all the stations that are not listed */
+		if (bss->macaddr_acl == DENY_UNLESS_ACCEPTED) {
+			prev = sta = iface->bss[i]->sta_list;
+			while (sta) {
+				next = sta->next;
+				for (j = 0; j < bss->num_accept_mac; j++)
+					if (!memcmp(sta->addr,
+						    bss->accept_mac[j].addr,
+						    ETH_ALEN))
+						break;
+				if (j == bss->num_accept_mac) {
+					if (iface->bss[i]->sta_list == sta)
+						iface->bss[i]->sta_list =
+								sta->next;
+					else
+						prev->next = sta->next;
+					hostapd_deauth_station(iface->bss[i],
+							       sta->addr,
+					       WLAN_REASON_PREV_AUTH_NOT_VALID);
+				} else
+					prev = sta;
+				sta = next;
+			}
+		}
+	}
+	return 0;
+}
diff --git a/hostapd/config_file.h b/hostapd/config_file.h
index fba57b8..90a306b 100644
--- a/hostapd/config_file.h
+++ b/hostapd/config_file.h
@@ -13,5 +13,6 @@  struct hostapd_config * hostapd_config_read(const char *fname);
 int hostapd_set_iface(struct hostapd_config *conf,
 		      struct hostapd_bss_config *bss, char *field,
 		      char *value);
+int hostapd_reload_macfile(struct hostapd_iface *iface);
 
 #endif /* CONFIG_FILE_H */
diff --git a/hostapd/main.c b/hostapd/main.c
index d8c2776..85a376a 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -363,6 +363,10 @@  static void handle_reload(int sig, void *signal_ctx)
 	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
 }
 
+int handle_reload_macfile_iface(struct hostapd_iface *iface, void *ctx)
+{
+	return hostapd_reload_macfile(iface);
+}
 
 static void handle_dump_state(int sig, void *signal_ctx)
 {
@@ -371,6 +375,15 @@  static void handle_dump_state(int sig, void *signal_ctx)
 	hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
 #endif /* HOSTAPD_DUMP_STATE */
 }
+
+static void handle_reload_macfile(int sig, void *signal_ctx)
+{
+	struct hapd_interfaces *interfaces = signal_ctx;
+	wpa_printf(MSG_DEBUG, "USR2 catched, reloading macfiles..");
+	hostapd_for_each_interface(interfaces, handle_reload_macfile_iface,
+				   NULL);
+}
+
 #endif /* CONFIG_NATIVE_WINDOWS */
 
 
@@ -398,6 +411,7 @@  static int hostapd_global_init(struct hapd_interfaces *interfaces,
 #ifndef CONFIG_NATIVE_WINDOWS
 	eloop_register_signal(SIGHUP, handle_reload, interfaces);
 	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
+	eloop_register_signal(SIGUSR2, handle_reload_macfile, interfaces);
 #endif /* CONFIG_NATIVE_WINDOWS */
 	eloop_register_signal_terminate(handle_term, interfaces);
 
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 78c9068..8e23528 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -207,14 +207,15 @@  struct hostapd_bss_config {
 	int ieee802_11f; /* use IEEE 802.11f (IAPP) */
 	char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
 					* frames */
-
 	enum {
 		ACCEPT_UNLESS_DENIED = 0,
 		DENY_UNLESS_ACCEPTED = 1,
 		USE_EXTERNAL_RADIUS_AUTH = 2
 	} macaddr_acl;
+	char accept_mac_filename[256];
 	struct mac_acl_entry *accept_mac;
 	int num_accept_mac;
+	char deny_mac_filename[256];
 	struct mac_acl_entry *deny_mac;
 	int num_deny_mac;
 	int wds_sta;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 9d6fd7b..d17b231 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -106,7 +106,6 @@  static void hostapd_reload_bss(struct hostapd_data *hapd)
 	wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
 }
 
-
 int hostapd_reload_config(struct hostapd_iface *iface)
 {
 	struct hostapd_data *hapd = iface->bss[0];
@@ -379,7 +378,6 @@  static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
 	return 0;
 }
 
-
 static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
 {
 	int ret = 0;
@@ -402,7 +400,6 @@  static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
 	return ret;
 }
 
-
 /**
  * hostapd_validate_bssid_configuration - Validate BSSID configuration
  * @iface: Pointer to interface data
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index a7dffc7..0a4c673 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -239,6 +239,38 @@  void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 	os_free(sta);
 }
 
+void hostapd_free_sta_info(struct hostapd_data *hapd, struct sta_info *sta,
+			   u16 reason)
+{
+	if (sta->flags & WLAN_STA_AUTH) {
+		mlme_deauthenticate_indication(hapd, sta, reason);
+	}
+	wpa_printf(MSG_DEBUG, "Removing station " MACSTR, MAC2STR(sta->addr));
+	ap_free_sta(hapd, sta);
+}
+
+void hostapd_free_sta(struct hostapd_data *hapd, u8 *addr, u16 reason)
+{
+	struct sta_info *sta, *prev;
+
+	prev = sta = hapd->sta_list;
+
+	while (sta && memcmp(sta->addr, addr, ETH_ALEN)) {
+		prev = sta;
+		sta = sta->next;
+	}
+
+	/* station not found */
+	if (!sta)
+		return;
+
+	if (sta == hapd->sta_list)
+		hapd->sta_list = sta->next;
+	else
+		prev->next = sta->next;
+
+	hostapd_free_sta_info(hapd, sta, reason);
+}
 
 void hostapd_free_stas(struct hostapd_data *hapd)
 {
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index cef428d..2ebe2db 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -144,6 +144,7 @@  int ap_for_each_sta(struct hostapd_data *hapd,
 struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
 void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
 void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
+void hostapd_free_sta(struct hostapd_data *hapd, u8 *addr, u16 reason);
 void hostapd_free_stas(struct hostapd_data *hapd);
 void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
 void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
@@ -174,6 +175,8 @@  static inline int ap_sta_is_authorized(struct sta_info *sta)
 	return sta->flags & WLAN_STA_AUTHORIZED;
 }
 
+void hostapd_free_sta_info(struct hostapd_data *hapd, struct sta_info *sta,
+			   u16 reason);
 void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
 void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);