2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / Station table
4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
19 #include <netinet/in.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
26 #include "accounting.h"
27 #include "ieee802_1x.h"
28 #include "ieee802_11.h"
32 #include "radius_client.h"
34 #include "hostap_common.h"
37 int ap_for_each_sta(struct hostapd_data *hapd,
38 int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
44 for (sta = hapd->sta_list; sta; sta = sta->next) {
45 if (cb(hapd, sta, ctx))
53 struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
57 s = hapd->sta_hash[STA_HASH(sta)];
58 while (s != NULL && memcmp(s->addr, sta, 6) != 0)
64 static void ap_sta_list_del(hostapd *hapd, struct sta_info *sta)
68 if (hapd->sta_list == sta) {
69 hapd->sta_list = sta->next;
74 while (tmp != NULL && tmp->next != sta)
77 printf("Could not remove STA " MACSTR " from list.\n",
80 tmp->next = sta->next;
84 void ap_sta_hash_add(hostapd *hapd, struct sta_info *sta)
86 sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
87 hapd->sta_hash[STA_HASH(sta->addr)] = sta;
91 static void ap_sta_hash_del(hostapd *hapd, struct sta_info *sta)
95 s = hapd->sta_hash[STA_HASH(sta->addr)];
96 if (s == NULL) return;
97 if (memcmp(s->addr, sta->addr, 6) == 0) {
98 hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
102 while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, 6) != 0)
104 if (s->hnext != NULL)
105 s->hnext = s->hnext->hnext;
107 printf("AP: could not remove STA " MACSTR " from hash table\n",
112 void ap_free_sta(hostapd *hapd, struct sta_info *sta)
114 accounting_sta_stop(hapd, sta);
115 if (!(sta->flags & WLAN_STA_PREAUTH))
116 hostapd_sta_remove(hapd, sta->addr);
118 ap_sta_hash_del(hapd, sta);
119 ap_sta_list_del(hapd, sta);
122 hapd->sta_aid[sta->aid - 1] = NULL;
125 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
127 ieee802_1x_free_station(sta);
128 wpa_free_station(sta);
129 radius_client_flush_auth(hapd->radius, sta->addr);
131 if (sta->last_assoc_req)
132 free(sta->last_assoc_req);
134 free(sta->challenge);
141 void hostapd_free_stas(hostapd *hapd)
143 struct sta_info *sta, *prev;
145 sta = hapd->sta_list;
150 printf("Removing station " MACSTR "\n", MAC2STR(prev->addr));
151 ap_free_sta(hapd, prev);
156 void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
158 hostapd *hapd = eloop_ctx;
159 struct sta_info *sta = timeout_ctx;
160 unsigned long next_time = 0;
162 if (sta->timeout_next == STA_REMOVE) {
163 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
164 HOSTAPD_LEVEL_INFO, "deauthenticated due to "
165 "local deauth request");
166 ap_free_sta(hapd, sta);
170 if ((sta->flags & WLAN_STA_ASSOC) &&
171 (sta->timeout_next == STA_NULLFUNC ||
172 sta->timeout_next == STA_DISASSOC)) {
174 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
175 "Checking STA " MACSTR " inactivity:\n",
177 inactive_sec = hostapd_get_inact_sec(hapd, sta->addr);
178 if (inactive_sec == -1) {
179 printf(" Could not get station info from kernel "
180 "driver for " MACSTR ".\n",
182 } else if (inactive_sec < AP_MAX_INACTIVITY &&
183 sta->flags & WLAN_STA_ASSOC) {
184 /* station activity detected; reset timeout state */
185 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
186 " Station has been active\n");
187 sta->timeout_next = STA_NULLFUNC;
188 next_time = AP_MAX_INACTIVITY - inactive_sec;
192 if ((sta->flags & WLAN_STA_ASSOC) &&
193 sta->timeout_next == STA_DISASSOC &&
194 !(sta->flags & WLAN_STA_PENDING_POLL)) {
195 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
196 " Station has ACKed data poll\n");
197 /* data nullfunc frame poll did not produce TX errors; assume
198 * station ACKed it */
199 sta->timeout_next = STA_NULLFUNC;
200 next_time = AP_MAX_INACTIVITY;
204 eloop_register_timeout(next_time, 0, ap_handle_timer, hapd,
209 if (sta->timeout_next == STA_NULLFUNC &&
210 (sta->flags & WLAN_STA_ASSOC)) {
211 /* send data frame to poll STA and check whether this frame
213 struct ieee80211_hdr hdr;
215 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
216 " Polling STA with data frame\n");
217 sta->flags |= WLAN_STA_PENDING_POLL;
219 /* FIX: WLAN_FC_STYPE_NULLFUNC would be more appropriate, but
220 * it is apparently not retried so TX Exc events are not
222 memset(&hdr, 0, sizeof(hdr));
224 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
225 hdr.frame_control |= host_to_le16(BIT(1));
226 hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
227 memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
228 memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, ETH_ALEN);
229 memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
231 if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0)
232 perror("ap_handle_timer: send");
233 } else if (sta->timeout_next != STA_REMOVE) {
234 int deauth = sta->timeout_next == STA_DEAUTH;
236 printf(" Sending %s info to STA " MACSTR "\n",
237 deauth ? "deauthentication" : "disassociation",
241 hostapd_sta_deauth(hapd, sta->addr,
242 WLAN_REASON_PREV_AUTH_NOT_VALID);
244 hostapd_sta_disassoc(
246 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
250 switch (sta->timeout_next) {
252 sta->timeout_next = STA_DISASSOC;
253 eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer,
257 sta->flags &= ~WLAN_STA_ASSOC;
258 ieee802_1x_set_port_enabled(hapd, sta, 0);
259 if (!sta->acct_terminate_cause)
260 sta->acct_terminate_cause =
261 RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
262 accounting_sta_stop(hapd, sta);
263 ieee802_1x_free_station(sta);
264 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
265 HOSTAPD_LEVEL_INFO, "disassociated due to "
267 sta->timeout_next = STA_DEAUTH;
268 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
273 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
274 HOSTAPD_LEVEL_INFO, "deauthenticated due to "
276 if (!sta->acct_terminate_cause)
277 sta->acct_terminate_cause =
278 RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
279 ap_free_sta(hapd, sta);
285 void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
287 hostapd *hapd = eloop_ctx;
288 struct sta_info *sta = timeout_ctx;
290 if (!(sta->flags & WLAN_STA_AUTH))
293 hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
294 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
295 HOSTAPD_LEVEL_INFO, "deauthenticated due to "
297 sta->acct_terminate_cause =
298 RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
299 ap_free_sta(hapd, sta);
303 void ap_sta_session_timeout(hostapd *hapd, struct sta_info *sta,
306 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
307 HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d "
308 "seconds", session_timeout);
309 eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
310 eloop_register_timeout(session_timeout, 0, ap_handle_session_timer,
315 void ap_sta_no_session_timeout(hostapd *hapd, struct sta_info *sta)
317 eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
321 struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
323 struct sta_info *sta;
325 sta = ap_get_sta(hapd, addr);
329 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " New STA\n");
330 if (hapd->num_sta >= MAX_STA_COUNT) {
331 /* FIX: might try to remove some old STAs first? */
332 printf(" no more room for new STAs (%d/%d)\n",
333 hapd->num_sta, MAX_STA_COUNT);
337 sta = (struct sta_info *) malloc(sizeof(struct sta_info));
339 printf(" malloc failed\n");
342 memset(sta, 0, sizeof(struct sta_info));
343 sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval;
345 /* initialize STA info data */
346 eloop_register_timeout(AP_MAX_INACTIVITY, 0, ap_handle_timer,
348 memcpy(sta->addr, addr, ETH_ALEN);
349 sta->next = hapd->sta_list;
350 hapd->sta_list = sta;
352 ap_sta_hash_add(hapd, sta);