1 |
/* |
2 |
* hostapd / Station table |
3 |
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> |
4 |
* |
5 |
* This software may be distributed under the terms of the BSD license. |
6 |
* See README for more details. |
7 |
*/ |
8 |
|
9 |
#include "utils/includes.h" |
10 |
|
11 |
#include "utils/common.h" |
12 |
#include "utils/eloop.h" |
13 |
#include "common/ieee802_11_defs.h" |
14 |
#include "common/wpa_ctrl.h" |
15 |
#include "radius/radius.h" |
16 |
#include "radius/radius_client.h" |
17 |
#include "drivers/driver.h" |
18 |
#include "p2p/p2p.h" |
19 |
#include "hostapd.h" |
20 |
#include "accounting.h" |
21 |
#include "ieee802_1x.h" |
22 |
#include "ieee802_11.h" |
23 |
#include "ieee802_11_auth.h" |
24 |
#include "wpa_auth.h" |
25 |
#include "preauth_auth.h" |
26 |
#include "ap_config.h" |
27 |
#include "beacon.h" |
28 |
#include "ap_mlme.h" |
29 |
#include "vlan_init.h" |
30 |
#include "p2p_hostapd.h" |
31 |
#include "ap_drv_ops.h" |
32 |
#include "gas_serv.h" |
33 |
#include "sta_info.h" |
34 |
|
35 |
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, |
36 |
struct sta_info *sta); |
37 |
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); |
38 |
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx); |
39 |
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx); |
40 |
#ifdef CONFIG_IEEE80211W |
41 |
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); |
42 |
#endif /* CONFIG_IEEE80211W */ |
43 |
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta); |
44 |
|
45 |
int ap_for_each_sta(struct hostapd_data *hapd, |
46 |
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, |
47 |
void *ctx), |
48 |
void *ctx) |
49 |
{ |
50 |
struct sta_info *sta; |
51 |
|
52 |
for (sta = hapd->sta_list; sta; sta = sta->next) { |
53 |
if (cb(hapd, sta, ctx)) |
54 |
return 1; |
55 |
} |
56 |
|
57 |
return 0; |
58 |
} |
59 |
|
60 |
|
61 |
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) |
62 |
{ |
63 |
struct sta_info *s; |
64 |
|
65 |
s = hapd->sta_hash[STA_HASH(sta)]; |
66 |
while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) |
67 |
s = s->hnext; |
68 |
return s; |
69 |
} |
70 |
|
71 |
|
72 |
static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) |
73 |
{ |
74 |
struct sta_info *tmp; |
75 |
|
76 |
if (hapd->sta_list == sta) { |
77 |
hapd->sta_list = sta->next; |
78 |
return; |
79 |
} |
80 |
|
81 |
tmp = hapd->sta_list; |
82 |
while (tmp != NULL && tmp->next != sta) |
83 |
tmp = tmp->next; |
84 |
if (tmp == NULL) { |
85 |
wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " |
86 |
"list.", MAC2STR(sta->addr)); |
87 |
} else |
88 |
tmp->next = sta->next; |
89 |
} |
90 |
|
91 |
|
92 |
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) |
93 |
{ |
94 |
sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; |
95 |
hapd->sta_hash[STA_HASH(sta->addr)] = sta; |
96 |
} |
97 |
|
98 |
|
99 |
static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) |
100 |
{ |
101 |
struct sta_info *s; |
102 |
|
103 |
s = hapd->sta_hash[STA_HASH(sta->addr)]; |
104 |
if (s == NULL) return; |
105 |
if (os_memcmp(s->addr, sta->addr, 6) == 0) { |
106 |
hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; |
107 |
return; |
108 |
} |
109 |
|
110 |
while (s->hnext != NULL && |
111 |
os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) |
112 |
s = s->hnext; |
113 |
if (s->hnext != NULL) |
114 |
s->hnext = s->hnext->hnext; |
115 |
else |
116 |
wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR |
117 |
" from hash table", MAC2STR(sta->addr)); |
118 |
} |
119 |
|
120 |
|
121 |
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) |
122 |
{ |
123 |
int set_beacon = 0; |
124 |
|
125 |
accounting_sta_stop(hapd, sta); |
126 |
|
127 |
/* just in case */ |
128 |
ap_sta_set_authorized(hapd, sta, 0); |
129 |
|
130 |
if (sta->flags & WLAN_STA_WDS) |
131 |
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0); |
132 |
|
133 |
if (!(sta->flags & WLAN_STA_PREAUTH)) |
134 |
hostapd_drv_sta_remove(hapd, sta->addr); |
135 |
|
136 |
ap_sta_hash_del(hapd, sta); |
137 |
ap_sta_list_del(hapd, sta); |
138 |
|
139 |
if (sta->aid > 0) |
140 |
hapd->sta_aid[(sta->aid - 1) / 32] &= |
141 |
~BIT((sta->aid - 1) % 32); |
142 |
|
143 |
hapd->num_sta--; |
144 |
if (sta->nonerp_set) { |
145 |
sta->nonerp_set = 0; |
146 |
hapd->iface->num_sta_non_erp--; |
147 |
if (hapd->iface->num_sta_non_erp == 0) |
148 |
set_beacon++; |
149 |
} |
150 |
|
151 |
if (sta->no_short_slot_time_set) { |
152 |
sta->no_short_slot_time_set = 0; |
153 |
hapd->iface->num_sta_no_short_slot_time--; |
154 |
if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G |
155 |
&& hapd->iface->num_sta_no_short_slot_time == 0) |
156 |
set_beacon++; |
157 |
} |
158 |
|
159 |
if (sta->no_short_preamble_set) { |
160 |
sta->no_short_preamble_set = 0; |
161 |
hapd->iface->num_sta_no_short_preamble--; |
162 |
if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G |
163 |
&& hapd->iface->num_sta_no_short_preamble == 0) |
164 |
set_beacon++; |
165 |
} |
166 |
|
167 |
if (sta->no_ht_gf_set) { |
168 |
sta->no_ht_gf_set = 0; |
169 |
hapd->iface->num_sta_ht_no_gf--; |
170 |
} |
171 |
|
172 |
if (sta->no_ht_set) { |
173 |
sta->no_ht_set = 0; |
174 |
hapd->iface->num_sta_no_ht--; |
175 |
} |
176 |
|
177 |
if (sta->ht_20mhz_set) { |
178 |
sta->ht_20mhz_set = 0; |
179 |
hapd->iface->num_sta_ht_20mhz--; |
180 |
} |
181 |
|
182 |
#ifdef CONFIG_P2P |
183 |
if (sta->no_p2p_set) { |
184 |
sta->no_p2p_set = 0; |
185 |
hapd->num_sta_no_p2p--; |
186 |
if (hapd->num_sta_no_p2p == 0) |
187 |
hostapd_p2p_non_p2p_sta_disconnected(hapd); |
188 |
} |
189 |
#endif /* CONFIG_P2P */ |
190 |
|
191 |
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) |
192 |
if (hostapd_ht_operation_update(hapd->iface) > 0) |
193 |
set_beacon++; |
194 |
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ |
195 |
|
196 |
if (set_beacon) |
197 |
ieee802_11_set_beacons(hapd->iface); |
198 |
|
199 |
wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR, |
200 |
__func__, MAC2STR(sta->addr)); |
201 |
eloop_cancel_timeout(ap_handle_timer, hapd, sta); |
202 |
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); |
203 |
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); |
204 |
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); |
205 |
|
206 |
ieee802_1x_free_station(sta); |
207 |
wpa_auth_sta_deinit(sta->wpa_sm); |
208 |
rsn_preauth_free_station(hapd, sta); |
209 |
#ifndef CONFIG_NO_RADIUS |
210 |
radius_client_flush_auth(hapd->radius, sta->addr); |
211 |
#endif /* CONFIG_NO_RADIUS */ |
212 |
|
213 |
os_free(sta->last_assoc_req); |
214 |
os_free(sta->challenge); |
215 |
|
216 |
#ifdef CONFIG_IEEE80211W |
217 |
os_free(sta->sa_query_trans_id); |
218 |
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); |
219 |
#endif /* CONFIG_IEEE80211W */ |
220 |
|
221 |
#ifdef CONFIG_P2P |
222 |
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); |
223 |
#endif /* CONFIG_P2P */ |
224 |
|
225 |
#ifdef CONFIG_INTERWORKING |
226 |
if (sta->gas_dialog) { |
227 |
int i; |
228 |
for (i = 0; i < GAS_DIALOG_MAX; i++) |
229 |
gas_serv_dialog_clear(&sta->gas_dialog[i]); |
230 |
os_free(sta->gas_dialog); |
231 |
} |
232 |
#endif /* CONFIG_INTERWORKING */ |
233 |
|
234 |
wpabuf_free(sta->wps_ie); |
235 |
wpabuf_free(sta->p2p_ie); |
236 |
wpabuf_free(sta->hs20_ie); |
237 |
|
238 |
os_free(sta->ht_capabilities); |
239 |
hostapd_free_psk_list(sta->psk); |
240 |
os_free(sta->identity); |
241 |
os_free(sta->radius_cui); |
242 |
|
243 |
os_free(sta); |
244 |
} |
245 |
|
246 |
|
247 |
void hostapd_free_stas(struct hostapd_data *hapd) |
248 |
{ |
249 |
struct sta_info *sta, *prev; |
250 |
|
251 |
sta = hapd->sta_list; |
252 |
|
253 |
while (sta) { |
254 |
prev = sta; |
255 |
if (sta->flags & WLAN_STA_AUTH) { |
256 |
mlme_deauthenticate_indication( |
257 |
hapd, sta, WLAN_REASON_UNSPECIFIED); |
258 |
} |
259 |
sta = sta->next; |
260 |
wpa_printf(MSG_DEBUG, "Removing station " MACSTR, |
261 |
MAC2STR(prev->addr)); |
262 |
ap_free_sta(hapd, prev); |
263 |
} |
264 |
} |
265 |
|
266 |
|
267 |
/** |
268 |
* ap_handle_timer - Per STA timer handler |
269 |
* @eloop_ctx: struct hostapd_data * |
270 |
* @timeout_ctx: struct sta_info * |
271 |
* |
272 |
* This function is called to check station activity and to remove inactive |
273 |
* stations. |
274 |
*/ |
275 |
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) |
276 |
{ |
277 |
struct hostapd_data *hapd = eloop_ctx; |
278 |
struct sta_info *sta = timeout_ctx; |
279 |
unsigned long next_time = 0; |
280 |
|
281 |
wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d", |
282 |
__func__, MAC2STR(sta->addr), sta->flags, |
283 |
sta->timeout_next); |
284 |
if (sta->timeout_next == STA_REMOVE) { |
285 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
286 |
HOSTAPD_LEVEL_INFO, "deauthenticated due to " |
287 |
"local deauth request"); |
288 |
ap_free_sta(hapd, sta); |
289 |
return; |
290 |
} |
291 |
|
292 |
if ((sta->flags & WLAN_STA_ASSOC) && |
293 |
(sta->timeout_next == STA_NULLFUNC || |
294 |
sta->timeout_next == STA_DISASSOC)) { |
295 |
int inactive_sec; |
296 |
/* |
297 |
* Add random value to timeout so that we don't end up bouncing |
298 |
* all stations at the same time if we have lots of associated |
299 |
* stations that are idle (but keep re-associating). |
300 |
*/ |
301 |
int fuzz = os_random() % 20; |
302 |
inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); |
303 |
if (inactive_sec == -1) { |
304 |
wpa_msg(hapd->msg_ctx, MSG_DEBUG, |
305 |
"Check inactivity: Could not " |
306 |
"get station info from kernel driver for " |
307 |
MACSTR, MAC2STR(sta->addr)); |
308 |
/* |
309 |
* The driver may not support this functionality. |
310 |
* Anyway, try again after the next inactivity timeout, |
311 |
* but do not disconnect the station now. |
312 |
*/ |
313 |
next_time = hapd->conf->ap_max_inactivity + fuzz; |
314 |
} else if (inactive_sec < hapd->conf->ap_max_inactivity && |
315 |
sta->flags & WLAN_STA_ASSOC) { |
316 |
/* station activity detected; reset timeout state */ |
317 |
wpa_msg(hapd->msg_ctx, MSG_DEBUG, |
318 |
"Station " MACSTR " has been active %is ago", |
319 |
MAC2STR(sta->addr), inactive_sec); |
320 |
sta->timeout_next = STA_NULLFUNC; |
321 |
next_time = hapd->conf->ap_max_inactivity + fuzz - |
322 |
inactive_sec; |
323 |
} else { |
324 |
wpa_msg(hapd->msg_ctx, MSG_DEBUG, |
325 |
"Station " MACSTR " has been " |
326 |
"inactive too long: %d sec, max allowed: %d", |
327 |
MAC2STR(sta->addr), inactive_sec, |
328 |
hapd->conf->ap_max_inactivity); |
329 |
|
330 |
if (hapd->conf->skip_inactivity_poll) |
331 |
sta->timeout_next = STA_DISASSOC; |
332 |
} |
333 |
} |
334 |
|
335 |
if ((sta->flags & WLAN_STA_ASSOC) && |
336 |
sta->timeout_next == STA_DISASSOC && |
337 |
!(sta->flags & WLAN_STA_PENDING_POLL) && |
338 |
!hapd->conf->skip_inactivity_poll) { |
339 |
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR |
340 |
" has ACKed data poll", MAC2STR(sta->addr)); |
341 |
/* data nullfunc frame poll did not produce TX errors; assume |
342 |
* station ACKed it */ |
343 |
sta->timeout_next = STA_NULLFUNC; |
344 |
next_time = hapd->conf->ap_max_inactivity; |
345 |
} |
346 |
|
347 |
if (next_time) { |
348 |
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " |
349 |
"for " MACSTR " (%lu seconds)", |
350 |
__func__, MAC2STR(sta->addr), next_time); |
351 |
eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, |
352 |
sta); |
353 |
return; |
354 |
} |
355 |
|
356 |
if (sta->timeout_next == STA_NULLFUNC && |
357 |
(sta->flags & WLAN_STA_ASSOC)) { |
358 |
wpa_printf(MSG_DEBUG, " Polling STA"); |
359 |
sta->flags |= WLAN_STA_PENDING_POLL; |
360 |
hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr, |
361 |
sta->flags & WLAN_STA_WMM); |
362 |
} else if (sta->timeout_next != STA_REMOVE) { |
363 |
int deauth = sta->timeout_next == STA_DEAUTH; |
364 |
|
365 |
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, |
366 |
"Timeout, sending %s info to STA " MACSTR, |
367 |
deauth ? "deauthentication" : "disassociation", |
368 |
MAC2STR(sta->addr)); |
369 |
|
370 |
if (deauth) { |
371 |
hostapd_drv_sta_deauth( |
372 |
hapd, sta->addr, |
373 |
WLAN_REASON_PREV_AUTH_NOT_VALID); |
374 |
} else { |
375 |
hostapd_drv_sta_disassoc( |
376 |
hapd, sta->addr, |
377 |
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); |
378 |
} |
379 |
} |
380 |
|
381 |
switch (sta->timeout_next) { |
382 |
case STA_NULLFUNC: |
383 |
sta->timeout_next = STA_DISASSOC; |
384 |
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " |
385 |
"for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)", |
386 |
__func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY); |
387 |
eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, |
388 |
hapd, sta); |
389 |
break; |
390 |
case STA_DISASSOC: |
391 |
ap_sta_set_authorized(hapd, sta, 0); |
392 |
sta->flags &= ~WLAN_STA_ASSOC; |
393 |
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); |
394 |
if (!sta->acct_terminate_cause) |
395 |
sta->acct_terminate_cause = |
396 |
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; |
397 |
accounting_sta_stop(hapd, sta); |
398 |
ieee802_1x_free_station(sta); |
399 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
400 |
HOSTAPD_LEVEL_INFO, "disassociated due to " |
401 |
"inactivity"); |
402 |
sta->timeout_next = STA_DEAUTH; |
403 |
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " |
404 |
"for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", |
405 |
__func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); |
406 |
eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, |
407 |
hapd, sta); |
408 |
mlme_disassociate_indication( |
409 |
hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); |
410 |
break; |
411 |
case STA_DEAUTH: |
412 |
case STA_REMOVE: |
413 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
414 |
HOSTAPD_LEVEL_INFO, "deauthenticated due to " |
415 |
"inactivity (timer DEAUTH/REMOVE)"); |
416 |
if (!sta->acct_terminate_cause) |
417 |
sta->acct_terminate_cause = |
418 |
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; |
419 |
mlme_deauthenticate_indication( |
420 |
hapd, sta, |
421 |
WLAN_REASON_PREV_AUTH_NOT_VALID); |
422 |
ap_free_sta(hapd, sta); |
423 |
break; |
424 |
} |
425 |
} |
426 |
|
427 |
|
428 |
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) |
429 |
{ |
430 |
struct hostapd_data *hapd = eloop_ctx; |
431 |
struct sta_info *sta = timeout_ctx; |
432 |
u8 addr[ETH_ALEN]; |
433 |
|
434 |
if (!(sta->flags & WLAN_STA_AUTH)) { |
435 |
if (sta->flags & WLAN_STA_GAS) { |
436 |
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA " |
437 |
"entry " MACSTR, MAC2STR(sta->addr)); |
438 |
ap_free_sta(hapd, sta); |
439 |
} |
440 |
return; |
441 |
} |
442 |
|
443 |
mlme_deauthenticate_indication(hapd, sta, |
444 |
WLAN_REASON_PREV_AUTH_NOT_VALID); |
445 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
446 |
HOSTAPD_LEVEL_INFO, "deauthenticated due to " |
447 |
"session timeout"); |
448 |
sta->acct_terminate_cause = |
449 |
RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; |
450 |
os_memcpy(addr, sta->addr, ETH_ALEN); |
451 |
ap_free_sta(hapd, sta); |
452 |
hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); |
453 |
} |
454 |
|
455 |
|
456 |
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, |
457 |
u32 session_timeout) |
458 |
{ |
459 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
460 |
HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " |
461 |
"seconds", session_timeout); |
462 |
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); |
463 |
eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, |
464 |
hapd, sta); |
465 |
} |
466 |
|
467 |
|
468 |
void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) |
469 |
{ |
470 |
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); |
471 |
} |
472 |
|
473 |
|
474 |
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) |
475 |
{ |
476 |
struct sta_info *sta; |
477 |
|
478 |
sta = ap_get_sta(hapd, addr); |
479 |
if (sta) |
480 |
return sta; |
481 |
|
482 |
wpa_printf(MSG_DEBUG, " New STA"); |
483 |
if (hapd->num_sta >= hapd->conf->max_num_sta) { |
484 |
/* FIX: might try to remove some old STAs first? */ |
485 |
wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", |
486 |
hapd->num_sta, hapd->conf->max_num_sta); |
487 |
return NULL; |
488 |
} |
489 |
|
490 |
sta = os_zalloc(sizeof(struct sta_info)); |
491 |
if (sta == NULL) { |
492 |
wpa_printf(MSG_ERROR, "malloc failed"); |
493 |
return NULL; |
494 |
} |
495 |
sta->acct_interim_interval = hapd->conf->acct_interim_interval; |
496 |
accounting_sta_get_id(hapd, sta); |
497 |
|
498 |
/* initialize STA info data */ |
499 |
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " |
500 |
"for " MACSTR " (%d seconds - ap_max_inactivity)", |
501 |
__func__, MAC2STR(addr), |
502 |
hapd->conf->ap_max_inactivity); |
503 |
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, |
504 |
ap_handle_timer, hapd, sta); |
505 |
os_memcpy(sta->addr, addr, ETH_ALEN); |
506 |
sta->next = hapd->sta_list; |
507 |
hapd->sta_list = sta; |
508 |
hapd->num_sta++; |
509 |
ap_sta_hash_add(hapd, sta); |
510 |
sta->ssid = &hapd->conf->ssid; |
511 |
ap_sta_remove_in_other_bss(hapd, sta); |
512 |
|
513 |
return sta; |
514 |
} |
515 |
|
516 |
|
517 |
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) |
518 |
{ |
519 |
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); |
520 |
|
521 |
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", |
522 |
MAC2STR(sta->addr)); |
523 |
if (hostapd_drv_sta_remove(hapd, sta->addr) && |
524 |
sta->flags & WLAN_STA_ASSOC) { |
525 |
wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR |
526 |
" from kernel driver.", MAC2STR(sta->addr)); |
527 |
return -1; |
528 |
} |
529 |
return 0; |
530 |
} |
531 |
|
532 |
|
533 |
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, |
534 |
struct sta_info *sta) |
535 |
{ |
536 |
struct hostapd_iface *iface = hapd->iface; |
537 |
size_t i; |
538 |
|
539 |
for (i = 0; i < iface->num_bss; i++) { |
540 |
struct hostapd_data *bss = iface->bss[i]; |
541 |
struct sta_info *sta2; |
542 |
/* bss should always be set during operation, but it may be |
543 |
* NULL during reconfiguration. Assume the STA is not |
544 |
* associated to another BSS in that case to avoid NULL pointer |
545 |
* dereferences. */ |
546 |
if (bss == hapd || bss == NULL) |
547 |
continue; |
548 |
sta2 = ap_get_sta(bss, sta->addr); |
549 |
if (!sta2) |
550 |
continue; |
551 |
|
552 |
ap_sta_disconnect(bss, sta2, sta2->addr, |
553 |
WLAN_REASON_PREV_AUTH_NOT_VALID); |
554 |
} |
555 |
} |
556 |
|
557 |
|
558 |
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx) |
559 |
{ |
560 |
struct hostapd_data *hapd = eloop_ctx; |
561 |
struct sta_info *sta = timeout_ctx; |
562 |
|
563 |
ap_sta_remove(hapd, sta); |
564 |
mlme_disassociate_indication(hapd, sta, sta->disassoc_reason); |
565 |
} |
566 |
|
567 |
|
568 |
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, |
569 |
u16 reason) |
570 |
{ |
571 |
wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, |
572 |
hapd->conf->iface, MAC2STR(sta->addr)); |
573 |
sta->flags &= ~WLAN_STA_ASSOC; |
574 |
ap_sta_set_authorized(hapd, sta, 0); |
575 |
sta->timeout_next = STA_DEAUTH; |
576 |
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " |
577 |
"for " MACSTR " (%d seconds - " |
578 |
"AP_MAX_INACTIVITY_AFTER_DISASSOC)", |
579 |
__func__, MAC2STR(sta->addr), |
580 |
AP_MAX_INACTIVITY_AFTER_DISASSOC); |
581 |
eloop_cancel_timeout(ap_handle_timer, hapd, sta); |
582 |
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, |
583 |
ap_handle_timer, hapd, sta); |
584 |
accounting_sta_stop(hapd, sta); |
585 |
ieee802_1x_free_station(sta); |
586 |
|
587 |
sta->disassoc_reason = reason; |
588 |
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB; |
589 |
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); |
590 |
eloop_register_timeout(hapd->iface->drv_flags & |
591 |
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, |
592 |
ap_sta_disassoc_cb_timeout, hapd, sta); |
593 |
} |
594 |
|
595 |
|
596 |
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx) |
597 |
{ |
598 |
struct hostapd_data *hapd = eloop_ctx; |
599 |
struct sta_info *sta = timeout_ctx; |
600 |
|
601 |
ap_sta_remove(hapd, sta); |
602 |
mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason); |
603 |
} |
604 |
|
605 |
|
606 |
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, |
607 |
u16 reason) |
608 |
{ |
609 |
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, |
610 |
hapd->conf->iface, MAC2STR(sta->addr)); |
611 |
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); |
612 |
ap_sta_set_authorized(hapd, sta, 0); |
613 |
sta->timeout_next = STA_REMOVE; |
614 |
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " |
615 |
"for " MACSTR " (%d seconds - " |
616 |
"AP_MAX_INACTIVITY_AFTER_DEAUTH)", |
617 |
__func__, MAC2STR(sta->addr), |
618 |
AP_MAX_INACTIVITY_AFTER_DEAUTH); |
619 |
eloop_cancel_timeout(ap_handle_timer, hapd, sta); |
620 |
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, |
621 |
ap_handle_timer, hapd, sta); |
622 |
accounting_sta_stop(hapd, sta); |
623 |
ieee802_1x_free_station(sta); |
624 |
|
625 |
sta->deauth_reason = reason; |
626 |
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; |
627 |
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); |
628 |
eloop_register_timeout(hapd->iface->drv_flags & |
629 |
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, |
630 |
ap_sta_deauth_cb_timeout, hapd, sta); |
631 |
} |
632 |
|
633 |
|
634 |
#ifdef CONFIG_WPS |
635 |
int ap_sta_wps_cancel(struct hostapd_data *hapd, |
636 |
struct sta_info *sta, void *ctx) |
637 |
{ |
638 |
if (sta && (sta->flags & WLAN_STA_WPS)) { |
639 |
ap_sta_deauthenticate(hapd, sta, |
640 |
WLAN_REASON_PREV_AUTH_NOT_VALID); |
641 |
wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR, |
642 |
__func__, MAC2STR(sta->addr)); |
643 |
return 1; |
644 |
} |
645 |
|
646 |
return 0; |
647 |
} |
648 |
#endif /* CONFIG_WPS */ |
649 |
|
650 |
|
651 |
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, |
652 |
int old_vlanid) |
653 |
{ |
654 |
#ifndef CONFIG_NO_VLAN |
655 |
const char *iface; |
656 |
struct hostapd_vlan *vlan = NULL; |
657 |
int ret; |
658 |
|
659 |
/* |
660 |
* Do not proceed furthur if the vlan id remains same. We do not want |
661 |
* duplicate dynamic vlan entries. |
662 |
*/ |
663 |
if (sta->vlan_id == old_vlanid) |
664 |
return 0; |
665 |
|
666 |
/* |
667 |
* During 1x reauth, if the vlan id changes, then remove the old id and |
668 |
* proceed furthur to add the new one. |
669 |
*/ |
670 |
if (old_vlanid > 0) |
671 |
vlan_remove_dynamic(hapd, old_vlanid); |
672 |
|
673 |
iface = hapd->conf->iface; |
674 |
if (sta->ssid->vlan[0]) |
675 |
iface = sta->ssid->vlan; |
676 |
|
677 |
if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) |
678 |
sta->vlan_id = 0; |
679 |
else if (sta->vlan_id > 0) { |
680 |
vlan = hapd->conf->vlan; |
681 |
while (vlan) { |
682 |
if (vlan->vlan_id == sta->vlan_id || |
683 |
vlan->vlan_id == VLAN_ID_WILDCARD) { |
684 |
iface = vlan->ifname; |
685 |
break; |
686 |
} |
687 |
vlan = vlan->next; |
688 |
} |
689 |
} |
690 |
|
691 |
if (sta->vlan_id > 0 && vlan == NULL) { |
692 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
693 |
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " |
694 |
"binding station to (vlan_id=%d)", |
695 |
sta->vlan_id); |
696 |
return -1; |
697 |
} else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) { |
698 |
vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id); |
699 |
if (vlan == NULL) { |
700 |
hostapd_logger(hapd, sta->addr, |
701 |
HOSTAPD_MODULE_IEEE80211, |
702 |
HOSTAPD_LEVEL_DEBUG, "could not add " |
703 |
"dynamic VLAN interface for vlan_id=%d", |
704 |
sta->vlan_id); |
705 |
return -1; |
706 |
} |
707 |
|
708 |
iface = vlan->ifname; |
709 |
if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { |
710 |
hostapd_logger(hapd, sta->addr, |
711 |
HOSTAPD_MODULE_IEEE80211, |
712 |
HOSTAPD_LEVEL_DEBUG, "could not " |
713 |
"configure encryption for dynamic VLAN " |
714 |
"interface for vlan_id=%d", |
715 |
sta->vlan_id); |
716 |
} |
717 |
|
718 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
719 |
HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN " |
720 |
"interface '%s'", iface); |
721 |
} else if (vlan && vlan->vlan_id == sta->vlan_id) { |
722 |
if (sta->vlan_id > 0) { |
723 |
vlan->dynamic_vlan++; |
724 |
hostapd_logger(hapd, sta->addr, |
725 |
HOSTAPD_MODULE_IEEE80211, |
726 |
HOSTAPD_LEVEL_DEBUG, "updated existing " |
727 |
"dynamic VLAN interface '%s'", iface); |
728 |
} |
729 |
|
730 |
/* |
731 |
* Update encryption configuration for statically generated |
732 |
* VLAN interface. This is only used for static WEP |
733 |
* configuration for the case where hostapd did not yet know |
734 |
* which keys are to be used when the interface was added. |
735 |
*/ |
736 |
if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { |
737 |
hostapd_logger(hapd, sta->addr, |
738 |
HOSTAPD_MODULE_IEEE80211, |
739 |
HOSTAPD_LEVEL_DEBUG, "could not " |
740 |
"configure encryption for VLAN " |
741 |
"interface for vlan_id=%d", |
742 |
sta->vlan_id); |
743 |
} |
744 |
} |
745 |
|
746 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
747 |
HOSTAPD_LEVEL_DEBUG, "binding station to interface " |
748 |
"'%s'", iface); |
749 |
|
750 |
if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) |
751 |
wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); |
752 |
|
753 |
ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); |
754 |
if (ret < 0) { |
755 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
756 |
HOSTAPD_LEVEL_DEBUG, "could not bind the STA " |
757 |
"entry to vlan_id=%d", sta->vlan_id); |
758 |
} |
759 |
return ret; |
760 |
#else /* CONFIG_NO_VLAN */ |
761 |
return 0; |
762 |
#endif /* CONFIG_NO_VLAN */ |
763 |
} |
764 |
|
765 |
|
766 |
#ifdef CONFIG_IEEE80211W |
767 |
|
768 |
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) |
769 |
{ |
770 |
u32 tu; |
771 |
struct os_time now, passed; |
772 |
os_get_time(&now); |
773 |
os_time_sub(&now, &sta->sa_query_start, &passed); |
774 |
tu = (passed.sec * 1000000 + passed.usec) / 1024; |
775 |
if (hapd->conf->assoc_sa_query_max_timeout < tu) { |
776 |
hostapd_logger(hapd, sta->addr, |
777 |
HOSTAPD_MODULE_IEEE80211, |
778 |
HOSTAPD_LEVEL_DEBUG, |
779 |
"association SA Query timed out"); |
780 |
sta->sa_query_timed_out = 1; |
781 |
os_free(sta->sa_query_trans_id); |
782 |
sta->sa_query_trans_id = NULL; |
783 |
sta->sa_query_count = 0; |
784 |
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); |
785 |
return 1; |
786 |
} |
787 |
|
788 |
return 0; |
789 |
} |
790 |
|
791 |
|
792 |
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) |
793 |
{ |
794 |
struct hostapd_data *hapd = eloop_ctx; |
795 |
struct sta_info *sta = timeout_ctx; |
796 |
unsigned int timeout, sec, usec; |
797 |
u8 *trans_id, *nbuf; |
798 |
|
799 |
if (sta->sa_query_count > 0 && |
800 |
ap_check_sa_query_timeout(hapd, sta)) |
801 |
return; |
802 |
|
803 |
nbuf = os_realloc_array(sta->sa_query_trans_id, |
804 |
sta->sa_query_count + 1, |
805 |
WLAN_SA_QUERY_TR_ID_LEN); |
806 |
if (nbuf == NULL) |
807 |
return; |
808 |
if (sta->sa_query_count == 0) { |
809 |
/* Starting a new SA Query procedure */ |
810 |
os_get_time(&sta->sa_query_start); |
811 |
} |
812 |
trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; |
813 |
sta->sa_query_trans_id = nbuf; |
814 |
sta->sa_query_count++; |
815 |
|
816 |
os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); |
817 |
|
818 |
timeout = hapd->conf->assoc_sa_query_retry_timeout; |
819 |
sec = ((timeout / 1000) * 1024) / 1000; |
820 |
usec = (timeout % 1000) * 1024; |
821 |
eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); |
822 |
|
823 |
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, |
824 |
HOSTAPD_LEVEL_DEBUG, |
825 |
"association SA Query attempt %d", sta->sa_query_count); |
826 |
|
827 |
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); |
828 |
} |
829 |
|
830 |
|
831 |
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) |
832 |
{ |
833 |
ap_sa_query_timer(hapd, sta); |
834 |
} |
835 |
|
836 |
|
837 |
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) |
838 |
{ |
839 |
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); |
840 |
os_free(sta->sa_query_trans_id); |
841 |
sta->sa_query_trans_id = NULL; |
842 |
sta->sa_query_count = 0; |
843 |
} |
844 |
|
845 |
#endif /* CONFIG_IEEE80211W */ |
846 |
|
847 |
|
848 |
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, |
849 |
int authorized) |
850 |
{ |
851 |
const u8 *dev_addr = NULL; |
852 |
#ifdef CONFIG_P2P |
853 |
u8 addr[ETH_ALEN]; |
854 |
#endif /* CONFIG_P2P */ |
855 |
|
856 |
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) |
857 |
return; |
858 |
|
859 |
#ifdef CONFIG_P2P |
860 |
if (hapd->p2p_group == NULL) { |
861 |
if (sta->p2p_ie != NULL && |
862 |
p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) |
863 |
dev_addr = addr; |
864 |
} else |
865 |
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); |
866 |
#endif /* CONFIG_P2P */ |
867 |
|
868 |
if (authorized) { |
869 |
if (dev_addr) |
870 |
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED |
871 |
MACSTR " p2p_dev_addr=" MACSTR, |
872 |
MAC2STR(sta->addr), MAC2STR(dev_addr)); |
873 |
else |
874 |
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED |
875 |
MACSTR, MAC2STR(sta->addr)); |
876 |
if (hapd->msg_ctx_parent && |
877 |
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr) |
878 |
wpa_msg(hapd->msg_ctx_parent, MSG_INFO, |
879 |
AP_STA_CONNECTED MACSTR " p2p_dev_addr=" |
880 |
MACSTR, |
881 |
MAC2STR(sta->addr), MAC2STR(dev_addr)); |
882 |
else if (hapd->msg_ctx_parent && |
883 |
hapd->msg_ctx_parent != hapd->msg_ctx) |
884 |
wpa_msg(hapd->msg_ctx_parent, MSG_INFO, |
885 |
AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); |
886 |
|
887 |
sta->flags |= WLAN_STA_AUTHORIZED; |
888 |
} else { |
889 |
if (dev_addr) |
890 |
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED |
891 |
MACSTR " p2p_dev_addr=" MACSTR, |
892 |
MAC2STR(sta->addr), MAC2STR(dev_addr)); |
893 |
else |
894 |
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED |
895 |
MACSTR, MAC2STR(sta->addr)); |
896 |
if (hapd->msg_ctx_parent && |
897 |
hapd->msg_ctx_parent != hapd->msg_ctx && dev_addr) |
898 |
wpa_msg(hapd->msg_ctx_parent, MSG_INFO, |
899 |
AP_STA_DISCONNECTED MACSTR " p2p_dev_addr=" |
900 |
MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); |
901 |
else if (hapd->msg_ctx_parent && |
902 |
hapd->msg_ctx_parent != hapd->msg_ctx) |
903 |
wpa_msg(hapd->msg_ctx_parent, MSG_INFO, |
904 |
AP_STA_DISCONNECTED MACSTR, |
905 |
MAC2STR(sta->addr)); |
906 |
sta->flags &= ~WLAN_STA_AUTHORIZED; |
907 |
} |
908 |
|
909 |
if (hapd->sta_authorized_cb) |
910 |
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, |
911 |
sta->addr, authorized, dev_addr); |
912 |
} |
913 |
|
914 |
|
915 |
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, |
916 |
const u8 *addr, u16 reason) |
917 |
{ |
918 |
|
919 |
if (sta == NULL && addr) |
920 |
sta = ap_get_sta(hapd, addr); |
921 |
|
922 |
if (addr) |
923 |
hostapd_drv_sta_deauth(hapd, addr, reason); |
924 |
|
925 |
if (sta == NULL) |
926 |
return; |
927 |
ap_sta_set_authorized(hapd, sta, 0); |
928 |
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); |
929 |
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); |
930 |
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); |
931 |
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " |
932 |
"for " MACSTR " (%d seconds - " |
933 |
"AP_MAX_INACTIVITY_AFTER_DEAUTH)", |
934 |
__func__, MAC2STR(sta->addr), |
935 |
AP_MAX_INACTIVITY_AFTER_DEAUTH); |
936 |
eloop_cancel_timeout(ap_handle_timer, hapd, sta); |
937 |
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, |
938 |
ap_handle_timer, hapd, sta); |
939 |
sta->timeout_next = STA_REMOVE; |
940 |
|
941 |
sta->deauth_reason = reason; |
942 |
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; |
943 |
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); |
944 |
eloop_register_timeout(hapd->iface->drv_flags & |
945 |
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, |
946 |
ap_sta_deauth_cb_timeout, hapd, sta); |
947 |
} |
948 |
|
949 |
|
950 |
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta) |
951 |
{ |
952 |
if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) { |
953 |
wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame"); |
954 |
return; |
955 |
} |
956 |
sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB; |
957 |
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); |
958 |
ap_sta_deauth_cb_timeout(hapd, sta); |
959 |
} |
960 |
|
961 |
|
962 |
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta) |
963 |
{ |
964 |
if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) { |
965 |
wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame"); |
966 |
return; |
967 |
} |
968 |
sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB; |
969 |
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); |
970 |
ap_sta_disassoc_cb_timeout(hapd, sta); |
971 |
} |