18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / Station table
3391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/wpa_ctrl.h"
15a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#include "common/sae.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius_client.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "accounting.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_1x.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h"
23d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#include "ieee802_11_auth.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "preauth_auth.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "beacon.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_mlme.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "vlan_init.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_hostapd.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h"
3204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "gas_serv.h"
33f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#include "wnm_ap.h"
346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "ndisc_snoop.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h"
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct sta_info *sta);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
40f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx);
411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ap_for_each_sta(struct hostapd_data *hapd,
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      void *ctx),
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    void *ctx)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (sta = hapd->sta_list; sta; sta = sta->next) {
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cb(hapd, sta, ctx))
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *s;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s = hapd->sta_hash[STA_HASH(sta)];
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s = s->hnext;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return s;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
75391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#ifdef CONFIG_P2P
76391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstruct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr)
77391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{
78391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	struct sta_info *sta;
79391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
80391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	for (sta = hapd->sta_list; sta; sta = sta->next) {
81391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		const u8 *p2p_dev_addr;
82391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
83391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (sta->p2p_ie == NULL)
84391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			continue;
85391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
86391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
87391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (p2p_dev_addr == NULL)
88391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			continue;
89391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
90391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (os_memcmp(p2p_dev_addr, addr, ETH_ALEN) == 0)
91391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			return sta;
92391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	}
93391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
94391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	return NULL;
95391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt}
96391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#endif /* CONFIG_P2P */
97391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
98391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *tmp;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->sta_list == sta) {
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->sta_list = sta->next;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = hapd->sta_list;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (tmp != NULL && tmp->next != sta)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = tmp->next;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL) {
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "list.", MAC2STR(sta->addr));
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp->next = sta->next;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->sta_hash[STA_HASH(sta->addr)] = sta;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *s;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s = hapd->sta_hash[STA_HASH(sta->addr)];
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s == NULL) return;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(s->addr, sta->addr, 6) == 0) {
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (s->hnext != NULL &&
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s = s->hnext;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s->hnext != NULL)
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		s->hnext = s->hnext->hnext;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " from hash table", MAC2STR(sta->addr));
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
1496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sta_ip6addr_del(hapd, sta);
1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int set_beacon = 0;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	accounting_sta_stop(hapd, sta);
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* just in case */
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sta_set_authorized(hapd, sta, 0);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->flags & WLAN_STA_WDS)
164c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (sta->ipaddr)
1676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
1686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ap_sta_ip6addr_del(hapd, sta);
1696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
170a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	if (!hapd->iface->driver_ap_teardown &&
171a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt	    !(sta->flags & WLAN_STA_PREAUTH))
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_drv_sta_remove(hapd, sta->addr);
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt#ifndef CONFIG_NO_VLAN
1758347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	if (sta->vlan_id_bound) {
1768347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		/*
1778347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		 * Need to remove the STA entry before potentially removing the
1788347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		 * VLAN.
1798347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		 */
1808347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		if (hapd->iface->driver_ap_teardown &&
1818347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		    !(sta->flags & WLAN_STA_PREAUTH))
1828347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt			hostapd_drv_sta_remove(hapd, sta->addr);
1838347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		vlan_remove_dynamic(hapd, sta->vlan_id_bound);
1848347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	}
1858347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt#endif /* CONFIG_NO_VLAN */
1868347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sta_hash_del(hapd, sta);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sta_list_del(hapd, sta);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->aid > 0)
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->sta_aid[(sta->aid - 1) / 32] &=
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			~BIT((sta->aid - 1) % 32);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->num_sta--;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->nonerp_set) {
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->nonerp_set = 0;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->iface->num_sta_non_erp--;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hapd->iface->num_sta_non_erp == 0)
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			set_beacon++;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->no_short_slot_time_set) {
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->no_short_slot_time_set = 0;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->iface->num_sta_no_short_slot_time--;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    && hapd->iface->num_sta_no_short_slot_time == 0)
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			set_beacon++;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->no_short_preamble_set) {
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->no_short_preamble_set = 0;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->iface->num_sta_no_short_preamble--;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    && hapd->iface->num_sta_no_short_preamble == 0)
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			set_beacon++;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->no_ht_gf_set) {
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->no_ht_gf_set = 0;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->iface->num_sta_ht_no_gf--;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->no_ht_set) {
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->no_ht_set = 0;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->iface->num_sta_no_ht--;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->ht_20mhz_set) {
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->ht_20mhz_set = 0;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->iface->num_sta_ht_20mhz--;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#ifdef CONFIG_IEEE80211N
2347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	ht40_intolerant_remove(hapd->iface, sta);
2357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#endif /* CONFIG_IEEE80211N */
2367832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->no_p2p_set) {
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->no_p2p_set = 0;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->num_sta_no_p2p--;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hapd->num_sta_no_p2p == 0)
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_p2p_non_p2p_sta_disconnected(hapd);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_ht_operation_update(hapd->iface) > 0)
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		set_beacon++;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH
2526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hapd->mesh_sta_free_cb)
2536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		hapd->mesh_sta_free_cb(sta);
2546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */
2556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (set_beacon)
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_11_set_beacons(hapd->iface);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR,
26004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   __func__, MAC2STR(sta->addr));
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
263f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
266ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt	sae_clear_retransmit_timer(hapd, sta);
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_free_station(sta);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_sta_deinit(sta->wpa_sm);
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_free_station(hapd, sta);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS
2729657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt	if (hapd->radius)
2739657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		radius_client_flush_auth(hapd->radius, sta->addr);
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sta->challenge);
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sta->sa_query_trans_id);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
28704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_INTERWORKING
28804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sta->gas_dialog) {
28904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		int i;
29004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		for (i = 0; i < GAS_DIALOG_MAX; i++)
29104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			gas_serv_dialog_clear(&sta->gas_dialog[i]);
29204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_free(sta->gas_dialog);
29304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
29404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_INTERWORKING */
29504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sta->wps_ie);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sta->p2p_ie);
298d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpabuf_free(sta->hs20_ie);
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sta->ht_capabilities);
301292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt	os_free(sta->vht_capabilities);
302d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	hostapd_free_psk_list(sta->psk);
30361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(sta->identity);
30461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(sta->radius_cui);
305f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	os_free(sta->remediation_url);
306f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	wpabuf_free(sta->hs20_deauth_req);
307f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	os_free(sta->hs20_session_info_url);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
309a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_SAE
310a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	sae_clear_data(sta->sae);
311a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	os_free(sta->sae);
312a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_SAE */
313a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sta);
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid hostapd_free_stas(struct hostapd_data *hapd)
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta, *prev;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta = hapd->sta_list;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (sta) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = sta;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sta->flags & WLAN_STA_AUTH) {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			mlme_deauthenticate_indication(
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hapd, sta, WLAN_REASON_UNSPECIFIED);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta = sta->next;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(prev->addr));
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ap_free_sta(hapd, prev);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ap_handle_timer - Per STA timer handler
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: struct hostapd_data *
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: struct sta_info *
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to check station activity and to remove inactive
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * stations.
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta = timeout_ctx;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long next_time = 0;
351b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	int reason;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
35304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
35404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   __func__, MAC2STR(sta->addr), sta->flags,
35504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   sta->timeout_next);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->timeout_next == STA_REMOVE) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "local deauth request");
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ap_free_sta(hapd, sta);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((sta->flags & WLAN_STA_ASSOC) &&
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sta->timeout_next == STA_NULLFUNC ||
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     sta->timeout_next == STA_DISASSOC)) {
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int inactive_sec;
36804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
36904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Add random value to timeout so that we don't end up bouncing
37004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * all stations at the same time if we have lots of associated
37104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * stations that are idle (but keep re-associating).
37204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
37304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		int fuzz = os_random() % 20;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (inactive_sec == -1) {
3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"Check inactivity: Could not "
378c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				"get station info from kernel driver for "
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MACSTR, MAC2STR(sta->addr));
380c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
381c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * The driver may not support this functionality.
382c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * Anyway, try again after the next inactivity timeout,
383c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * but do not disconnect the station now.
384c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
38504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			next_time = hapd->conf->ap_max_inactivity + fuzz;
3862f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		} else if (inactive_sec == -ENOENT) {
3872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3882f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				"Station " MACSTR " has lost its driver entry",
3892f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				MAC2STR(sta->addr));
3902f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
3917f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt			/* Avoid sending client probe on removed client */
3927f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt			sta->timeout_next = STA_DISASSOC;
3937f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt			goto skip_poll;
3942f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		} else if (inactive_sec < hapd->conf->ap_max_inactivity) {
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* station activity detected; reset timeout state */
3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"Station " MACSTR " has been active %is ago",
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(sta->addr), inactive_sec);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->timeout_next = STA_NULLFUNC;
40004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			next_time = hapd->conf->ap_max_inactivity + fuzz -
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				inactive_sec;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"Station " MACSTR " has been "
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"inactive too long: %d sec, max allowed: %d",
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(sta->addr), inactive_sec,
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hapd->conf->ap_max_inactivity);
4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (hapd->conf->skip_inactivity_poll)
4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				sta->timeout_next = STA_DISASSOC;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((sta->flags & WLAN_STA_ASSOC) &&
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sta->timeout_next == STA_DISASSOC &&
4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !(sta->flags & WLAN_STA_PENDING_POLL) &&
4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    !hapd->conf->skip_inactivity_poll) {
4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			" has ACKed data poll", MAC2STR(sta->addr));
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* data nullfunc frame poll did not produce TX errors; assume
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * station ACKed it */
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->timeout_next = STA_NULLFUNC;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next_time = hapd->conf->ap_max_inactivity;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4267f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtskip_poll:
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (next_time) {
42804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "for " MACSTR " (%lu seconds)",
43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   __func__, MAC2STR(sta->addr), next_time);
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sta);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->timeout_next == STA_NULLFUNC &&
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sta->flags & WLAN_STA_ASSOC)) {
4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "  Polling STA");
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->flags |= WLAN_STA_PENDING_POLL;
4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr,
4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					sta->flags & WLAN_STA_WMM);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (sta->timeout_next != STA_REMOVE) {
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int deauth = sta->timeout_next == STA_DEAUTH;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"Timeout, sending %s info to STA " MACSTR,
4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			deauth ? "deauthentication" : "disassociation",
4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			MAC2STR(sta->addr));
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (deauth) {
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_drv_sta_deauth(
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hapd, sta->addr,
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				WLAN_REASON_PREV_AUTH_NOT_VALID);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
455b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			reason = (sta->timeout_next == STA_DISASSOC) ?
456b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY :
457b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				WLAN_REASON_PREV_AUTH_NOT_VALID;
458b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
459b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sta->timeout_next) {
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case STA_NULLFUNC:
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->timeout_next = STA_DISASSOC;
46604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
46704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)",
46804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   __func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY);
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       hapd, sta);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case STA_DISASSOC:
473b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	case STA_DISASSOC_FROM_CLI:
4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ap_sta_set_authorized(hapd, sta, 0);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->flags &= ~WLAN_STA_ASSOC;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sta->acct_terminate_cause)
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->acct_terminate_cause =
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		accounting_sta_stop(hapd, sta);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_free_station(sta);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_INFO, "disassociated due to "
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "inactivity");
485b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		reason = (sta->timeout_next == STA_DISASSOC) ?
486b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY :
487b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			WLAN_REASON_PREV_AUTH_NOT_VALID;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->timeout_next = STA_DEAUTH;
48904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
49004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)",
49104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY);
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       hapd, sta);
494b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		mlme_disassociate_indication(hapd, sta, reason);
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case STA_DEAUTH:
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case STA_REMOVE:
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       "inactivity (timer DEAUTH/REMOVE)");
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sta->acct_terminate_cause)
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->acct_terminate_cause =
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		mlme_deauthenticate_indication(
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hapd, sta,
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WLAN_REASON_PREV_AUTH_NOT_VALID);
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ap_free_sta(hapd, sta);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta = timeout_ctx;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!(sta->flags & WLAN_STA_AUTH)) {
51904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (sta->flags & WLAN_STA_GAS) {
52004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   "entry " MACSTR, MAC2STR(sta->addr));
52204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ap_free_sta(hapd, sta);
52304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
52504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
527818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	hostapd_drv_sta_deauth(hapd, sta->addr,
528818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			       WLAN_REASON_PREV_AUTH_NOT_VALID);
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mlme_deauthenticate_indication(hapd, sta,
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       WLAN_REASON_PREV_AUTH_NOT_VALID);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "session timeout");
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->acct_terminate_cause =
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_free_sta(hapd, sta);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5405460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtvoid ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta,
5415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			      u32 session_timeout)
5425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{
5435460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt	if (eloop_replenish_timeout(session_timeout, 0,
544fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				    ap_handle_session_timer, hapd, sta) == 1) {
5455460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
5465460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			       HOSTAPD_LEVEL_DEBUG, "setting session timeout "
5475460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			       "to %d seconds", session_timeout);
5485460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt	}
5495460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt}
5505460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
5515460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    u32 session_timeout)
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d "
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "seconds", session_timeout);
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(session_timeout, 0, ap_handle_session_timer,
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       hapd, sta);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta)
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
570f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx)
571f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{
572f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_WNM
573f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
574f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	struct sta_info *sta = timeout_ctx;
575f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
576f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WNM: Session warning time reached for " MACSTR,
577f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		   MAC2STR(sta->addr));
578f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sta->hs20_session_info_url == NULL)
579f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return;
580f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
581f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	wnm_send_ess_disassoc_imminent(hapd, sta, sta->hs20_session_info_url,
582f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				       sta->hs20_disassoc_timer);
583f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_WNM */
584f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt}
585f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
586f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
587f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtvoid ap_sta_session_warning_timeout(struct hostapd_data *hapd,
588f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				    struct sta_info *sta, int warning_time)
589f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{
590f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
591f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	eloop_register_timeout(warning_time, 0, ap_handle_session_warning_timer,
592f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			       hapd, sta);
593f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt}
594f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
595f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta = ap_get_sta(hapd, addr);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta)
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sta;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "  New STA");
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->num_sta >= hapd->conf->max_num_sta) {
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* FIX: might try to remove some old STAs first? */
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   hapd->num_sta, hapd->conf->max_num_sta);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta = os_zalloc(sizeof(struct sta_info));
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta == NULL) {
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "malloc failed");
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->acct_interim_interval = hapd->conf->acct_interim_interval;
618a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	accounting_sta_get_id(hapd, sta);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
62001904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
62101904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
62201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			   "for " MACSTR " (%d seconds - ap_max_inactivity)",
62301904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			   __func__, MAC2STR(addr),
62401904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			   hapd->conf->ap_max_inactivity);
62501904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
62601904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt				       ap_handle_timer, hapd, sta);
62701904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	}
62801904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* initialize STA info data */
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sta->addr, addr, ETH_ALEN);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->next = hapd->sta_list;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->sta_list = sta;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->num_sta++;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sta_hash_add(hapd, sta);
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sta_remove_in_other_bss(hapd, sta);
6366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
6376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	dl_list_init(&sta->ip6addr);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sta;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (sta->ipaddr)
6486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
6496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ap_sta_ip6addr_del(hapd, sta);
6506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(sta->addr));
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_drv_sta_remove(hapd, sta->addr) &&
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sta->flags & WLAN_STA_ASSOC) {
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " from kernel driver.", MAC2STR(sta->addr));
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct sta_info *sta)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_iface *iface = hapd->iface;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < iface->num_bss; i++) {
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct hostapd_data *bss = iface->bss[i];
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct sta_info *sta2;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* bss should always be set during operation, but it may be
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * NULL during reconfiguration. Assume the STA is not
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * associated to another BSS in that case to avoid NULL pointer
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * dereferences. */
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss == hapd || bss == NULL)
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta2 = ap_get_sta(bss, sta->addr);
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sta2)
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ap_sta_disconnect(bss, sta2, sta2->addr,
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  WLAN_REASON_PREV_AUTH_NOT_VALID);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
6891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
6911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct sta_info *sta = timeout_ctx;
6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ap_sta_remove(hapd, sta);
6941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
6951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 u16 reason)
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   hapd->conf->iface, MAC2STR(sta->addr));
7036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
704700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
7051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ap_sta_set_authorized(hapd, sta, 0);
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->timeout_next = STA_DEAUTH;
70704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
70804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "for " MACSTR " (%d seconds - "
70904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "AP_MAX_INACTIVITY_AFTER_DISASSOC)",
71004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   __func__, MAC2STR(sta->addr),
71104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   AP_MAX_INACTIVITY_AFTER_DISASSOC);
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       ap_handle_timer, hapd, sta);
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	accounting_sta_stop(hapd, sta);
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_free_station(sta);
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->disassoc_reason = reason;
7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
7201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
7211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(hapd->iface->drv_flags &
7221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
7231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       ap_sta_disassoc_cb_timeout, hapd, sta);
7241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
7251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
7281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
7301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct sta_info *sta = timeout_ctx;
7311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ap_sta_remove(hapd, sta);
7331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   u16 reason)
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   hapd->conf->iface, MAC2STR(sta->addr));
7426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
7436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ap_sta_set_authorized(hapd, sta, 0);
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->timeout_next = STA_REMOVE;
74604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
74704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "for " MACSTR " (%d seconds - "
74804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "AP_MAX_INACTIVITY_AFTER_DEAUTH)",
74904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   __func__, MAC2STR(sta->addr),
75004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   AP_MAX_INACTIVITY_AFTER_DEAUTH);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       ap_handle_timer, hapd, sta);
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	accounting_sta_stop(hapd, sta);
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_free_station(sta);
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->deauth_reason = reason;
7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(hapd->iface->drv_flags &
7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
7621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       ap_sta_deauth_cb_timeout, hapd, sta);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
76604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS
76704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint ap_sta_wps_cancel(struct hostapd_data *hapd,
76804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		      struct sta_info *sta, void *ctx)
76904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
77004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sta && (sta->flags & WLAN_STA_WPS)) {
77104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		ap_sta_deauthenticate(hapd, sta,
77204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      WLAN_REASON_PREV_AUTH_NOT_VALID);
77304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR,
77404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   __func__, MAC2STR(sta->addr));
77504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 1;
77604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
77704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
77804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
77904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
78004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS */
78104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
78204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
7838347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidtint ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *iface;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_vlan *vlan = NULL;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
7898347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	int old_vlanid = sta->vlan_id_bound;
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iface = hapd->conf->iface;
7929d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	if (hapd->conf->ssid.vlan[0])
7939d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		iface = hapd->conf->ssid.vlan;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7959d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt	if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->vlan_id = 0;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sta->vlan_id > 0) {
798d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt		struct hostapd_vlan *wildcard_vlan = NULL;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		vlan = hapd->conf->vlan;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (vlan) {
801d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt			if (vlan->vlan_id == sta->vlan_id)
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
803d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt			if (vlan->vlan_id == VLAN_ID_WILDCARD)
804d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt				wildcard_vlan = vlan;
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			vlan = vlan->next;
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
807d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt		if (!vlan)
808d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt			vlan = wildcard_vlan;
809d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt		if (vlan)
810d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt			iface = vlan->ifname;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8138347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	/*
8148347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	 * Do not increment ref counters if the VLAN ID remains same, but do
8158347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	 * not skip hostapd_drv_set_sta_vlan() as hostapd_drv_sta_remove() might
8168347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	 * have been called before.
8178347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	 */
8188347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	if (sta->vlan_id == old_vlanid)
8198347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		goto skip_counting;
8208347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->vlan_id > 0 && vlan == NULL) {
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "binding station to (vlan_id=%d)",
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       sta->vlan_id);
826216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		ret = -1;
827216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		goto done;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (vlan == NULL) {
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, sta->addr,
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_MODULE_IEEE80211,
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_DEBUG, "could not add "
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "dynamic VLAN interface for vlan_id=%d",
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sta->vlan_id);
836216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			ret = -1;
837216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt			goto done;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iface = vlan->ifname;
8419d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		if (vlan_setup_encryption_dyn(hapd, iface) != 0) {
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, sta->addr,
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_MODULE_IEEE80211,
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_DEBUG, "could not "
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "configure encryption for dynamic VLAN "
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "interface for vlan_id=%d",
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sta->vlan_id);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "interface '%s'", iface);
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (vlan && vlan->vlan_id == sta->vlan_id) {
8548347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt		if (vlan->dynamic_vlan > 0) {
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			vlan->dynamic_vlan++;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, sta->addr,
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_MODULE_IEEE80211,
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_DEBUG, "updated existing "
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "dynamic VLAN interface '%s'", iface);
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Update encryption configuration for statically generated
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * VLAN interface. This is only used for static WEP
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configuration for the case where hostapd did not yet know
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * which keys are to be used when the interface was added.
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
8689d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt		if (vlan_setup_encryption_dyn(hapd, iface) != 0) {
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, sta->addr,
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_MODULE_IEEE80211,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_DEBUG, "could not "
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "configure encryption for VLAN "
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "interface for vlan_id=%d",
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sta->vlan_id);
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8788347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	/* ref counters have been increased, so mark the station */
8798347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	sta->vlan_id_bound = sta->vlan_id;
8808347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt
8818347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidtskip_counting:
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_DEBUG, "binding station to interface "
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "'%s'", iface);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0) {
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "entry to vlan_id=%d", sta->vlan_id);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
895216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
896216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt	/* During 1x reauth, if the vlan id changes, then remove the old id. */
8978347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt	if (old_vlanid > 0 && old_vlanid != sta->vlan_id)
898216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt		vlan_remove_dynamic(hapd, old_vlanid);
8998347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidtdone:
900216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_VLAN */
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 tu;
91304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	struct os_reltime now, passed;
91404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	os_get_reltime(&now);
91504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	os_reltime_sub(&now, &sta->sa_query_start, &passed);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tu = (passed.sec * 1000000 + passed.usec) / 1024;
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->conf->assoc_sa_query_max_timeout < tu) {
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_logger(hapd, sta->addr,
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_MODULE_IEEE80211,
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       HOSTAPD_LEVEL_DEBUG,
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "association SA Query timed out");
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->sa_query_timed_out = 1;
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sta->sa_query_trans_id);
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->sa_query_trans_id = NULL;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->sa_query_count = 0;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta = timeout_ctx;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int timeout, sec, usec;
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *trans_id, *nbuf;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->sa_query_count > 0 &&
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ap_check_sa_query_timeout(hapd, sta))
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
94561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	nbuf = os_realloc_array(sta->sa_query_trans_id,
94661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sta->sa_query_count + 1,
94761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				WLAN_SA_QUERY_TR_ID_LEN);
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nbuf == NULL)
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta->sa_query_count == 0) {
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Starting a new SA Query procedure */
95204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt		os_get_reltime(&sta->sa_query_start);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->sa_query_trans_id = nbuf;
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->sa_query_count++;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
9596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		/*
9606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * We don't really care which ID is used here, so simply
9616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * hardcode this if the mostly theoretical os_get_random()
9626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 * failure happens.
9636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		 */
9646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		trans_id[0] = 0x12;
9656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		trans_id[1] = 0x34;
9666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout = hapd->conf->assoc_sa_query_retry_timeout;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sec = ((timeout / 1000) * 1024) / 1000;
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	usec = (timeout % 1000) * 1024;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_DEBUG,
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "association SA Query attempt %d", sta->sa_query_count);
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sa_query_timer(hapd, sta);
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sta->sa_query_trans_id);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->sa_query_trans_id = NULL;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->sa_query_count = 0;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   int authorized)
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const u8 *dev_addr = NULL;
1002b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	char buf[100];
100304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_P2P
100404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u8 addr[ETH_ALEN];
1005cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	u8 ip_addr_buf[4];
100604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_P2P */
100704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (authorized)
10126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		sta->flags |= WLAN_STA_AUTHORIZED;
10136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	else
10146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		sta->flags &= ~WLAN_STA_AUTHORIZED;
10156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_P2P
101704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (hapd->p2p_group == NULL) {
101804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (sta->p2p_ie != NULL &&
101904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0)
102004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			dev_addr = addr;
102104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	} else
102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
10231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1024b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (dev_addr)
1025b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR,
1026b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			    MAC2STR(sta->addr), MAC2STR(dev_addr));
1027b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	else
1028661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#endif /* CONFIG_P2P */
1029b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
1030b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
10316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (hapd->sta_authorized_cb)
10326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
10336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					sta->addr, authorized, dev_addr);
10346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
10351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (authorized) {
1036cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		char ip_addr[100];
1037cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		ip_addr[0] = '\0';
1038cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
1039cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
1040cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			os_snprintf(ip_addr, sizeof(ip_addr),
1041cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    " ip_addr=%u.%u.%u.%u",
1042cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    ip_addr_buf[0], ip_addr_buf[1],
1043cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				    ip_addr_buf[2], ip_addr_buf[3]);
1044cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
1045cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
1046cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
1047cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s",
1048cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			buf, ip_addr);
1049b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
10501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (hapd->msg_ctx_parent &&
1051b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		    hapd->msg_ctx_parent != hapd->msg_ctx)
1052b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
1053cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					  AP_STA_CONNECTED "%s%s",
1054cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					  buf, ip_addr);
10551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
1056b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
1057b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt
10581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (hapd->msg_ctx_parent &&
1059b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		    hapd->msg_ctx_parent != hapd->msg_ctx)
1060b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
1061b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt					  AP_STA_DISCONNECTED "%s", buf);
10621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const u8 *addr, u16 reason)
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta == NULL && addr)
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta = ap_get_sta(hapd, addr);
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_drv_sta_deauth(hapd, addr, reason);
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta == NULL)
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_sta_set_authorized(hapd, sta, 0);
1079c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
1080c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
108204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
108304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "for " MACSTR " (%d seconds - "
108404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   "AP_MAX_INACTIVITY_AFTER_DEAUTH)",
108504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   __func__, MAC2STR(sta->addr),
108604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   AP_MAX_INACTIVITY_AFTER_DEAUTH);
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
10881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
10891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       ap_handle_timer, hapd, sta);
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->timeout_next = STA_REMOVE;
10911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->deauth_reason = reason;
10931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
10941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
10951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(hapd->iface->drv_flags &
10961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
10971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       ap_sta_deauth_cb_timeout, hapd, sta);
10981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
10991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta)
11021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) {
11041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame");
11051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
11061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB;
11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
11091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ap_sta_deauth_cb_timeout(hapd, sta);
11101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta)
11141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) {
11161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame");
11171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
11181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB;
11201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
11211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ap_sta_disassoc_cb_timeout(hapd, sta);
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1123fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1124fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1125fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
1126fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{
1127fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	int res;
1128fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1129fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	buf[0] = '\0';
11302f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1131fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
1132fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
1133fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
1134fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
1135fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			   ""),
1136fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_SHORT_PREAMBLE ?
1137fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			   "[SHORT_PREAMBLE]" : ""),
1138fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
1139fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_WMM ? "[WMM]" : ""),
1140fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_MFP ? "[MFP]" : ""),
1141fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_WPS ? "[WPS]" : ""),
1142fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
1143fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_WDS ? "[WDS]" : ""),
1144fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
1145fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
1146fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_GAS ? "[GAS]" : ""),
1147fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_VHT ? "[VHT]" : ""),
11482f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			  (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
1149fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			  (flags & WLAN_STA_WNM_SLEEP_MODE ?
1150fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			   "[WNM_SLEEP_MODE]" : ""));
11516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(buflen, res))
11526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		res = -1;
1153fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1154fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	return res;
1155fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt}
1156