sta_info.c revision 214501
11556Srgrimes/* 21556Srgrimes * hostapd / Station table 31556Srgrimes * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 41556Srgrimes * 51556Srgrimes * This program is free software; you can redistribute it and/or modify 61556Srgrimes * it under the terms of the GNU General Public License version 2 as 71556Srgrimes * published by the Free Software Foundation. 81556Srgrimes * 91556Srgrimes * Alternatively, this software may be distributed under the terms of BSD 101556Srgrimes * license. 111556Srgrimes * 121556Srgrimes * See README and COPYING for more details. 131556Srgrimes */ 141556Srgrimes 151556Srgrimes#include "utils/includes.h" 161556Srgrimes 171556Srgrimes#include "utils/common.h" 181556Srgrimes#include "utils/eloop.h" 191556Srgrimes#include "common/ieee802_11_defs.h" 201556Srgrimes#include "radius/radius.h" 211556Srgrimes#include "radius/radius_client.h" 221556Srgrimes#include "drivers/driver.h" 231556Srgrimes#include "hostapd.h" 241556Srgrimes#include "accounting.h" 251556Srgrimes#include "ieee802_1x.h" 261556Srgrimes#include "ieee802_11.h" 271556Srgrimes#include "wpa_auth.h" 281556Srgrimes#include "preauth_auth.h" 291556Srgrimes#include "ap_config.h" 301556Srgrimes#include "beacon.h" 311556Srgrimes#include "ap_mlme.h" 321556Srgrimes#include "vlan_init.h" 331556Srgrimes#include "sta_info.h" 3436150Scharnier 3536150Scharnierstatic void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, 3636150Scharnier struct sta_info *sta); 371556Srgrimesstatic void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); 3899110Sobrien#ifdef CONFIG_IEEE80211W 3999110Sobrienstatic void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); 401556Srgrimes#endif /* CONFIG_IEEE80211W */ 4117987Speter 4217987Speterint ap_for_each_sta(struct hostapd_data *hapd, 4317987Speter int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, 4417987Speter void *ctx), 451556Srgrimes void *ctx) 461556Srgrimes{ 471556Srgrimes struct sta_info *sta; 481556Srgrimes 491556Srgrimes for (sta = hapd->sta_list; sta; sta = sta->next) { 501556Srgrimes if (cb(hapd, sta, ctx)) 511556Srgrimes return 1; 521556Srgrimes } 531556Srgrimes 541556Srgrimes return 0; 551556Srgrimes} 561556Srgrimes 571556Srgrimes 581556Srgrimesstruct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) 5917987Speter{ 6017987Speter struct sta_info *s; 6117987Speter 621556Srgrimes s = hapd->sta_hash[STA_HASH(sta)]; 631556Srgrimes while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) 641556Srgrimes s = s->hnext; 651556Srgrimes return s; 6659436Scracauer} 671556Srgrimes 681556Srgrimes 691556Srgrimesstatic void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) 701556Srgrimes{ 711556Srgrimes struct sta_info *tmp; 7290111Simp 7390111Simp if (hapd->sta_list == sta) { 7490111Simp hapd->sta_list = sta->next; 7590111Simp return; 761556Srgrimes } 771556Srgrimes 781556Srgrimes tmp = hapd->sta_list; 791556Srgrimes while (tmp != NULL && tmp->next != sta) 801556Srgrimes tmp = tmp->next; 811556Srgrimes if (tmp == NULL) { 821556Srgrimes wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " 8390111Simp "list.", MAC2STR(sta->addr)); 8417987Speter } else 851556Srgrimes tmp->next = sta->next; 861556Srgrimes} 871556Srgrimes 881556Srgrimes 891556Srgrimesvoid ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) 901556Srgrimes{ 911556Srgrimes sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; 9219240Ssteve hapd->sta_hash[STA_HASH(sta->addr)] = sta; 931556Srgrimes} 941556Srgrimes 951556Srgrimes 961556Srgrimesstatic void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) 971556Srgrimes{ 981556Srgrimes struct sta_info *s; 991556Srgrimes 1001556Srgrimes s = hapd->sta_hash[STA_HASH(sta->addr)]; 1011556Srgrimes if (s == NULL) return; 1021556Srgrimes if (os_memcmp(s->addr, sta->addr, 6) == 0) { 1031556Srgrimes hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; 1041556Srgrimes return; 1051556Srgrimes } 1061556Srgrimes 1071556Srgrimes while (s->hnext != NULL && 10820425Ssteve os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) 10925227Ssteve s = s->hnext; 11011111Sjoerg if (s->hnext != NULL) 11120742Ssteve s->hnext = s->hnext->hnext; 1121556Srgrimes else 11320742Ssteve wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR 1141556Srgrimes " from hash table", MAC2STR(sta->addr)); 1151556Srgrimes} 1161556Srgrimes 1171556Srgrimes 1181556Srgrimesvoid ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) 1191556Srgrimes{ 1201556Srgrimes int set_beacon = 0; 1211556Srgrimes 1221556Srgrimes accounting_sta_stop(hapd, sta); 12317987Speter 12490111Simp if (sta->flags & WLAN_STA_WDS) 12517987Speter hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0); 1261556Srgrimes 12717987Speter if (!(sta->flags & WLAN_STA_PREAUTH)) 1281556Srgrimes hapd->drv.sta_remove(hapd, sta->addr); 12917987Speter 1301556Srgrimes ap_sta_hash_del(hapd, sta); 1311556Srgrimes ap_sta_list_del(hapd, sta); 1321556Srgrimes 1331556Srgrimes if (sta->aid > 0) 1341556Srgrimes hapd->sta_aid[(sta->aid - 1) / 32] &= 1351556Srgrimes ~BIT((sta->aid - 1) % 32); 1361556Srgrimes 1371556Srgrimes hapd->num_sta--; 1381556Srgrimes if (sta->nonerp_set) { 13990111Simp sta->nonerp_set = 0; 14017987Speter hapd->iface->num_sta_non_erp--; 141146255Sgad if (hapd->iface->num_sta_non_erp == 0) 1421556Srgrimes set_beacon++; 1431556Srgrimes } 1441556Srgrimes 1451556Srgrimes if (sta->no_short_slot_time_set) { 1461556Srgrimes sta->no_short_slot_time_set = 0; 1471556Srgrimes hapd->iface->num_sta_no_short_slot_time--; 1481556Srgrimes if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G 1491556Srgrimes && hapd->iface->num_sta_no_short_slot_time == 0) 1501556Srgrimes set_beacon++; 151141962Sgad } 152141962Sgad 153141962Sgad if (sta->no_short_preamble_set) { 154141962Sgad sta->no_short_preamble_set = 0; 155141962Sgad hapd->iface->num_sta_no_short_preamble--; 156146255Sgad if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G 157146255Sgad && hapd->iface->num_sta_no_short_preamble == 0) 158146255Sgad set_beacon++; 159146255Sgad } 160146255Sgad 161146255Sgad if (sta->no_ht_gf_set) { 162146255Sgad sta->no_ht_gf_set = 0; 163146255Sgad hapd->iface->num_sta_ht_no_gf--; 164146255Sgad } 165146255Sgad 166146255Sgad if (sta->no_ht_set) { 167146255Sgad sta->no_ht_set = 0; 168146255Sgad hapd->iface->num_sta_no_ht--; 169146255Sgad } 170146255Sgad 171146255Sgad if (sta->ht_20mhz_set) { 172146255Sgad sta->ht_20mhz_set = 0; 173146255Sgad hapd->iface->num_sta_ht_20mhz--; 174146255Sgad } 1751556Srgrimes 1761556Srgrimes#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) 1771556Srgrimes if (hostapd_ht_operation_update(hapd->iface) > 0) 1781556Srgrimes set_beacon++; 1791556Srgrimes#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ 1801556Srgrimes 1811556Srgrimes if (set_beacon) 1821556Srgrimes ieee802_11_set_beacons(hapd->iface); 1831556Srgrimes 1841556Srgrimes eloop_cancel_timeout(ap_handle_timer, hapd, sta); 1851556Srgrimes eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); 1861556Srgrimes 1871556Srgrimes ieee802_1x_free_station(sta); 1881556Srgrimes wpa_auth_sta_deinit(sta->wpa_sm); 1891556Srgrimes rsn_preauth_free_station(hapd, sta); 1901556Srgrimes#ifndef CONFIG_NO_RADIUS 1911556Srgrimes radius_client_flush_auth(hapd->radius, sta->addr); 1921556Srgrimes#endif /* CONFIG_NO_RADIUS */ 1931556Srgrimes 1941556Srgrimes os_free(sta->last_assoc_req); 1951556Srgrimes os_free(sta->challenge); 1961556Srgrimes 1971556Srgrimes#ifdef CONFIG_IEEE80211W 1981556Srgrimes os_free(sta->sa_query_trans_id); 19919240Ssteve eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); 20019240Ssteve#endif /* CONFIG_IEEE80211W */ 20119240Ssteve 20219240Ssteve wpabuf_free(sta->wps_ie); 2031556Srgrimes 2041556Srgrimes os_free(sta->ht_capabilities); 2051556Srgrimes 2061556Srgrimes os_free(sta); 207141962Sgad} 208141962Sgad 209141962Sgad 210141962Sgadvoid hostapd_free_stas(struct hostapd_data *hapd) 211141962Sgad{ 212141962Sgad struct sta_info *sta, *prev; 213141962Sgad 214141962Sgad sta = hapd->sta_list; 215141962Sgad 216141962Sgad while (sta) { 217141962Sgad prev = sta; 218141962Sgad if (sta->flags & WLAN_STA_AUTH) { 219141962Sgad mlme_deauthenticate_indication( 220141962Sgad hapd, sta, WLAN_REASON_UNSPECIFIED); 221141962Sgad } 222141962Sgad sta = sta->next; 223141962Sgad wpa_printf(MSG_DEBUG, "Removing station " MACSTR, 224141962Sgad MAC2STR(prev->addr)); 225141962Sgad ap_free_sta(hapd, prev); 226141962Sgad } 227141962Sgad} 228141962Sgad 229141962Sgad 230141962Sgad/** 231141962Sgad * ap_handle_timer - Per STA timer handler 232141962Sgad * @eloop_ctx: struct hostapd_data * 233141962Sgad * @timeout_ctx: struct sta_info * 234141962Sgad * 235141962Sgad * This function is called to check station activity and to remove inactive 236141962Sgad * stations. 237141962Sgad */ 238141962Sgadvoid ap_handle_timer(void *eloop_ctx, void *timeout_ctx) 239141962Sgad{ 240141962Sgad struct hostapd_data *hapd = eloop_ctx; 241141962Sgad struct sta_info *sta = timeout_ctx; 242141962Sgad unsigned long next_time = 0; 243141962Sgad 244141962Sgad if (sta->timeout_next == STA_REMOVE) { 2451556Srgrimes hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 2461556Srgrimes HOSTAPD_LEVEL_INFO, "deauthenticated due to " 2471556Srgrimes "local deauth request"); 24890111Simp ap_free_sta(hapd, sta); 2491556Srgrimes return; 250151866Sstefanf } 2511556Srgrimes 2521556Srgrimes if ((sta->flags & WLAN_STA_ASSOC) && 25397276Stjr (sta->timeout_next == STA_NULLFUNC || 25497276Stjr sta->timeout_next == STA_DISASSOC)) { 25597276Stjr int inactive_sec; 25697276Stjr wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:", 25797276Stjr MAC2STR(sta->addr)); 25897276Stjr inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr); 25997276Stjr if (inactive_sec == -1) { 26097276Stjr wpa_printf(MSG_DEBUG, "Could not get station info " 261151866Sstefanf "from kernel driver for " MACSTR ".", 262151866Sstefanf MAC2STR(sta->addr)); 263151866Sstefanf } else if (inactive_sec < hapd->conf->ap_max_inactivity && 264151866Sstefanf sta->flags & WLAN_STA_ASSOC) { 265151866Sstefanf /* station activity detected; reset timeout state */ 266151866Sstefanf wpa_printf(MSG_DEBUG, " Station has been active"); 267151866Sstefanf sta->timeout_next = STA_NULLFUNC; 26897276Stjr next_time = hapd->conf->ap_max_inactivity - 2691556Srgrimes inactive_sec; 2701556Srgrimes } 2711556Srgrimes } 27219240Ssteve 27319240Ssteve if ((sta->flags & WLAN_STA_ASSOC) && 27419240Ssteve sta->timeout_next == STA_DISASSOC && 27519240Ssteve !(sta->flags & WLAN_STA_PENDING_POLL)) { 2761556Srgrimes wpa_printf(MSG_DEBUG, " Station has ACKed data poll"); 2771556Srgrimes /* data nullfunc frame poll did not produce TX errors; assume 2781556Srgrimes * station ACKed it */ 2791556Srgrimes sta->timeout_next = STA_NULLFUNC; 2801556Srgrimes next_time = hapd->conf->ap_max_inactivity; 2811556Srgrimes } 2821556Srgrimes 2838855Srgrimes if (next_time) { 2841556Srgrimes eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, 28590111Simp sta); 28690111Simp return; 2871556Srgrimes } 2881556Srgrimes 2891556Srgrimes if (sta->timeout_next == STA_NULLFUNC && 2901556Srgrimes (sta->flags & WLAN_STA_ASSOC)) { 2911556Srgrimes#ifndef CONFIG_NATIVE_WINDOWS 2921556Srgrimes /* send data frame to poll STA and check whether this frame 2931556Srgrimes * is ACKed */ 2941556Srgrimes struct ieee80211_hdr hdr; 2951556Srgrimes 2961556Srgrimes wpa_printf(MSG_DEBUG, " Polling STA with data frame"); 2971556Srgrimes sta->flags |= WLAN_STA_PENDING_POLL; 2981556Srgrimes 2991556Srgrimes os_memset(&hdr, 0, sizeof(hdr)); 3001556Srgrimes if (hapd->driver && 3011556Srgrimes os_strcmp(hapd->driver->name, "hostap") == 0) { 3021556Srgrimes /* 3031556Srgrimes * WLAN_FC_STYPE_NULLFUNC would be more appropriate, 3041556Srgrimes * but it is apparently not retried so TX Exc events 3051556Srgrimes * are not received for it. 3061556Srgrimes */ 3071556Srgrimes hdr.frame_control = 3081556Srgrimes IEEE80211_FC(WLAN_FC_TYPE_DATA, 3091556Srgrimes WLAN_FC_STYPE_DATA); 3101556Srgrimes } else { 3111556Srgrimes hdr.frame_control = 3121556Srgrimes IEEE80211_FC(WLAN_FC_TYPE_DATA, 3131556Srgrimes WLAN_FC_STYPE_NULLFUNC); 3141556Srgrimes } 3151556Srgrimes 3161556Srgrimes hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); 3171556Srgrimes os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); 3181556Srgrimes os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, 3191556Srgrimes ETH_ALEN); 3201556Srgrimes os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); 3211556Srgrimes 3221556Srgrimes if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0) 3231556Srgrimes perror("ap_handle_timer: send"); 3241556Srgrimes#endif /* CONFIG_NATIVE_WINDOWS */ 32590111Simp } else if (sta->timeout_next != STA_REMOVE) { 32690111Simp int deauth = sta->timeout_next == STA_DEAUTH; 3271556Srgrimes 3281556Srgrimes wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR, 3291556Srgrimes deauth ? "deauthentication" : "disassociation", 3301556Srgrimes MAC2STR(sta->addr)); 3311556Srgrimes 3321556Srgrimes if (deauth) { 3331556Srgrimes hapd->drv.sta_deauth(hapd, sta->addr, 3341556Srgrimes WLAN_REASON_PREV_AUTH_NOT_VALID); 3351556Srgrimes } else { 3361556Srgrimes hapd->drv.sta_disassoc( 3371556Srgrimes hapd, sta->addr, 3381556Srgrimes WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); 3391556Srgrimes } 3401556Srgrimes } 341182300Sstefanf 3421556Srgrimes switch (sta->timeout_next) { 3431556Srgrimes case STA_NULLFUNC: 3441556Srgrimes sta->timeout_next = STA_DISASSOC; 3451556Srgrimes eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, 3461556Srgrimes hapd, sta); 3471556Srgrimes break; 3481556Srgrimes case STA_DISASSOC: 3491556Srgrimes sta->flags &= ~WLAN_STA_ASSOC; 3501556Srgrimes ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 35190111Simp if (!sta->acct_terminate_cause) 35290111Simp sta->acct_terminate_cause = 3531556Srgrimes RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; 3541556Srgrimes accounting_sta_stop(hapd, sta); 3551556Srgrimes ieee802_1x_free_station(sta); 3561556Srgrimes hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 3571556Srgrimes HOSTAPD_LEVEL_INFO, "disassociated due to " 3581556Srgrimes "inactivity"); 3591556Srgrimes sta->timeout_next = STA_DEAUTH; 3601556Srgrimes eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, 3611556Srgrimes hapd, sta); 3621556Srgrimes mlme_disassociate_indication( 3631556Srgrimes hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); 3641556Srgrimes break; 3651556Srgrimes case STA_DEAUTH: 3661556Srgrimes case STA_REMOVE: 3671556Srgrimes hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 36817987Speter HOSTAPD_LEVEL_INFO, "deauthenticated due to " 36990111Simp "inactivity"); 37017987Speter if (!sta->acct_terminate_cause) 3711556Srgrimes sta->acct_terminate_cause = 3721556Srgrimes RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; 3731556Srgrimes mlme_deauthenticate_indication( 3741556Srgrimes hapd, sta, 3751556Srgrimes WLAN_REASON_PREV_AUTH_NOT_VALID); 3761556Srgrimes ap_free_sta(hapd, sta); 3771556Srgrimes break; 378157601Sstefanf } 3791556Srgrimes} 3801556Srgrimes 3811556Srgrimes 3821556Srgrimesstatic void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) 3831556Srgrimes{ 3841556Srgrimes struct hostapd_data *hapd = eloop_ctx; 3851556Srgrimes struct sta_info *sta = timeout_ctx; 3861556Srgrimes u8 addr[ETH_ALEN]; 387177497Sstefanf 3881556Srgrimes if (!(sta->flags & WLAN_STA_AUTH)) 3891556Srgrimes return; 3901556Srgrimes 3911556Srgrimes mlme_deauthenticate_indication(hapd, sta, 3921556Srgrimes WLAN_REASON_PREV_AUTH_NOT_VALID); 3931556Srgrimes hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 3941556Srgrimes HOSTAPD_LEVEL_INFO, "deauthenticated due to " 3951556Srgrimes "session timeout"); 3961556Srgrimes sta->acct_terminate_cause = 3971556Srgrimes RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; 39817987Speter os_memcpy(addr, sta->addr, ETH_ALEN); 39990111Simp ap_free_sta(hapd, sta); 40017987Speter hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); 4011556Srgrimes} 4021556Srgrimes 4031556Srgrimes 4041556Srgrimesvoid ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, 4051556Srgrimes u32 session_timeout) 4061556Srgrimes{ 4071556Srgrimes hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 4081556Srgrimes HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " 4091556Srgrimes "seconds", session_timeout); 4101556Srgrimes eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); 4111556Srgrimes eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, 4121556Srgrimes hapd, sta); 4131556Srgrimes} 41420425Ssteve 41590111Simp 41620425Sstevevoid ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) 41720425Ssteve{ 41820425Ssteve eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); 41920425Ssteve} 42020425Ssteve 42120425Ssteve 4221556Srgrimesstruct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) 4231556Srgrimes{ 4241556Srgrimes struct sta_info *sta; 4251556Srgrimes 4261556Srgrimes sta = ap_get_sta(hapd, addr); 4271556Srgrimes if (sta) 4281556Srgrimes return sta; 42917987Speter 43090111Simp wpa_printf(MSG_DEBUG, " New STA"); 43117987Speter if (hapd->num_sta >= hapd->conf->max_num_sta) { 43220425Ssteve /* FIX: might try to remove some old STAs first? */ 43320425Ssteve wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", 43420425Ssteve hapd->num_sta, hapd->conf->max_num_sta); 43595258Sdes return NULL; 43620425Ssteve } 43720425Ssteve 43820425Ssteve sta = os_zalloc(sizeof(struct sta_info)); 43920425Ssteve if (sta == NULL) { 44020425Ssteve wpa_printf(MSG_ERROR, "malloc failed"); 44120425Ssteve return NULL; 44220425Ssteve } 44320425Ssteve sta->acct_interim_interval = hapd->conf->acct_interim_interval; 44420425Ssteve 44520425Ssteve /* initialize STA info data */ 44620425Ssteve eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, 44720425Ssteve ap_handle_timer, hapd, sta); 44820425Ssteve os_memcpy(sta->addr, addr, ETH_ALEN); 44920425Ssteve sta->next = hapd->sta_list; 45020425Ssteve hapd->sta_list = sta; 45120425Ssteve hapd->num_sta++; 45290111Simp ap_sta_hash_add(hapd, sta); 45390111Simp sta->ssid = &hapd->conf->ssid; 45420425Ssteve ap_sta_remove_in_other_bss(hapd, sta); 45525227Ssteve 45620425Ssteve return sta; 45720425Ssteve} 45820425Ssteve 45920425Ssteve 4601556Srgrimesstatic int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) 4611556Srgrimes{ 46220425Ssteve ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 46320425Ssteve 46420425Ssteve wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", 46520425Ssteve MAC2STR(sta->addr)); 46620425Ssteve if (hapd->drv.sta_remove(hapd, sta->addr) && 4671556Srgrimes sta->flags & WLAN_STA_ASSOC) { 4681556Srgrimes wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR 46920742Ssteve " from kernel driver.", MAC2STR(sta->addr)); 47020425Ssteve return -1; 47120742Ssteve } 47220425Ssteve return 0; 47320425Ssteve} 4741556Srgrimes 47520425Ssteve 4761556Srgrimesstatic void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, 4771556Srgrimes struct sta_info *sta) 4781556Srgrimes{ 47920425Ssteve struct hostapd_iface *iface = hapd->iface; 4801556Srgrimes size_t i; 48120425Ssteve 4821556Srgrimes for (i = 0; i < iface->num_bss; i++) { 48320425Ssteve struct hostapd_data *bss = iface->bss[i]; 48420425Ssteve struct sta_info *sta2; 48520425Ssteve /* bss should always be set during operation, but it may be 48620425Ssteve * NULL during reconfiguration. Assume the STA is not 48720425Ssteve * associated to another BSS in that case to avoid NULL pointer 48820425Ssteve * dereferences. */ 48920425Ssteve if (bss == hapd || bss == NULL) 49020425Ssteve continue; 49120425Ssteve sta2 = ap_get_sta(bss, sta->addr); 4921556Srgrimes if (!sta2) 49320425Ssteve continue; 4941556Srgrimes 4951556Srgrimes ap_sta_disconnect(bss, sta2, sta2->addr, 4961556Srgrimes WLAN_REASON_PREV_AUTH_NOT_VALID); 4971556Srgrimes } 49820425Ssteve} 4991556Srgrimes 50020425Ssteve 50120425Sstevevoid ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, 50220425Ssteve u16 reason) 50320425Ssteve{ 50420425Ssteve wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, 50520425Ssteve hapd->conf->iface, MAC2STR(sta->addr)); 50620425Ssteve sta->flags &= ~WLAN_STA_ASSOC; 50720425Ssteve ap_sta_remove(hapd, sta); 50820425Ssteve sta->timeout_next = STA_DEAUTH; 50920425Ssteve eloop_cancel_timeout(ap_handle_timer, hapd, sta); 51020425Ssteve eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, 51120425Ssteve ap_handle_timer, hapd, sta); 51220425Ssteve accounting_sta_stop(hapd, sta); 5131556Srgrimes ieee802_1x_free_station(sta); 51420425Ssteve 51520425Ssteve mlme_disassociate_indication(hapd, sta, reason); 51620425Ssteve} 51720425Ssteve 5181556Srgrimes 5191556Srgrimesvoid ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, 52020425Ssteve u16 reason) 52120425Ssteve{ 52220425Ssteve wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, 52320425Ssteve hapd->conf->iface, MAC2STR(sta->addr)); 52420425Ssteve sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); 52520425Ssteve ap_sta_remove(hapd, sta); 52620425Ssteve sta->timeout_next = STA_REMOVE; 52720425Ssteve eloop_cancel_timeout(ap_handle_timer, hapd, sta); 52820425Ssteve eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, 5291556Srgrimes ap_handle_timer, hapd, sta); 53020425Ssteve accounting_sta_stop(hapd, sta); 53120425Ssteve ieee802_1x_free_station(sta); 53220425Ssteve 5331556Srgrimes mlme_deauthenticate_indication(hapd, sta, reason); 5341556Srgrimes} 53520425Ssteve 53620425Ssteve 53720425Ssteveint ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, 53820425Ssteve int old_vlanid) 53920425Ssteve{ 54020425Ssteve#ifndef CONFIG_NO_VLAN 54120425Ssteve const char *iface; 54220425Ssteve struct hostapd_vlan *vlan = NULL; 5431556Srgrimes int ret; 5441556Srgrimes 5451556Srgrimes /* 5461556Srgrimes * Do not proceed furthur if the vlan id remains same. We do not want 5471556Srgrimes * duplicate dynamic vlan entries. 5481556Srgrimes */ 5491556Srgrimes if (sta->vlan_id == old_vlanid) 5501556Srgrimes return 0; 5511556Srgrimes 5521556Srgrimes /* 5531556Srgrimes * During 1x reauth, if the vlan id changes, then remove the old id and 5541556Srgrimes * proceed furthur to add the new one. 5551556Srgrimes */ 5561556Srgrimes if (old_vlanid > 0) 55790111Simp vlan_remove_dynamic(hapd, old_vlanid); 55890111Simp 55925227Ssteve iface = hapd->conf->iface; 5601556Srgrimes if (sta->ssid->vlan[0]) 5611556Srgrimes iface = sta->ssid->vlan; 5621556Srgrimes 5631556Srgrimes if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) 5641556Srgrimes sta->vlan_id = 0; 5651556Srgrimes else if (sta->vlan_id > 0) { 5661556Srgrimes vlan = hapd->conf->vlan; 5671556Srgrimes while (vlan) { 5681556Srgrimes if (vlan->vlan_id == sta->vlan_id || 5691556Srgrimes vlan->vlan_id == VLAN_ID_WILDCARD) { 5701556Srgrimes iface = vlan->ifname; 5711556Srgrimes break; 5721556Srgrimes } 5731556Srgrimes vlan = vlan->next; 5741556Srgrimes } 5751556Srgrimes } 5761556Srgrimes 5771556Srgrimes if (sta->vlan_id > 0 && vlan == NULL) { 5781556Srgrimes hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 5791556Srgrimes HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " 58059436Scracauer "binding station to (vlan_id=%d)", 5811556Srgrimes sta->vlan_id); 5821556Srgrimes return -1; 5831556Srgrimes } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) { 5841556Srgrimes vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id); 5851556Srgrimes if (vlan == NULL) { 586 hostapd_logger(hapd, sta->addr, 587 HOSTAPD_MODULE_IEEE80211, 588 HOSTAPD_LEVEL_DEBUG, "could not add " 589 "dynamic VLAN interface for vlan_id=%d", 590 sta->vlan_id); 591 return -1; 592 } 593 594 iface = vlan->ifname; 595 if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { 596 hostapd_logger(hapd, sta->addr, 597 HOSTAPD_MODULE_IEEE80211, 598 HOSTAPD_LEVEL_DEBUG, "could not " 599 "configure encryption for dynamic VLAN " 600 "interface for vlan_id=%d", 601 sta->vlan_id); 602 } 603 604 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 605 HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN " 606 "interface '%s'", iface); 607 } else if (vlan && vlan->vlan_id == sta->vlan_id) { 608 if (sta->vlan_id > 0) { 609 vlan->dynamic_vlan++; 610 hostapd_logger(hapd, sta->addr, 611 HOSTAPD_MODULE_IEEE80211, 612 HOSTAPD_LEVEL_DEBUG, "updated existing " 613 "dynamic VLAN interface '%s'", iface); 614 } 615 616 /* 617 * Update encryption configuration for statically generated 618 * VLAN interface. This is only used for static WEP 619 * configuration for the case where hostapd did not yet know 620 * which keys are to be used when the interface was added. 621 */ 622 if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { 623 hostapd_logger(hapd, sta->addr, 624 HOSTAPD_MODULE_IEEE80211, 625 HOSTAPD_LEVEL_DEBUG, "could not " 626 "configure encryption for VLAN " 627 "interface for vlan_id=%d", 628 sta->vlan_id); 629 } 630 } 631 632 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 633 HOSTAPD_LEVEL_DEBUG, "binding station to interface " 634 "'%s'", iface); 635 636 if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) 637 wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); 638 639 ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); 640 if (ret < 0) { 641 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 642 HOSTAPD_LEVEL_DEBUG, "could not bind the STA " 643 "entry to vlan_id=%d", sta->vlan_id); 644 } 645 return ret; 646#else /* CONFIG_NO_VLAN */ 647 return 0; 648#endif /* CONFIG_NO_VLAN */ 649} 650 651 652#ifdef CONFIG_IEEE80211W 653 654int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) 655{ 656 u32 tu; 657 struct os_time now, passed; 658 os_get_time(&now); 659 os_time_sub(&now, &sta->sa_query_start, &passed); 660 tu = (passed.sec * 1000000 + passed.usec) / 1024; 661 if (hapd->conf->assoc_sa_query_max_timeout < tu) { 662 hostapd_logger(hapd, sta->addr, 663 HOSTAPD_MODULE_IEEE80211, 664 HOSTAPD_LEVEL_DEBUG, 665 "association SA Query timed out"); 666 sta->sa_query_timed_out = 1; 667 os_free(sta->sa_query_trans_id); 668 sta->sa_query_trans_id = NULL; 669 sta->sa_query_count = 0; 670 eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); 671 return 1; 672 } 673 674 return 0; 675} 676 677 678static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) 679{ 680 struct hostapd_data *hapd = eloop_ctx; 681 struct sta_info *sta = timeout_ctx; 682 unsigned int timeout, sec, usec; 683 u8 *trans_id, *nbuf; 684 685 if (sta->sa_query_count > 0 && 686 ap_check_sa_query_timeout(hapd, sta)) 687 return; 688 689 nbuf = os_realloc(sta->sa_query_trans_id, 690 (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN); 691 if (nbuf == NULL) 692 return; 693 if (sta->sa_query_count == 0) { 694 /* Starting a new SA Query procedure */ 695 os_get_time(&sta->sa_query_start); 696 } 697 trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; 698 sta->sa_query_trans_id = nbuf; 699 sta->sa_query_count++; 700 701 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); 702 703 timeout = hapd->conf->assoc_sa_query_retry_timeout; 704 sec = ((timeout / 1000) * 1024) / 1000; 705 usec = (timeout % 1000) * 1024; 706 eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); 707 708 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 709 HOSTAPD_LEVEL_DEBUG, 710 "association SA Query attempt %d", sta->sa_query_count); 711 712#ifdef NEED_AP_MLME 713 ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); 714#endif /* NEED_AP_MLME */ 715} 716 717 718void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) 719{ 720 ap_sa_query_timer(hapd, sta); 721} 722 723 724void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) 725{ 726 eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); 727 os_free(sta->sa_query_trans_id); 728 sta->sa_query_trans_id = NULL; 729 sta->sa_query_count = 0; 730} 731 732#endif /* CONFIG_IEEE80211W */ 733 734 735void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, 736 const u8 *addr, u16 reason) 737{ 738 739 if (sta == NULL && addr) 740 sta = ap_get_sta(hapd, addr); 741 742 if (addr) 743 hapd->drv.sta_deauth(hapd, addr, reason); 744 745 if (sta == NULL) 746 return; 747 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); 748 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 749 eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); 750 sta->timeout_next = STA_REMOVE; 751} 752