#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"
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "gas_serv.h"
+#include "wnm_ap.h"
+#include "ndisc_snoop.h"
#include "sta_info.h"
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
struct sta_info *sta);
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
+static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx);
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
#ifdef CONFIG_IEEE80211W
}
+void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ sta_ip6addr_del(hapd, sta);
+}
+
+
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
int set_beacon = 0;
if (sta->flags & WLAN_STA_WDS)
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
- if (!(sta->flags & WLAN_STA_PREAUTH))
+ if (sta->ipaddr)
+ hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
+ ap_sta_ip6addr_del(hapd, sta);
+
+ if (!hapd->iface->driver_ap_teardown &&
+ !(sta->flags & WLAN_STA_PREAUTH))
hostapd_drv_sta_remove(hapd, sta->addr);
ap_sta_hash_del(hapd, sta);
hapd->iface->num_sta_ht_20mhz--;
}
+#ifdef CONFIG_IEEE80211N
+ ht40_intolerant_remove(hapd->iface, sta);
+#endif /* CONFIG_IEEE80211N */
+
#ifdef CONFIG_P2P
if (sta->no_p2p_set) {
sta->no_p2p_set = 0;
set_beacon++;
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
+#ifdef CONFIG_MESH
+ if (hapd->mesh_sta_free_cb)
+ hapd->mesh_sta_free_cb(sta);
+#endif /* CONFIG_MESH */
+
if (set_beacon)
ieee802_11_set_beacons(hapd->iface);
__func__, MAC2STR(sta->addr));
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
- eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
- eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
+ eloop_cancel_timeout(ap_handle_session_warning_timer, 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 */
- os_free(sta->last_assoc_req);
+#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);
os_free(sta->identity);
os_free(sta->radius_cui);
os_free(sta->remediation_url);
+ wpabuf_free(sta->hs20_deauth_req);
+ os_free(sta->hs20_session_info_url);
#ifdef CONFIG_SAE
sae_clear_data(sta->sae);
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,
* but do not disconnect the station now.
*/
next_time = hapd->conf->ap_max_inactivity + fuzz;
- } else if (inactive_sec < hapd->conf->ap_max_inactivity &&
- sta->flags & WLAN_STA_ASSOC) {
+ } else if (inactive_sec == -ENOENT) {
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+ "Station " MACSTR " has lost its driver entry",
+ MAC2STR(sta->addr));
+
+ /* Avoid sending client probe on removed client */
+ sta->timeout_next = STA_DISASSOC;
+ goto skip_poll;
+ } else if (inactive_sec < hapd->conf->ap_max_inactivity) {
/* station activity detected; reset timeout state */
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has been active %is ago",
next_time = hapd->conf->ap_max_inactivity;
}
+skip_poll:
if (next_time) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%lu seconds)",
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;
- u8 addr[ETH_ALEN];
+ 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 "
return;
}
+ hostapd_drv_sta_deauth(hapd, sta->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
mlme_deauthenticate_indication(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
"session timeout");
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
- os_memcpy(addr, sta->addr, ETH_ALEN);
ap_free_sta(hapd, sta);
- hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
}
}
+static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx)
+{
+#ifdef CONFIG_WNM
+ struct hostapd_data *hapd = eloop_ctx;
+ struct sta_info *sta = timeout_ctx;
+
+ 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;
+
+ wnm_send_ess_disassoc_imminent(hapd, sta, sta->hs20_session_info_url,
+ sta->hs20_disassoc_timer);
+#endif /* CONFIG_WNM */
+}
+
+
+void ap_sta_session_warning_timeout(struct hostapd_data *hapd,
+ struct sta_info *sta, int warning_time)
+{
+ eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
+ eloop_register_timeout(warning_time, 0, ap_handle_session_warning_timer,
+ hapd, sta);
+}
+
+
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
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);
return sta;
}
{
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
- wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
- MAC2STR(sta->addr));
+ if (sta->ipaddr)
+ hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
+ ap_sta_ip6addr_del(hapd, sta);
+
+ 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);
}
{
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_DEAUTH;
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);
}
{
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
- sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+ sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
+ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
ap_sta_set_authorized(hapd, sta, 0);
sta->timeout_next = STA_REMOVE;
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
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;
-
- /*
- * During 1x reauth, if the vlan id changes, then remove the old id and
- * proceed furthur to add the new one.
- */
- if (old_vlanid > 0)
- vlan_remove_dynamic(hapd, old_vlanid);
+ 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 "
"binding station to (vlan_id=%d)",
sta->vlan_id);
- return -1;
+ ret = -1;
+ goto done;
} else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
if (vlan == NULL) {
HOSTAPD_LEVEL_DEBUG, "could not add "
"dynamic VLAN interface for vlan_id=%d",
sta->vlan_id);
- return -1;
+ ret = -1;
+ goto done;
}
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);
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
"entry to vlan_id=%d", sta->vlan_id);
}
+
+ /* During 1x reauth, if the vlan id changes, then remove the old id. */
+ if (old_vlanid > 0 && old_vlanid != sta->vlan_id)
+ vlan_remove_dynamic(hapd, old_vlanid);
+done:
+
return ret;
#else /* CONFIG_NO_VLAN */
return 0;
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;
sta->sa_query_trans_id = nbuf;
sta->sa_query_count++;
- os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
+ if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
+ /*
+ * We don't really care which ID is used here, so simply
+ * hardcode this if the mostly theoretical os_get_random()
+ * failure happens.
+ */
+ trans_id[0] = 0x12;
+ trans_id[1] = 0x34;
+ }
timeout = hapd->conf->assoc_sa_query_retry_timeout;
sec = ((timeout / 1000) * 1024) / 1000;
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return;
+ if (authorized)
+ sta->flags |= WLAN_STA_AUTHORIZED;
+ else
+ sta->flags &= ~WLAN_STA_AUTHORIZED;
+
#ifdef CONFIG_P2P
if (hapd->p2p_group == NULL) {
if (sta->p2p_ie != NULL &&
dev_addr = addr;
} else
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
-#endif /* CONFIG_P2P */
if (dev_addr)
os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR,
MAC2STR(sta->addr), MAC2STR(dev_addr));
else
+#endif /* CONFIG_P2P */
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
+ if (hapd->sta_authorized_cb)
+ hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
+ sta->addr, authorized, dev_addr);
+
if (authorized) {
char ip_addr[100];
ip_addr[0] = '\0';
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED "%s%s",
buf, ip_addr);
-
- sta->flags |= WLAN_STA_AUTHORIZED;
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED "%s", buf);
-
- sta->flags &= ~WLAN_STA_AUTHORIZED;
}
- if (hapd->sta_authorized_cb)
- hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
- sta->addr, authorized, dev_addr);
+#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;
buf[0] = '\0';
- res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
(flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
(flags & WLAN_STA_GAS ? "[GAS]" : ""),
(flags & WLAN_STA_VHT ? "[VHT]" : ""),
+ (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
(flags & WLAN_STA_WNM_SLEEP_MODE ?
"[WNM_SLEEP_MODE]" : ""));
+ if (os_snprintf_error(buflen, res))
+ res = -1;
return res;
}