sta_info.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * hostapd / Station table
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This software may be distributed under the terms of the BSD license.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See README for more details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "utils/includes.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "utils/common.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "utils/eloop.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "common/ieee802_11_defs.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "common/wpa_ctrl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "radius/radius.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "radius/radius_client.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "drivers/driver.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "p2p/p2p.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "hostapd.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "accounting.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ieee802_1x.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ieee802_11.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wpa_auth.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "preauth_auth.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ap_config.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "beacon.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ap_mlme.h"
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "vlan_init.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "p2p_hostapd.h"
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ap_drv_ops.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sta_info.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       struct sta_info *sta);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211W
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif /* CONFIG_IEEE80211W */
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int ap_for_each_sta(struct hostapd_data *hapd,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			      void *ctx),
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    void *ctx)
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct sta_info *sta;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (sta = hapd->sta_list; sta; sta = sta->next) {
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)		if (cb(hapd, sta, ctx))
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return 1;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct sta_info *s;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)	s = hapd->sta_hash[STA_HASH(sta)];
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)		s = s->hnext;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return s;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct sta_info *tmp;
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (hapd->sta_list == sta) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		hapd->sta_list = sta->next;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tmp = hapd->sta_list;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (tmp != NULL && tmp->next != sta)
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		tmp = tmp->next;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tmp == NULL) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   "list.", MAC2STR(sta->addr));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		tmp->next = sta->next;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hapd->sta_hash[STA_HASH(sta->addr)] = sta;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct sta_info *s;
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	s = hapd->sta_hash[STA_HASH(sta->addr)];
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (s == NULL) return;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (os_memcmp(s->addr, sta->addr, 6) == 0) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return;
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	while (s->hnext != NULL &&
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	       os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		s = s->hnext;
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (s->hnext != NULL)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		s->hnext = s->hnext->hnext;
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	else
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			   " from hash table", MAC2STR(sta->addr));
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles){
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)	int set_beacon = 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	accounting_sta_stop(hapd, sta);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/* just in case */
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	ap_sta_set_authorized(hapd, sta, 0);
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta->flags & WLAN_STA_WDS)
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	if (!(sta->flags & WLAN_STA_PREAUTH))
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		hostapd_drv_sta_remove(hapd, sta->addr);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	ap_sta_hash_del(hapd, sta);
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	ap_sta_list_del(hapd, sta);
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta->aid > 0)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->sta_aid[(sta->aid - 1) / 32] &=
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			~BIT((sta->aid - 1) % 32);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hapd->num_sta--;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta->nonerp_set) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->nonerp_set = 0;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->iface->num_sta_non_erp--;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (hapd->iface->num_sta_non_erp == 0)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			set_beacon++;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (sta->no_short_slot_time_set) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		sta->no_short_slot_time_set = 0;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		hapd->iface->num_sta_no_short_slot_time--;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    && hapd->iface->num_sta_no_short_slot_time == 0)
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			set_beacon++;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (sta->no_short_preamble_set) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		sta->no_short_preamble_set = 0;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		hapd->iface->num_sta_no_short_preamble--;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    && hapd->iface->num_sta_no_short_preamble == 0)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			set_beacon++;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta->no_ht_gf_set) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->no_ht_gf_set = 0;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->iface->num_sta_ht_no_gf--;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta->no_ht_set) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->no_ht_set = 0;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->iface->num_sta_no_ht--;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta->ht_20mhz_set) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->ht_20mhz_set = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->iface->num_sta_ht_20mhz--;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_P2P
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta->no_p2p_set) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->no_p2p_set = 0;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hapd->num_sta_no_p2p--;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (hapd->num_sta_no_p2p == 0)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			hostapd_p2p_non_p2p_sta_disconnected(hapd);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_P2P */
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (hostapd_ht_operation_update(hapd->iface) > 0)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		set_beacon++;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (set_beacon)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ieee802_11_set_beacons(hapd->iface);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ieee802_1x_free_station(sta);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_auth_sta_deinit(sta->wpa_sm);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rsn_preauth_free_station(hapd, sta);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CONFIG_NO_RADIUS
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	radius_client_flush_auth(hapd->radius, sta->addr);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_NO_RADIUS */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(sta->last_assoc_req);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(sta->challenge);
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211W
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(sta->sa_query_trans_id);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211W */
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef CONFIG_P2P
218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)	p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif /* CONFIG_P2P */
220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_free(sta->wps_ie);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_free(sta->p2p_ie);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(sta->ht_capabilities);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(sta->psk);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(sta);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void hostapd_free_stas(struct hostapd_data *hapd)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct sta_info *sta, *prev;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	sta = hapd->sta_list;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (sta) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		prev = sta;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (sta->flags & WLAN_STA_AUTH) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			mlme_deauthenticate_indication(
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)				hapd, sta, WLAN_REASON_UNSPECIFIED);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta = sta->next;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   MAC2STR(prev->addr));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ap_free_sta(hapd, prev);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/**
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * ap_handle_timer - Per STA timer handler
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @eloop_ctx: struct hostapd_data *
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @timeout_ctx: struct sta_info *
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This function is called to check station activity and to remove inactive
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * stations.
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct hostapd_data *hapd = eloop_ctx;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct sta_info *sta = timeout_ctx;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned long next_time = 0;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta->timeout_next == STA_REMOVE) {
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			       "local deauth request");
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		ap_free_sta(hapd, sta);
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	if ((sta->flags & WLAN_STA_ASSOC) &&
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	    (sta->timeout_next == STA_NULLFUNC ||
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	     sta->timeout_next == STA_DISASSOC)) {
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		int inactive_sec;
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr);
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		if (inactive_sec == -1) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				"Check inactivity: Could not "
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				"get station info from kernel driver for "
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MACSTR, MAC2STR(sta->addr));
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			/*
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			 * The driver may not support this functionality.
285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			 * Anyway, try again after the next inactivity timeout,
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			 * but do not disconnect the station now.
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			 */
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			next_time = hapd->conf->ap_max_inactivity;
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		} else if (inactive_sec < hapd->conf->ap_max_inactivity &&
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			   sta->flags & WLAN_STA_ASSOC) {
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			/* station activity detected; reset timeout state */
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				"Station " MACSTR " has been active %is ago",
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MAC2STR(sta->addr), inactive_sec);
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			sta->timeout_next = STA_NULLFUNC;
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			next_time = hapd->conf->ap_max_inactivity -
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				inactive_sec;
2988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		} else {
2998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)			wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)				"Station " MACSTR " has been "
3018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)				"inactive too long: %d sec, max allowed: %d",
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MAC2STR(sta->addr), inactive_sec,
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				hapd->conf->ap_max_inactivity);
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			if (hapd->conf->skip_inactivity_poll)
306c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				sta->timeout_next = STA_DISASSOC;
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		}
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if ((sta->flags & WLAN_STA_ASSOC) &&
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    sta->timeout_next == STA_DISASSOC &&
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    !(sta->flags & WLAN_STA_PENDING_POLL) &&
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    !hapd->conf->skip_inactivity_poll) {
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			" has ACKed data poll", MAC2STR(sta->addr));
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		/* data nullfunc frame poll did not produce TX errors; assume
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		 * station ACKed it */
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		sta->timeout_next = STA_NULLFUNC;
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		next_time = hapd->conf->ap_max_inactivity;
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (next_time) {
3238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       sta);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
327c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
328c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if (sta->timeout_next == STA_NULLFUNC &&
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    (sta->flags & WLAN_STA_ASSOC)) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "  Polling STA");
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->flags |= WLAN_STA_PENDING_POLL;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr,
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch					sta->flags & WLAN_STA_WMM);
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	} else if (sta->timeout_next != STA_REMOVE) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		int deauth = sta->timeout_next == STA_DEAUTH;
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"Timeout, sending %s info to STA " MACSTR,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			deauth ? "deauthentication" : "disassociation",
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			MAC2STR(sta->addr));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (deauth) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			hostapd_drv_sta_deauth(
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hapd, sta->addr,
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				WLAN_REASON_PREV_AUTH_NOT_VALID);
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		} else {
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			hostapd_drv_sta_disassoc(
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				hapd, sta->addr,
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	switch (sta->timeout_next) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case STA_NULLFUNC:
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->timeout_next = STA_DISASSOC;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       hapd, sta);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case STA_DISASSOC:
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ap_sta_set_authorized(hapd, sta, 0);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sta->flags &= ~WLAN_STA_ASSOC;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch		if (!sta->acct_terminate_cause)
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch			sta->acct_terminate_cause =
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch		accounting_sta_stop(hapd, sta);
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		ieee802_1x_free_station(sta);
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch			       HOSTAPD_LEVEL_INFO, "disassociated due to "
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch			       "inactivity");
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch		sta->timeout_next = STA_DEAUTH;
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch		eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch				       hapd, sta);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mlme_disassociate_indication(
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		break;
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	case STA_DEAUTH:
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	case STA_REMOVE:
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			       "inactivity (timer DEAUTH/REMOVE)");
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (!sta->acct_terminate_cause)
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			sta->acct_terminate_cause =
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		mlme_deauthenticate_indication(
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			hapd, sta,
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			WLAN_REASON_PREV_AUTH_NOT_VALID);
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		ap_free_sta(hapd, sta);
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		break;
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct hostapd_data *hapd = eloop_ctx;
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct sta_info *sta = timeout_ctx;
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	u8 addr[ETH_ALEN];
399a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
400a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch	if (!(sta->flags & WLAN_STA_AUTH))
401a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch		return;
402a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	mlme_deauthenticate_indication(hapd, sta,
404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)				       WLAN_REASON_PREV_AUTH_NOT_VALID);
405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)		       HOSTAPD_LEVEL_INFO, "deauthenticated due to "
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		       "session timeout");
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->acct_terminate_cause =
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	os_memcpy(addr, sta->addr, ETH_ALEN);
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	ap_free_sta(hapd, sta);
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			    u32 session_timeout)
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
419c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		       HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d "
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		       "seconds", session_timeout);
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	eloop_register_timeout(session_timeout, 0, ap_handle_session_timer,
424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			       hapd, sta);
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
428c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta)
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
431c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles){
436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)	struct sta_info *sta;
437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sta = ap_get_sta(hapd, addr);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sta)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return sta;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "  New STA");
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (hapd->num_sta >= hapd->conf->max_num_sta) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* FIX: might try to remove some old STAs first? */
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   hapd->num_sta, hapd->conf->max_num_sta);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	sta = os_zalloc(sizeof(struct sta_info));
451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if (sta == NULL) {
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_ERROR, "malloc failed");
453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return NULL;
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	sta->acct_interim_interval = hapd->conf->acct_interim_interval;
456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	/* initialize STA info data */
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			       ap_handle_timer, hapd, sta);
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	os_memcpy(sta->addr, addr, ETH_ALEN);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->next = hapd->sta_list;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hapd->sta_list = sta;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hapd->num_sta++;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ap_sta_hash_add(hapd, sta);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->ssid = &hapd->conf->ssid;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ap_sta_remove_in_other_bss(hapd, sta);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return sta;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
471c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
4751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   MAC2STR(sta->addr));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (hostapd_drv_sta_remove(hapd, sta->addr) &&
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sta->flags & WLAN_STA_ASSOC) {
4801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			   " from kernel driver.", MAC2STR(sta->addr));
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return -1;
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return 0;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				       struct sta_info *sta)
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct hostapd_iface *iface = hapd->iface;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t i;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < iface->num_bss; i++) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		struct hostapd_data *bss = iface->bss[i];
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		struct sta_info *sta2;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* bss should always be set during operation, but it may be
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * NULL during reconfiguration. Assume the STA is not
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * associated to another BSS in that case to avoid NULL pointer
5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		 * dereferences. */
5011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)		if (bss == hapd || bss == NULL)
5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			continue;
5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		sta2 = ap_get_sta(bss, sta->addr);
5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		if (!sta2)
5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			continue;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		ap_sta_disconnect(bss, sta2, sta2->addr,
508c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				  WLAN_REASON_PREV_AUTH_NOT_VALID);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct hostapd_data *hapd = eloop_ctx;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct sta_info *sta = timeout_ctx;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ap_sta_remove(hapd, sta);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 u16 reason)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   hapd->conf->iface, MAC2STR(sta->addr));
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->flags &= ~WLAN_STA_ASSOC;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ap_sta_set_authorized(hapd, sta, 0);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->timeout_next = STA_DEAUTH;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       ap_handle_timer, hapd, sta);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	accounting_sta_stop(hapd, sta);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ieee802_1x_free_station(sta);
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->disassoc_reason = reason;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	eloop_register_timeout(hapd->iface->drv_flags &
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       ap_sta_disassoc_cb_timeout, hapd, sta);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	struct hostapd_data *hapd = eloop_ctx;
549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	struct sta_info *sta = timeout_ctx;
550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	ap_sta_remove(hapd, sta);
552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
5544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
556c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
5574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			   u16 reason)
558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		   hapd->conf->iface, MAC2STR(sta->addr));
5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	ap_sta_set_authorized(hapd, sta, 0);
5634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	sta->timeout_next = STA_REMOVE;
564a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
566c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			       ap_handle_timer, hapd, sta);
567c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	accounting_sta_stop(hapd, sta);
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ieee802_1x_free_station(sta);
569a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->deauth_reason = reason;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	eloop_register_timeout(hapd->iface->drv_flags &
574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       ap_sta_deauth_cb_timeout, hapd, sta);
576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		     int old_vlanid)
5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles){
5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#ifndef CONFIG_NO_VLAN
5838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	const char *iface;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct hostapd_vlan *vlan = NULL;
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int ret;
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/*
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * Do not proceed furthur if the vlan id remains same. We do not want
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * duplicate dynamic vlan entries.
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 */
5918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	if (sta->vlan_id == old_vlanid)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return 0;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * During 1x reauth, if the vlan id changes, then remove the old id and
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * proceed furthur to add the new one.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (old_vlanid > 0)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		vlan_remove_dynamic(hapd, old_vlanid);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	iface = hapd->conf->iface;
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (sta->ssid->vlan[0])
6034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		iface = sta->ssid->vlan;
6044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
6064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		sta->vlan_id = 0;
607c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	else if (sta->vlan_id > 0) {
608effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		vlan = hapd->conf->vlan;
609c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		while (vlan) {
610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			if (vlan->vlan_id == sta->vlan_id ||
6114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			    vlan->vlan_id == VLAN_ID_WILDCARD) {
612effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				iface = vlan->ifname;
613effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				break;
6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			}
6154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			vlan = vlan->next;
6164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		}
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
618c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta->vlan_id > 0 && vlan == NULL) {
6204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			       HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			       "binding station to (vlan_id=%d)",
6234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			       sta->vlan_id);
6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return -1;
625c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	} else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		if (vlan == NULL) {
6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			hostapd_logger(hapd, sta->addr,
6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       HOSTAPD_MODULE_IEEE80211,
6304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       HOSTAPD_LEVEL_DEBUG, "could not add "
6314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       "dynamic VLAN interface for vlan_id=%d",
632effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				       sta->vlan_id);
633effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			return -1;
6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		}
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		iface = vlan->ifname;
6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
6384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			hostapd_logger(hapd, sta->addr,
6394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       HOSTAPD_MODULE_IEEE80211,
6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       HOSTAPD_LEVEL_DEBUG, "could not "
6414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       "configure encryption for dynamic VLAN "
6424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       "interface for vlan_id=%d",
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       sta->vlan_id);
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			       HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			       "interface '%s'", iface);
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	} else if (vlan && vlan->vlan_id == sta->vlan_id) {
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (sta->vlan_id > 0) {
6514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			vlan->dynamic_vlan++;
6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			hostapd_logger(hapd, sta->addr,
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				       HOSTAPD_MODULE_IEEE80211,
6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				       HOSTAPD_LEVEL_DEBUG, "updated existing "
6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				       "dynamic VLAN interface '%s'", iface);
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		/*
6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		 * Update encryption configuration for statically generated
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		 * VLAN interface. This is only used for static WEP
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		 * configuration for the case where hostapd did not yet know
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		 * which keys are to be used when the interface was added.
6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		 */
6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			hostapd_logger(hapd, sta->addr,
666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				       HOSTAPD_MODULE_IEEE80211,
667a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				       HOSTAPD_LEVEL_DEBUG, "could not "
668c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				       "configure encryption for VLAN "
669a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				       "interface for vlan_id=%d",
670a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				       sta->vlan_id);
6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		}
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		       HOSTAPD_LEVEL_DEBUG, "binding station to interface "
6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		       "'%s'", iface);
677a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
678a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
681a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
682a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (ret < 0) {
683a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
684a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			       HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
685a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			       "entry to vlan_id=%d", sta->vlan_id);
6864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
6874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	return ret;
6884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#else /* CONFIG_NO_VLAN */
6894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	return 0;
6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif /* CONFIG_NO_VLAN */
6914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_IEEE80211W
695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){
698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	u32 tu;
699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	struct os_time now, passed;
700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	os_get_time(&now);
701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	os_time_sub(&now, &sta->sa_query_start, &passed);
702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	tu = (passed.sec * 1000000 + passed.usec) / 1024;
703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (hapd->conf->assoc_sa_query_max_timeout < tu) {
704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		hostapd_logger(hapd, sta->addr,
705a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch			       HOSTAPD_MODULE_IEEE80211,
706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			       HOSTAPD_LEVEL_DEBUG,
707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			       "association SA Query timed out");
708a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		sta->sa_query_timed_out = 1;
709a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		os_free(sta->sa_query_trans_id);
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		sta->sa_query_trans_id = NULL;
711a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		sta->sa_query_count = 0;
712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		return 1;
714a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	}
715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	return 0;
7174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
719f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
721a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){
722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	struct hostapd_data *hapd = eloop_ctx;
723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	struct sta_info *sta = timeout_ctx;
724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	unsigned int timeout, sec, usec;
725a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	u8 *trans_id, *nbuf;
7264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta->sa_query_count > 0 &&
7284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    ap_check_sa_query_timeout(hapd, sta))
7294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
7304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	nbuf = os_realloc(sta->sa_query_trans_id,
7324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			  (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
7334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (nbuf == NULL)
7344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
7354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta->sa_query_count == 0) {
7364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		/* Starting a new SA Query procedure */
7374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		os_get_time(&sta->sa_query_start);
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
7394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
740a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	sta->sa_query_trans_id = nbuf;
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	sta->sa_query_count++;
742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	timeout = hapd->conf->assoc_sa_query_retry_timeout;
7464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	sec = ((timeout / 1000) * 1024) / 1000;
7474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	usec = (timeout % 1000) * 1024;
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
7494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
7514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		       HOSTAPD_LEVEL_DEBUG,
7524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		       "association SA Query attempt %d", sta->sa_query_count);
7534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef NEED_AP_MLME
7554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif /* NEED_AP_MLME */
7574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
7584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
7610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles){
7620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)	ap_sa_query_timer(hapd, sta);
7634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
764c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
765c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
766effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
768c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
7694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	os_free(sta->sa_query_trans_id);
770c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	sta->sa_query_trans_id = NULL;
7714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	sta->sa_query_count = 0;
772c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
774c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif /* CONFIG_IEEE80211W */
7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			   int authorized)
779c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	const u8 *dev_addr = NULL;
7814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
7824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
7834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef CONFIG_P2P
7854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
7864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif /* CONFIG_P2P */
7874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
788f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (authorized) {
789c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		if (dev_addr)
7901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)			wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
7910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)				MACSTR " p2p_dev_addr=" MACSTR,
792effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch				MAC2STR(sta->addr), MAC2STR(dev_addr));
793c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		else
794c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED
795c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				MACSTR, MAC2STR(sta->addr));
7960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)		if (hapd->msg_ctx_parent &&
797c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		    hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
798c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				AP_STA_CONNECTED MACSTR " p2p_dev_addr="
8000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)				MACSTR,
801c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				MAC2STR(sta->addr), MAC2STR(dev_addr));
8024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		else if (hapd->msg_ctx_parent &&
8034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			 hapd->msg_ctx_parent != hapd->msg_ctx)
804c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
805c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
806c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
807c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		sta->flags |= WLAN_STA_AUTHORIZED;
808c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	} else {
809c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		if (dev_addr)
8104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
8114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MACSTR " p2p_dev_addr=" MACSTR,
8124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MAC2STR(sta->addr), MAC2STR(dev_addr));
813effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		else
8144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED
8150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)				MACSTR, MAC2STR(sta->addr));
8164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		if (hapd->msg_ctx_parent &&
8174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		    hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr)
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
8194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				AP_STA_DISCONNECTED MACSTR " p2p_dev_addr="
8204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr));
8214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		else if (hapd->msg_ctx_parent &&
8224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			 hapd->msg_ctx_parent != hapd->msg_ctx)
8234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
8244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				AP_STA_DISCONNECTED MACSTR,
8254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				MAC2STR(sta->addr));
8264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		sta->flags &= ~WLAN_STA_AUTHORIZED;
8274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
8284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (hapd->sta_authorized_cb)
830a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
8314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)					sta->addr, authorized, dev_addr);
8324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
8334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
834a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
8364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		       const u8 *addr, u16 reason)
837a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
838a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta == NULL && addr)
8404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		sta = ap_get_sta(hapd, addr);
8414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
842c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if (addr)
8434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		hostapd_drv_sta_deauth(hapd, addr, reason);
844c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
8454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (sta == NULL)
8464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
847a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch	ap_sta_set_authorized(hapd, sta, 0);
8481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
8494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
8504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
8524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
853c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			       ap_handle_timer, hapd, sta);
8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sta->timeout_next = STA_REMOVE;
8554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sta->deauth_reason = reason;
8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
8584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
8594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	eloop_register_timeout(hapd->iface->drv_flags &
860c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			       WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
8614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			       ap_sta_deauth_cb_timeout, hapd, sta);
8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta)
8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) {
8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame");
8694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
8704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
871f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB;
8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
873f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	ap_sta_deauth_cb_timeout(hapd, sta);
8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
876f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta)
878c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
8794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) {
880c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame");
8814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		return;
8824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
883c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB;
8844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
8854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	ap_sta_disassoc_cb_timeout(hapd, sta);
8864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
887a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)