#include "radius/radius.h"
#include "radius/radius_client.h"
#include "p2p/p2p.h"
+#include "fst/fst.h"
#include "hostapd.h"
#include "accounting.h"
#include "ieee802_1x.h"
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
- eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
- eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
sae_clear_retransmit_timer(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
wpa_auth_sta_deinit(sta->wpa_sm);
rsn_preauth_free_station(hapd, sta);
#ifndef CONFIG_NO_RADIUS
radius_client_flush_auth(hapd->radius, sta->addr);
#endif /* CONFIG_NO_RADIUS */
+#ifndef CONFIG_NO_VLAN
+ /*
+ * sta->wpa_sm->group needs to be released before so that
+ * vlan_remove_dynamic() can check that no stations are left on the
+ * AP_VLAN netdev.
+ */
+ if (sta->vlan_id_bound) {
+ /*
+ * Need to remove the STA entry before potentially removing the
+ * VLAN.
+ */
+ if (hapd->iface->driver_ap_teardown &&
+ !(sta->flags & WLAN_STA_PREAUTH))
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ vlan_remove_dynamic(hapd, sta->vlan_id_bound);
+ }
+#endif /* CONFIG_NO_VLAN */
+
os_free(sta->challenge);
#ifdef CONFIG_IEEE80211W
wpabuf_free(sta->wps_ie);
wpabuf_free(sta->p2p_ie);
wpabuf_free(sta->hs20_ie);
+#ifdef CONFIG_FST
+ wpabuf_free(sta->mb_ies);
+#endif /* CONFIG_FST */
os_free(sta->ht_capabilities);
os_free(sta->vht_capabilities);
unsigned long next_time = 0;
int reason;
- wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
- __func__, MAC2STR(sta->addr), sta->flags,
+ wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%x timeout_next=%d",
+ hapd->conf->iface, __func__, MAC2STR(sta->addr), sta->flags,
sta->timeout_next);
if (sta->timeout_next == STA_REMOVE) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated due to "
"inactivity");
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
+ wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
if (!(sta->flags & WLAN_STA_AUTH)) {
if (sta->flags & WLAN_STA_GAS) {
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
- wpa_printf(MSG_DEBUG, "WNM: Session warning time reached for " MACSTR,
- MAC2STR(sta->addr));
+ wpa_printf(MSG_DEBUG, "%s: WNM: Session warning time reached for "
+ MACSTR, hapd->conf->iface, MAC2STR(sta->addr));
if (sta->hs20_session_info_url == NULL)
return;
return NULL;
}
sta->acct_interim_interval = hapd->conf->acct_interim_interval;
- accounting_sta_get_id(hapd, sta);
+ if (accounting_sta_get_id(hapd, sta) < 0) {
+ os_free(sta);
+ return NULL;
+ }
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
hapd->sta_list = sta;
hapd->num_sta++;
ap_sta_hash_add(hapd, sta);
- sta->ssid = &hapd->conf->ssid;
ap_sta_remove_in_other_bss(hapd, sta);
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
dl_list_init(&sta->ip6addr);
hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
ap_sta_ip6addr_del(hapd, sta);
- wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
- MAC2STR(sta->addr));
+ wpa_printf(MSG_DEBUG, "%s: Removing STA " MACSTR " from kernel driver",
+ hapd->conf->iface, MAC2STR(sta->addr));
if (hostapd_drv_sta_remove(hapd, sta->addr) &&
sta->flags & WLAN_STA_ASSOC) {
- wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
- " from kernel driver.", MAC2STR(sta->addr));
+ wpa_printf(MSG_DEBUG, "%s: Could not remove station " MACSTR
+ " from kernel driver",
+ hapd->conf->iface, MAC2STR(sta->addr));
return -1;
}
return 0;
if (!sta2)
continue;
+ wpa_printf(MSG_DEBUG, "%s: disconnect old STA " MACSTR
+ " association from another BSS %s",
+ hapd->conf->iface, MAC2STR(sta2->addr),
+ bss->conf->iface);
ap_sta_disconnect(bss, sta2, sta2->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
}
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
+ wpa_printf(MSG_DEBUG, "%s: Disassociation callback for STA " MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
ap_sta_remove(hapd, sta);
mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
}
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
ap_handle_timer, hapd, sta);
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
sta->disassoc_reason = reason;
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
+ wpa_printf(MSG_DEBUG, "%s: Deauthentication callback for STA " MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
ap_sta_remove(hapd, sta);
mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
}
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
ap_handle_timer, hapd, sta);
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
sta->deauth_reason = reason;
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
#endif /* CONFIG_WPS */
-int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
- int old_vlanid)
+int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifndef CONFIG_NO_VLAN
const char *iface;
struct hostapd_vlan *vlan = NULL;
int ret;
-
- /*
- * Do not proceed furthur if the vlan id remains same. We do not want
- * duplicate dynamic vlan entries.
- */
- if (sta->vlan_id == old_vlanid)
- return 0;
+ int old_vlanid = sta->vlan_id_bound;
iface = hapd->conf->iface;
- if (sta->ssid->vlan[0])
- iface = sta->ssid->vlan;
+ if (hapd->conf->ssid.vlan[0])
+ iface = hapd->conf->ssid.vlan;
- if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
+ if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
sta->vlan_id = 0;
else if (sta->vlan_id > 0) {
struct hostapd_vlan *wildcard_vlan = NULL;
iface = vlan->ifname;
}
+ /*
+ * Do not increment ref counters if the VLAN ID remains same, but do
+ * not skip hostapd_drv_set_sta_vlan() as hostapd_drv_sta_remove() might
+ * have been called before.
+ */
+ if (sta->vlan_id == old_vlanid)
+ goto skip_counting;
+
if (sta->vlan_id > 0 && vlan == NULL) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
}
iface = vlan->ifname;
- if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "could not "
- "configure encryption for dynamic VLAN "
- "interface for vlan_id=%d",
- sta->vlan_id);
- }
-
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
"interface '%s'", iface);
- } else if (vlan && vlan->vlan_id == sta->vlan_id) {
- if (sta->vlan_id > 0) {
- vlan->dynamic_vlan++;
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "updated existing "
- "dynamic VLAN interface '%s'", iface);
- }
-
- /*
- * Update encryption configuration for statically generated
- * VLAN interface. This is only used for static WEP
- * configuration for the case where hostapd did not yet know
- * which keys are to be used when the interface was added.
- */
- if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "could not "
- "configure encryption for VLAN "
- "interface for vlan_id=%d",
- sta->vlan_id);
- }
+ } else if (vlan && vlan->vlan_id == sta->vlan_id &&
+ vlan->dynamic_vlan > 0) {
+ vlan->dynamic_vlan++;
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "updated existing dynamic VLAN interface '%s'",
+ iface);
}
+ /* ref counters have been increased, so mark the station */
+ sta->vlan_id_bound = sta->vlan_id;
+
+skip_counting:
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "binding station to interface "
"'%s'", iface);
"entry to vlan_id=%d", sta->vlan_id);
}
-done:
/* During 1x reauth, if the vlan id changes, then remove the old id. */
- if (old_vlanid > 0)
+ if (old_vlanid > 0 && old_vlanid != sta->vlan_id)
vlan_remove_dynamic(hapd, old_vlanid);
+done:
return ret;
#else /* CONFIG_NO_VLAN */
unsigned int timeout, sec, usec;
u8 *trans_id, *nbuf;
+ wpa_printf(MSG_DEBUG, "%s: SA Query timer for STA " MACSTR
+ " (count=%d)",
+ hapd->conf->iface, MAC2STR(sta->addr), sta->sa_query_count);
+
if (sta->sa_query_count > 0 &&
ap_check_sa_query_timeout(hapd, sta))
return;
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED "%s", buf);
}
+
+#ifdef CONFIG_FST
+ if (hapd->iface->fst) {
+ if (authorized)
+ fst_notify_peer_connected(hapd->iface->fst, sta->addr);
+ else
+ fst_notify_peer_disconnected(hapd->iface->fst,
+ sta->addr);
+ }
+#endif /* CONFIG_FST */
}
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 reason)
{
+ if (sta)
+ wpa_printf(MSG_DEBUG, "%s: %s STA " MACSTR " reason=%u",
+ hapd->conf->iface, __func__, MAC2STR(sta->addr),
+ reason);
+ else if (addr)
+ wpa_printf(MSG_DEBUG, "%s: %s addr " MACSTR " reason=%u",
+ hapd->conf->iface, __func__, MAC2STR(addr),
+ reason);
if (sta == NULL && addr)
sta = ap_get_sta(hapd, addr);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
- wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
+ wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
- __func__, MAC2STR(sta->addr),
+ hapd->conf->iface, __func__, MAC2STR(sta->addr),
AP_MAX_INACTIVITY_AFTER_DEAUTH);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
}
+void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ if (eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta) > 0)
+ wpa_printf(MSG_DEBUG,
+ "%s: Removed ap_sta_deauth_cb_timeout timeout for "
+ MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
+ if (eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta) > 0)
+ wpa_printf(MSG_DEBUG,
+ "%s: Removed ap_sta_disassoc_cb_timeout timeout for "
+ MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
+}
+
+
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
{
int res;