📄 sta_info.c
字号:
/* * hostapd / Station table * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> * Copyright (c) 2007-2008, Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "hostapd.h"#include "sta_info.h"#include "eloop.h"#include "accounting.h"#include "ieee802_1x.h"#include "ieee802_11.h"#include "radius/radius.h"#include "wpa.h"#include "preauth.h"#include "radius/radius_client.h"#include "driver.h"#include "beacon.h"#include "hw_features.h"#include "mlme.h"#include "vlan_init.h"static int ap_sta_in_other_bss(struct hostapd_data *hapd, struct sta_info *sta, u32 flags);static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);#ifdef CONFIG_IEEE80211Wstatic void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);#endif /* CONFIG_IEEE80211W */int ap_for_each_sta(struct hostapd_data *hapd, int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, void *ctx), void *ctx){ struct sta_info *sta; for (sta = hapd->sta_list; sta; sta = sta->next) { if (cb(hapd, sta, ctx)) return 1; } return 0;}struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta){ struct sta_info *s; s = hapd->sta_hash[STA_HASH(sta)]; while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) s = s->hnext; return s;}static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta){ struct sta_info *tmp; if (hapd->sta_list == sta) { hapd->sta_list = sta->next; return; } tmp = hapd->sta_list; while (tmp != NULL && tmp->next != sta) tmp = tmp->next; if (tmp == NULL) { wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " "list.", MAC2STR(sta->addr)); } else tmp->next = sta->next;}void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta){ sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; hapd->sta_hash[STA_HASH(sta->addr)] = sta;}static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta){ struct sta_info *s; s = hapd->sta_hash[STA_HASH(sta->addr)]; if (s == NULL) return; if (os_memcmp(s->addr, sta->addr, 6) == 0) { hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; return; } while (s->hnext != NULL && os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) s = s->hnext; if (s->hnext != NULL) s->hnext = s->hnext->hnext; else wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR " from hash table", MAC2STR(sta->addr));}void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta){ int set_beacon = 0; accounting_sta_stop(hapd, sta); if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && !(sta->flags & WLAN_STA_PREAUTH)) hostapd_sta_remove(hapd, sta->addr); ap_sta_hash_del(hapd, sta); ap_sta_list_del(hapd, sta); if (sta->aid > 0) hapd->sta_aid[sta->aid - 1] = NULL; hapd->num_sta--; if (sta->nonerp_set) { sta->nonerp_set = 0; hapd->iface->num_sta_non_erp--; if (hapd->iface->num_sta_non_erp == 0) set_beacon++; } if (sta->no_short_slot_time_set) { sta->no_short_slot_time_set = 0; hapd->iface->num_sta_no_short_slot_time--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_slot_time == 0) set_beacon++; } if (sta->no_short_preamble_set) { sta->no_short_preamble_set = 0; hapd->iface->num_sta_no_short_preamble--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_preamble == 0) set_beacon++; }#ifdef CONFIG_IEEE80211N if (sta->no_ht_gf_set) { sta->no_ht_gf_set = 0; hapd->iface->num_sta_ht_no_gf--; } if (sta->no_ht_set) { sta->no_ht_set = 0; hapd->iface->num_sta_no_ht--; } if (sta->ht_20mhz_set) { sta->ht_20mhz_set = 0; hapd->iface->num_sta_ht_20mhz--; } if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++;#endif /* CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_set_beacons(hapd->iface); eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); ieee802_1x_free_station(sta); wpa_auth_sta_deinit(sta->wpa_sm); rsn_preauth_free_station(hapd, sta); radius_client_flush_auth(hapd->radius, sta->addr); os_free(sta->last_assoc_req); os_free(sta->challenge);#ifdef CONFIG_IEEE80211W os_free(sta->sa_query_trans_id); eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);#endif /* CONFIG_IEEE80211W */ wpabuf_free(sta->wps_ie); os_free(sta);}void hostapd_free_stas(struct hostapd_data *hapd){ struct sta_info *sta, *prev; sta = hapd->sta_list; while (sta) { prev = sta; if (sta->flags & WLAN_STA_AUTH) { mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_UNSPECIFIED); } sta = sta->next; wpa_printf(MSG_DEBUG, "Removing station " MACSTR, MAC2STR(prev->addr)); ap_free_sta(hapd, prev); }}/** * ap_handle_timer - Per STA timer handler * @eloop_ctx: struct hostapd_data * * @timeout_ctx: struct sta_info * * * This function is called to check station activity and to remove inactive * stations. */void ap_handle_timer(void *eloop_ctx, void *timeout_ctx){ struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; unsigned long next_time = 0; if (sta->timeout_next == STA_REMOVE) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "local deauth request"); ap_free_sta(hapd, sta); return; } if ((sta->flags & WLAN_STA_ASSOC) && (sta->timeout_next == STA_NULLFUNC || sta->timeout_next == STA_DISASSOC)) { int inactive_sec; wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:", MAC2STR(sta->addr)); inactive_sec = hostapd_get_inact_sec(hapd, sta->addr); if (inactive_sec == -1) { wpa_printf(MSG_DEBUG, "Could not get station info " "from kernel driver for " MACSTR ".", MAC2STR(sta->addr)); } else if (inactive_sec < hapd->conf->ap_max_inactivity && sta->flags & WLAN_STA_ASSOC) { /* station activity detected; reset timeout state */ wpa_printf(MSG_DEBUG, " Station has been active"); sta->timeout_next = STA_NULLFUNC; next_time = hapd->conf->ap_max_inactivity - inactive_sec; } } if ((sta->flags & WLAN_STA_ASSOC) && sta->timeout_next == STA_DISASSOC && !(sta->flags & WLAN_STA_PENDING_POLL)) { wpa_printf(MSG_DEBUG, " Station has ACKed data poll"); /* data nullfunc frame poll did not produce TX errors; assume * station ACKed it */ sta->timeout_next = STA_NULLFUNC; next_time = hapd->conf->ap_max_inactivity; } if (next_time) { eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, sta); return; } if (sta->timeout_next == STA_NULLFUNC && (sta->flags & WLAN_STA_ASSOC)) { /* send data frame to poll STA and check whether this frame * is ACKed */ struct ieee80211_hdr hdr; wpa_printf(MSG_DEBUG, " Polling STA with data frame"); sta->flags |= WLAN_STA_PENDING_POLL;#ifndef CONFIG_NATIVE_WINDOWS os_memset(&hdr, 0, sizeof(hdr)); if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") == 0) { /* * WLAN_FC_STYPE_NULLFUNC would be more appropriate, * but it is apparently not retried so TX Exc events * are not received for it. */ hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); } else { hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_NULLFUNC); } hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, ETH_ALEN); os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0) perror("ap_handle_timer: send");#endif /* CONFIG_NATIVE_WINDOWS */ } else if (sta->timeout_next != STA_REMOVE) { int deauth = sta->timeout_next == STA_DEAUTH; wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR, deauth ? "deauthentication" : "disassociation", MAC2STR(sta->addr)); if (deauth) { hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } else { hostapd_sta_disassoc( hapd, sta->addr, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } switch (sta->timeout_next) { case STA_NULLFUNC: sta->timeout_next = STA_DISASSOC; eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, hapd, sta); break; case STA_DISASSOC: sta->flags &= ~WLAN_STA_ASSOC; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; accounting_sta_stop(hapd, sta); ieee802_1x_free_station(sta); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated due to " "inactivity"); sta->timeout_next = STA_DEAUTH; eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); mlme_disassociate_indication( hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -