[OpenWrt-Devel] hostapd: Add client association log file
diff mbox

Message ID 20150121135911.GK13405@zirkel.wertarbyte.de
State Rejected
Delegated to: Felix Fietkau
Headers show

Commit Message

Stefan Tomanek Jan. 21, 2015, 1:59 p.m. UTC
This change adds the configuration option "assoc_log_file" to hostapd, making
it possible to specify a log file to which clients joining and parting the
corresponding BSS are written.

Every BSS can have an individual log file, and each entry written contains a
timestamp, an indicator whether the client is associating (+) or disassociating
(-), the client and the bss hardware addresses as well as the device and SSID
identifiers of the affected network. This makes it easy to join the file with
the leases database of an DHCP server like dnsmasq.

To use a logfile with OpenWrt, simply add an assoc_log_file entry to the
wireless network:

config wifi-iface
	option device 'radio1'
	option network 'hotspot'
	option ssid 'MyNetwork'
	option mode 'ap'
	option encryption 'none'
	option assoc_log_file '/tmp/assoc_log-hotspot'

Signed-off-by: Stefan Tomanek <stefan.tomanek+openwrt@wertarbyte.de>
---
 package/network/services/hostapd/files/netifd.sh   |    7 +-
 ...rite-client-dis-associations-to-a-logfile.patch |  231 ++++++++++++++++++++
 2 files changed, 237 insertions(+), 1 deletions(-)
 create mode 100644 package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch

Comments

John Crispin Feb. 13, 2015, 10:54 a.m. UTC | #1
nak on this one as it was rejected upstream aswell

On 21/01/2015 14:59, Stefan Tomanek wrote:
> This change adds the configuration option "assoc_log_file" to hostapd, making
> it possible to specify a log file to which clients joining and parting the
> corresponding BSS are written.
> 
> Every BSS can have an individual log file, and each entry written contains a
> timestamp, an indicator whether the client is associating (+) or disassociating
> (-), the client and the bss hardware addresses as well as the device and SSID
> identifiers of the affected network. This makes it easy to join the file with
> the leases database of an DHCP server like dnsmasq.
> 
> To use a logfile with OpenWrt, simply add an assoc_log_file entry to the
> wireless network:
> 
> config wifi-iface
> 	option device 'radio1'
> 	option network 'hotspot'
> 	option ssid 'MyNetwork'
> 	option mode 'ap'
> 	option encryption 'none'
> 	option assoc_log_file '/tmp/assoc_log-hotspot'
> 
> Signed-off-by: Stefan Tomanek <stefan.tomanek+openwrt@wertarbyte.de>
> ---
>  package/network/services/hostapd/files/netifd.sh   |    7 +-
>  ...rite-client-dis-associations-to-a-logfile.patch |  231 ++++++++++++++++++++
>  2 files changed, 237 insertions(+), 1 deletions(-)
>  create mode 100644 package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch
> 
> diff --git a/package/network/services/hostapd/files/netifd.sh b/package/network/services/hostapd/files/netifd.sh
> index ed2a631..be94398 100644
> --- a/package/network/services/hostapd/files/netifd.sh
> +++ b/package/network/services/hostapd/files/netifd.sh
> @@ -159,6 +159,8 @@ hostapd_common_add_bss_config() {
>  	config_add_int mcast_rate
>  	config_add_array basic_rate
>  	config_add_array supported_rates
> +
> +	config_add_string assoc_log_file
>  }
>  
>  hostapd_set_bss_options() {
> @@ -177,7 +179,7 @@ hostapd_set_bss_options() {
>  		wps_pushbutton wps_label ext_registrar wps_pbc_in_m1 \
>  		wps_device_type wps_device_name wps_manufacturer wps_pin \
>  		macfilter ssid wmm uapsd hidden short_preamble rsn_preauth \
> -		iapp_interface
> +		iapp_interface assoc_log_file
>  
>  	set_default isolate 0
>  	set_default maxassoc 0
> @@ -189,6 +191,9 @@ hostapd_set_bss_options() {
>  	set_default uapsd 1
>  
>  	append bss_conf "ctrl_interface=/var/run/hostapd"
> +	if [ "$assoc_log_file" ]; then
> +		append bss_conf "assoc_log_file=$assoc_log_file" "$N"
> +	fi
>  	if [ "$isolate" -gt 0 ]; then
>  		append bss_conf "ap_isolate=$isolate" "$N"
>  	fi
> diff --git a/package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch b/package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch
> new file mode 100644
> index 0000000..7a87529
> --- /dev/null
> +++ b/package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch
> @@ -0,0 +1,231 @@
> +Write client (dis)associations to a logfile
> +
> +This change adds the configuration option "assoc_log_file" to hostapd, making
> +it possible to specify a log file to which clients joining and parting the
> +corresponding BSS are written.
> +
> +Every BSS can have an individual log file, and each entry written contains a
> +timestamp, an indicator whether the client is associating (+) or disassociating
> +(-), the client and the bss hardware addresses as well as the device and SSID
> +identifiers of the affected network. This makes it easy to join the file with
> +the leases database of an DHCP server like dnsmasq.
> +---
> + hostapd/config_file.c |  3 +++
> + hostapd/hostapd.conf  |  3 +++
> + hostapd/main.c        |  6 ++++++
> + src/ap/ap_config.c    | 27 +++++++++++++++++++++++++++
> + src/ap/ap_config.h    |  5 +++++
> + src/ap/ap_mlme.c      | 26 ++++++++++++++++++++++++++
> + src/ap/hostapd.c      |  4 ++++
> + src/ap/hostapd.h      |  2 ++
> + 8 files changed, 76 insertions(+)
> +
> +diff --git a/hostapd/config_file.c b/hostapd/config_file.c
> +index ddebf1f..827f9b4 100644
> +--- a/hostapd/config_file.c
> ++++ b/hostapd/config_file.c
> +@@ -1876,6 +1876,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
> + 		bss->logger_syslog = atoi(pos);
> + 	} else if (os_strcmp(buf, "logger_stdout") == 0) {
> + 		bss->logger_stdout = atoi(pos);
> ++	} else if (os_strcmp(buf, "assoc_log_file") == 0) {
> ++		os_free(bss->assoc_log_file);
> ++		bss->assoc_log_file = os_strdup(pos);
> + 	} else if (os_strcmp(buf, "dump_file") == 0) {
> + 		wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
> + 			   line);
> +diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
> +index 2e6f841..31b2193 100644
> +--- a/hostapd/hostapd.conf
> ++++ b/hostapd/hostapd.conf
> +@@ -51,6 +51,9 @@ logger_syslog_level=2
> + logger_stdout=-1
> + logger_stdout_level=2
> + 
> ++# Clients joining or departing the AP can be logged to a separate file.
> ++assoc_log_file=/tmp/assoc_log-wlan0
> ++
> + # Interface for separate control program. If this is specified, hostapd
> + # will create this directory and a UNIX domain socket for listening to requests
> + # from external programs (CLI/GUI, etc.) for status information and
> +diff --git a/hostapd/main.c b/hostapd/main.c
> +index 5a47711..38a9ab2 100644
> +--- a/hostapd/main.c
> ++++ b/hostapd/main.c
> +@@ -258,6 +258,12 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
> + 		return NULL;
> + 	}
> + 
> ++	for (k = 0; k < iface->conf->num_bss; k++) {
> ++		int r = hostapd_open_assoc_log(iface->bss[k]);
> ++		if (r < 0)
> ++			return NULL;
> ++	}
> ++
> + 	return iface;
> + }
> + 
> +diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
> +index 90f1630..6d7389f 100644
> +--- a/src/ap/ap_config.c
> ++++ b/src/ap/ap_config.c
> +@@ -6,6 +6,8 @@
> +  * See README for more details.
> +  */
> + 
> ++#include <fcntl.h>
> ++
> + #include "utils/includes.h"
> + 
> + #include "utils/common.h"
> +@@ -18,6 +20,7 @@
> + #include "wpa_auth.h"
> + #include "sta_info.h"
> + #include "ap_config.h"
> ++#include "hostapd.h"
> + 
> + 
> + static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
> +@@ -201,6 +204,30 @@ int hostapd_mac_comp_empty(const void *a)
> + 	return os_memcmp(a, empty, sizeof(macaddr));
> + }
> + 
> ++int hostapd_open_assoc_log(struct hostapd_data *bss)
> ++{
> ++	char *alog = bss->conf->assoc_log_file;
> ++	if (alog) {
> ++		int fd = open(alog, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW, 0600);
> ++		if (fd < 0) {
> ++			wpa_printf(MSG_ERROR, "Error opening association log file '%s'\n", alog);
> ++			return -1;
> ++		}
> ++		bss->assoc_log_fd = fd;
> ++		return 1;
> ++	} else {
> ++		bss->assoc_log_fd = -1;
> ++	}
> ++	return 0;
> ++}
> ++
> ++void hostapd_close_assoc_log(struct hostapd_data *bss)
> ++{
> ++	if (bss->assoc_log_fd != -1) {
> ++		close(bss->assoc_log_fd);
> ++		bss->assoc_log_fd = -1;
> ++	}
> ++}
> + 
> + static int hostapd_config_read_wpa_psk(const char *fname,
> + 				       struct hostapd_ssid *ssid)
> +diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
> +index 18538c9..205ff42 100644
> +--- a/src/ap/ap_config.h
> ++++ b/src/ap/ap_config.h
> +@@ -217,6 +217,8 @@ struct hostapd_bss_config {
> + 	unsigned int logger_syslog; /* module bitfield */
> + 	unsigned int logger_stdout; /* module bitfield */
> + 
> ++	char *assoc_log_file;
> ++
> + 	int max_num_sta; /* maximum number of STAs in station table */
> + 
> + 	int dtim_period;
> +@@ -629,6 +631,9 @@ struct hostapd_config {
> + #endif /* CONFIG_ACS */
> + };
> + 
> ++struct hostapd_data;
> ++int hostapd_open_assoc_log(struct hostapd_data *bss);
> ++void hostapd_close_assoc_log(struct hostapd_data *bss);
> + 
> + int hostapd_mac_comp(const void *a, const void *b);
> + int hostapd_mac_comp_empty(const void *a);
> +diff --git a/src/ap/ap_mlme.c b/src/ap/ap_mlme.c
> +index 13604ed..2dd7d72 100644
> +--- a/src/ap/ap_mlme.c
> ++++ b/src/ap/ap_mlme.c
> +@@ -35,6 +35,23 @@ static const char * mlme_auth_alg_str(int alg)
> + }
> + #endif /* CONFIG_NO_HOSTAPD_LOGGER */
> + 
> ++static void write_assoc_log(struct hostapd_data *hapd, struct sta_info *sta, char op) {
> ++	struct os_time now;
> ++	int fd = hapd->assoc_log_fd;
> ++	if (fd >= 0) {
> ++		os_get_time(&now);
> ++		char msg[100];
> ++		sprintf(msg,
> ++		        "%lu\t" MACSTR "\t%c\t%s\t" MACSTR "\t'%s'\n",
> ++		        now.sec,
> ++		        MAC2STR(sta->addr),
> ++			op,
> ++		        hapd->conf->iface,
> ++		        MAC2STR(hapd->own_addr),
> ++		        wpa_ssid_txt(sta->ssid->ssid, sta->ssid->ssid_len));
> ++		write(fd, msg, strlen(msg));
> ++	}
> ++}
> + 
> + /**
> +  * mlme_authenticate_indication - Report the establishment of an authentication
> +@@ -104,6 +121,9 @@ void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta)
> + 		       HOSTAPD_LEVEL_DEBUG,
> + 		       "MLME-ASSOCIATE.indication(" MACSTR ")",
> + 		       MAC2STR(sta->addr));
> ++
> ++	write_assoc_log(hapd, sta, '+');
> ++
> + 	if (sta->auth_alg != WLAN_AUTH_FT)
> + 		mlme_deletekeys_request(hapd, sta);
> + }
> +@@ -128,6 +148,9 @@ void mlme_reassociate_indication(struct hostapd_data *hapd,
> + 		       HOSTAPD_LEVEL_DEBUG,
> + 		       "MLME-REASSOCIATE.indication(" MACSTR ")",
> + 		       MAC2STR(sta->addr));
> ++
> ++	write_assoc_log(hapd, sta, '@');
> ++
> + 	if (sta->auth_alg != WLAN_AUTH_FT)
> + 		mlme_deletekeys_request(hapd, sta);
> + }
> +@@ -152,6 +175,9 @@ void mlme_disassociate_indication(struct hostapd_data *hapd,
> + 		       HOSTAPD_LEVEL_DEBUG,
> + 		       "MLME-DISASSOCIATE.indication(" MACSTR ", %d)",
> + 		       MAC2STR(sta->addr), reason_code);
> ++
> ++	write_assoc_log(hapd, sta, '-');
> ++
> + 	mlme_deletekeys_request(hapd, sta);
> + }
> + 
> +diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
> +index 9fda339..8157a08 100644
> +--- a/src/ap/hostapd.c
> ++++ b/src/ap/hostapd.c
> +@@ -70,6 +70,10 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
> + 	radius_client_reconfig(hapd->radius, hapd->conf->radius);
> + #endif /* CONFIG_NO_RADIUS */
> + 
> ++	/* close and reopen assoc_log */
> ++	hostapd_close_assoc_log(hapd);
> ++	hostapd_open_assoc_log(hapd);
> ++
> + 	ssid = &hapd->conf->ssid;
> + 	if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
> + 	    ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
> +diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
> +index 3f79413..891c453 100644
> +--- a/src/ap/hostapd.h
> ++++ b/src/ap/hostapd.h
> +@@ -113,6 +113,8 @@ struct hostapd_data {
> + #define STA_HASH(sta) (sta[5])
> + 	struct sta_info *sta_hash[STA_HASH_SIZE];
> + 
> ++	int assoc_log_fd;
> ++
> + 	/*
> + 	 * Bitfield for indicating which AIDs are allocated. Only AID values
> + 	 * 1-2007 are used and as such, the bit at index 0 corresponds to AID
> +-- 
> +2.1.3
> +
>

Patch
diff mbox

diff --git a/package/network/services/hostapd/files/netifd.sh b/package/network/services/hostapd/files/netifd.sh
index ed2a631..be94398 100644
--- a/package/network/services/hostapd/files/netifd.sh
+++ b/package/network/services/hostapd/files/netifd.sh
@@ -159,6 +159,8 @@  hostapd_common_add_bss_config() {
 	config_add_int mcast_rate
 	config_add_array basic_rate
 	config_add_array supported_rates
+
+	config_add_string assoc_log_file
 }
 
 hostapd_set_bss_options() {
@@ -177,7 +179,7 @@  hostapd_set_bss_options() {
 		wps_pushbutton wps_label ext_registrar wps_pbc_in_m1 \
 		wps_device_type wps_device_name wps_manufacturer wps_pin \
 		macfilter ssid wmm uapsd hidden short_preamble rsn_preauth \
-		iapp_interface
+		iapp_interface assoc_log_file
 
 	set_default isolate 0
 	set_default maxassoc 0
@@ -189,6 +191,9 @@  hostapd_set_bss_options() {
 	set_default uapsd 1
 
 	append bss_conf "ctrl_interface=/var/run/hostapd"
+	if [ "$assoc_log_file" ]; then
+		append bss_conf "assoc_log_file=$assoc_log_file" "$N"
+	fi
 	if [ "$isolate" -gt 0 ]; then
 		append bss_conf "ap_isolate=$isolate" "$N"
 	fi
diff --git a/package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch b/package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch
new file mode 100644
index 0000000..7a87529
--- /dev/null
+++ b/package/network/services/hostapd/patches/720-Write-client-dis-associations-to-a-logfile.patch
@@ -0,0 +1,231 @@ 
+Write client (dis)associations to a logfile
+
+This change adds the configuration option "assoc_log_file" to hostapd, making
+it possible to specify a log file to which clients joining and parting the
+corresponding BSS are written.
+
+Every BSS can have an individual log file, and each entry written contains a
+timestamp, an indicator whether the client is associating (+) or disassociating
+(-), the client and the bss hardware addresses as well as the device and SSID
+identifiers of the affected network. This makes it easy to join the file with
+the leases database of an DHCP server like dnsmasq.
+---
+ hostapd/config_file.c |  3 +++
+ hostapd/hostapd.conf  |  3 +++
+ hostapd/main.c        |  6 ++++++
+ src/ap/ap_config.c    | 27 +++++++++++++++++++++++++++
+ src/ap/ap_config.h    |  5 +++++
+ src/ap/ap_mlme.c      | 26 ++++++++++++++++++++++++++
+ src/ap/hostapd.c      |  4 ++++
+ src/ap/hostapd.h      |  2 ++
+ 8 files changed, 76 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index ddebf1f..827f9b4 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -1876,6 +1876,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ 		bss->logger_syslog = atoi(pos);
+ 	} else if (os_strcmp(buf, "logger_stdout") == 0) {
+ 		bss->logger_stdout = atoi(pos);
++	} else if (os_strcmp(buf, "assoc_log_file") == 0) {
++		os_free(bss->assoc_log_file);
++		bss->assoc_log_file = os_strdup(pos);
+ 	} else if (os_strcmp(buf, "dump_file") == 0) {
+ 		wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
+ 			   line);
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index 2e6f841..31b2193 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -51,6 +51,9 @@ logger_syslog_level=2
+ logger_stdout=-1
+ logger_stdout_level=2
+ 
++# Clients joining or departing the AP can be logged to a separate file.
++assoc_log_file=/tmp/assoc_log-wlan0
++
+ # Interface for separate control program. If this is specified, hostapd
+ # will create this directory and a UNIX domain socket for listening to requests
+ # from external programs (CLI/GUI, etc.) for status information and
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 5a47711..38a9ab2 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -258,6 +258,12 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
+ 		return NULL;
+ 	}
+ 
++	for (k = 0; k < iface->conf->num_bss; k++) {
++		int r = hostapd_open_assoc_log(iface->bss[k]);
++		if (r < 0)
++			return NULL;
++	}
++
+ 	return iface;
+ }
+ 
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 90f1630..6d7389f 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -6,6 +6,8 @@
+  * See README for more details.
+  */
+ 
++#include <fcntl.h>
++
+ #include "utils/includes.h"
+ 
+ #include "utils/common.h"
+@@ -18,6 +20,7 @@
+ #include "wpa_auth.h"
+ #include "sta_info.h"
+ #include "ap_config.h"
++#include "hostapd.h"
+ 
+ 
+ static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
+@@ -201,6 +204,30 @@ int hostapd_mac_comp_empty(const void *a)
+ 	return os_memcmp(a, empty, sizeof(macaddr));
+ }
+ 
++int hostapd_open_assoc_log(struct hostapd_data *bss)
++{
++	char *alog = bss->conf->assoc_log_file;
++	if (alog) {
++		int fd = open(alog, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW, 0600);
++		if (fd < 0) {
++			wpa_printf(MSG_ERROR, "Error opening association log file '%s'\n", alog);
++			return -1;
++		}
++		bss->assoc_log_fd = fd;
++		return 1;
++	} else {
++		bss->assoc_log_fd = -1;
++	}
++	return 0;
++}
++
++void hostapd_close_assoc_log(struct hostapd_data *bss)
++{
++	if (bss->assoc_log_fd != -1) {
++		close(bss->assoc_log_fd);
++		bss->assoc_log_fd = -1;
++	}
++}
+ 
+ static int hostapd_config_read_wpa_psk(const char *fname,
+ 				       struct hostapd_ssid *ssid)
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 18538c9..205ff42 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -217,6 +217,8 @@ struct hostapd_bss_config {
+ 	unsigned int logger_syslog; /* module bitfield */
+ 	unsigned int logger_stdout; /* module bitfield */
+ 
++	char *assoc_log_file;
++
+ 	int max_num_sta; /* maximum number of STAs in station table */
+ 
+ 	int dtim_period;
+@@ -629,6 +631,9 @@ struct hostapd_config {
+ #endif /* CONFIG_ACS */
+ };
+ 
++struct hostapd_data;
++int hostapd_open_assoc_log(struct hostapd_data *bss);
++void hostapd_close_assoc_log(struct hostapd_data *bss);
+ 
+ int hostapd_mac_comp(const void *a, const void *b);
+ int hostapd_mac_comp_empty(const void *a);
+diff --git a/src/ap/ap_mlme.c b/src/ap/ap_mlme.c
+index 13604ed..2dd7d72 100644
+--- a/src/ap/ap_mlme.c
++++ b/src/ap/ap_mlme.c
+@@ -35,6 +35,23 @@ static const char * mlme_auth_alg_str(int alg)
+ }
+ #endif /* CONFIG_NO_HOSTAPD_LOGGER */
+ 
++static void write_assoc_log(struct hostapd_data *hapd, struct sta_info *sta, char op) {
++	struct os_time now;
++	int fd = hapd->assoc_log_fd;
++	if (fd >= 0) {
++		os_get_time(&now);
++		char msg[100];
++		sprintf(msg,
++		        "%lu\t" MACSTR "\t%c\t%s\t" MACSTR "\t'%s'\n",
++		        now.sec,
++		        MAC2STR(sta->addr),
++			op,
++		        hapd->conf->iface,
++		        MAC2STR(hapd->own_addr),
++		        wpa_ssid_txt(sta->ssid->ssid, sta->ssid->ssid_len));
++		write(fd, msg, strlen(msg));
++	}
++}
+ 
+ /**
+  * mlme_authenticate_indication - Report the establishment of an authentication
+@@ -104,6 +121,9 @@ void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta)
+ 		       HOSTAPD_LEVEL_DEBUG,
+ 		       "MLME-ASSOCIATE.indication(" MACSTR ")",
+ 		       MAC2STR(sta->addr));
++
++	write_assoc_log(hapd, sta, '+');
++
+ 	if (sta->auth_alg != WLAN_AUTH_FT)
+ 		mlme_deletekeys_request(hapd, sta);
+ }
+@@ -128,6 +148,9 @@ void mlme_reassociate_indication(struct hostapd_data *hapd,
+ 		       HOSTAPD_LEVEL_DEBUG,
+ 		       "MLME-REASSOCIATE.indication(" MACSTR ")",
+ 		       MAC2STR(sta->addr));
++
++	write_assoc_log(hapd, sta, '@');
++
+ 	if (sta->auth_alg != WLAN_AUTH_FT)
+ 		mlme_deletekeys_request(hapd, sta);
+ }
+@@ -152,6 +175,9 @@ void mlme_disassociate_indication(struct hostapd_data *hapd,
+ 		       HOSTAPD_LEVEL_DEBUG,
+ 		       "MLME-DISASSOCIATE.indication(" MACSTR ", %d)",
+ 		       MAC2STR(sta->addr), reason_code);
++
++	write_assoc_log(hapd, sta, '-');
++
+ 	mlme_deletekeys_request(hapd, sta);
+ }
+ 
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 9fda339..8157a08 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -70,6 +70,10 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
+ 	radius_client_reconfig(hapd->radius, hapd->conf->radius);
+ #endif /* CONFIG_NO_RADIUS */
+ 
++	/* close and reopen assoc_log */
++	hostapd_close_assoc_log(hapd);
++	hostapd_open_assoc_log(hapd);
++
+ 	ssid = &hapd->conf->ssid;
+ 	if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
+ 	    ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 3f79413..891c453 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -113,6 +113,8 @@ struct hostapd_data {
+ #define STA_HASH(sta) (sta[5])
+ 	struct sta_info *sta_hash[STA_HASH_SIZE];
+ 
++	int assoc_log_fd;
++
+ 	/*
+ 	 * Bitfield for indicating which AIDs are allocated. Only AID values
+ 	 * 1-2007 are used and as such, the bit at index 0 corresponds to AID
+-- 
+2.1.3
+