2 * hostapd / Station table
3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "common/ieee802_11_defs.h"
20 #include "radius/radius.h"
21 #include "radius/radius_client.h"
22 #include "drivers/driver.h"
24 #include "accounting.h"
25 #include "ieee802_1x.h"
26 #include "ieee802_11.h"
28 #include "preauth_auth.h"
29 #include "ap_config.h"
32 #include "vlan_init.h"
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 #ifdef CONFIG_IEEE80211W
39 static void ap_sa_query_timer(void *eloop_ctx
, void *timeout_ctx
);
40 #endif /* CONFIG_IEEE80211W */
42 int ap_for_each_sta(struct hostapd_data
*hapd
,
43 int (*cb
)(struct hostapd_data
*hapd
, struct sta_info
*sta
,
49 for (sta
= hapd
->sta_list
; sta
; sta
= sta
->next
) {
50 if (cb(hapd
, sta
, ctx
))
58 struct sta_info
* ap_get_sta(struct hostapd_data
*hapd
, const u8
*sta
)
62 s
= hapd
->sta_hash
[STA_HASH(sta
)];
63 while (s
!= NULL
&& os_memcmp(s
->addr
, sta
, 6) != 0)
69 static void ap_sta_list_del(struct hostapd_data
*hapd
, struct sta_info
*sta
)
73 if (hapd
->sta_list
== sta
) {
74 hapd
->sta_list
= sta
->next
;
79 while (tmp
!= NULL
&& tmp
->next
!= sta
)
82 wpa_printf(MSG_DEBUG
, "Could not remove STA " MACSTR
" from "
83 "list.", MAC2STR(sta
->addr
));
85 tmp
->next
= sta
->next
;
89 void ap_sta_hash_add(struct hostapd_data
*hapd
, struct sta_info
*sta
)
91 sta
->hnext
= hapd
->sta_hash
[STA_HASH(sta
->addr
)];
92 hapd
->sta_hash
[STA_HASH(sta
->addr
)] = sta
;
96 static void ap_sta_hash_del(struct hostapd_data
*hapd
, struct sta_info
*sta
)
100 s
= hapd
->sta_hash
[STA_HASH(sta
->addr
)];
101 if (s
== NULL
) return;
102 if (os_memcmp(s
->addr
, sta
->addr
, 6) == 0) {
103 hapd
->sta_hash
[STA_HASH(sta
->addr
)] = s
->hnext
;
107 while (s
->hnext
!= NULL
&&
108 os_memcmp(s
->hnext
->addr
, sta
->addr
, ETH_ALEN
) != 0)
110 if (s
->hnext
!= NULL
)
111 s
->hnext
= s
->hnext
->hnext
;
113 wpa_printf(MSG_DEBUG
, "AP: could not remove STA " MACSTR
114 " from hash table", MAC2STR(sta
->addr
));
118 void ap_free_sta(struct hostapd_data
*hapd
, struct sta_info
*sta
)
122 accounting_sta_stop(hapd
, sta
);
124 if (sta
->flags
& WLAN_STA_WDS
)
125 hapd
->drv
.set_wds_sta(hapd
, sta
->addr
, sta
->aid
, 0);
127 if (!(sta
->flags
& WLAN_STA_PREAUTH
))
128 hapd
->drv
.sta_remove(hapd
, sta
->addr
);
130 ap_sta_hash_del(hapd
, sta
);
131 ap_sta_list_del(hapd
, sta
);
134 hapd
->sta_aid
[(sta
->aid
- 1) / 32] &=
135 ~BIT((sta
->aid
- 1) % 32);
138 if (sta
->nonerp_set
) {
140 hapd
->iface
->num_sta_non_erp
--;
141 if (hapd
->iface
->num_sta_non_erp
== 0)
145 if (sta
->no_short_slot_time_set
) {
146 sta
->no_short_slot_time_set
= 0;
147 hapd
->iface
->num_sta_no_short_slot_time
--;
148 if (hapd
->iface
->current_mode
->mode
== HOSTAPD_MODE_IEEE80211G
149 && hapd
->iface
->num_sta_no_short_slot_time
== 0)
153 if (sta
->no_short_preamble_set
) {
154 sta
->no_short_preamble_set
= 0;
155 hapd
->iface
->num_sta_no_short_preamble
--;
156 if (hapd
->iface
->current_mode
->mode
== HOSTAPD_MODE_IEEE80211G
157 && hapd
->iface
->num_sta_no_short_preamble
== 0)
161 if (sta
->no_ht_gf_set
) {
162 sta
->no_ht_gf_set
= 0;
163 hapd
->iface
->num_sta_ht_no_gf
--;
166 if (sta
->no_ht_set
) {
168 hapd
->iface
->num_sta_no_ht
--;
171 if (sta
->ht_20mhz_set
) {
172 sta
->ht_20mhz_set
= 0;
173 hapd
->iface
->num_sta_ht_20mhz
--;
176 #if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
177 if (hostapd_ht_operation_update(hapd
->iface
) > 0)
179 #endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
182 ieee802_11_set_beacons(hapd
->iface
);
184 eloop_cancel_timeout(ap_handle_timer
, hapd
, sta
);
185 eloop_cancel_timeout(ap_handle_session_timer
, hapd
, sta
);
187 ieee802_1x_free_station(sta
);
188 wpa_auth_sta_deinit(sta
->wpa_sm
);
189 rsn_preauth_free_station(hapd
, sta
);
190 #ifndef CONFIG_NO_RADIUS
191 radius_client_flush_auth(hapd
->radius
, sta
->addr
);
192 #endif /* CONFIG_NO_RADIUS */
194 os_free(sta
->last_assoc_req
);
195 os_free(sta
->challenge
);
197 #ifdef CONFIG_IEEE80211W
198 os_free(sta
->sa_query_trans_id
);
199 eloop_cancel_timeout(ap_sa_query_timer
, hapd
, sta
);
200 #endif /* CONFIG_IEEE80211W */
202 wpabuf_free(sta
->wps_ie
);
204 os_free(sta
->ht_capabilities
);
210 void hostapd_free_stas(struct hostapd_data
*hapd
)
212 struct sta_info
*sta
, *prev
;
214 sta
= hapd
->sta_list
;
218 if (sta
->flags
& WLAN_STA_AUTH
) {
219 mlme_deauthenticate_indication(
220 hapd
, sta
, WLAN_REASON_UNSPECIFIED
);
223 wpa_printf(MSG_DEBUG
, "Removing station " MACSTR
,
224 MAC2STR(prev
->addr
));
225 ap_free_sta(hapd
, prev
);
231 * ap_handle_timer - Per STA timer handler
232 * @eloop_ctx: struct hostapd_data *
233 * @timeout_ctx: struct sta_info *
235 * This function is called to check station activity and to remove inactive
238 void ap_handle_timer(void *eloop_ctx
, void *timeout_ctx
)
240 struct hostapd_data
*hapd
= eloop_ctx
;
241 struct sta_info
*sta
= timeout_ctx
;
242 unsigned long next_time
= 0;
244 if (sta
->timeout_next
== STA_REMOVE
) {
245 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
246 HOSTAPD_LEVEL_INFO
, "deauthenticated due to "
247 "local deauth request");
248 ap_free_sta(hapd
, sta
);
252 if ((sta
->flags
& WLAN_STA_ASSOC
) &&
253 (sta
->timeout_next
== STA_NULLFUNC
||
254 sta
->timeout_next
== STA_DISASSOC
)) {
256 wpa_printf(MSG_DEBUG
, "Checking STA " MACSTR
" inactivity:",
258 inactive_sec
= hapd
->drv
.get_inact_sec(hapd
, sta
->addr
);
259 if (inactive_sec
== -1) {
260 wpa_printf(MSG_DEBUG
, "Could not get station info "
261 "from kernel driver for " MACSTR
".",
263 } else if (inactive_sec
< hapd
->conf
->ap_max_inactivity
&&
264 sta
->flags
& WLAN_STA_ASSOC
) {
265 /* station activity detected; reset timeout state */
266 wpa_printf(MSG_DEBUG
, " Station has been active");
267 sta
->timeout_next
= STA_NULLFUNC
;
268 next_time
= hapd
->conf
->ap_max_inactivity
-
273 if ((sta
->flags
& WLAN_STA_ASSOC
) &&
274 sta
->timeout_next
== STA_DISASSOC
&&
275 !(sta
->flags
& WLAN_STA_PENDING_POLL
)) {
276 wpa_printf(MSG_DEBUG
, " Station has ACKed data poll");
277 /* data nullfunc frame poll did not produce TX errors; assume
278 * station ACKed it */
279 sta
->timeout_next
= STA_NULLFUNC
;
280 next_time
= hapd
->conf
->ap_max_inactivity
;
284 eloop_register_timeout(next_time
, 0, ap_handle_timer
, hapd
,
289 if (sta
->timeout_next
== STA_NULLFUNC
&&
290 (sta
->flags
& WLAN_STA_ASSOC
)) {
291 #ifndef CONFIG_NATIVE_WINDOWS
292 /* send data frame to poll STA and check whether this frame
294 struct ieee80211_hdr hdr
;
296 wpa_printf(MSG_DEBUG
, " Polling STA with data frame");
297 sta
->flags
|= WLAN_STA_PENDING_POLL
;
299 os_memset(&hdr
, 0, sizeof(hdr
));
301 os_strcmp(hapd
->driver
->name
, "hostap") == 0) {
303 * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
304 * but it is apparently not retried so TX Exc events
305 * are not received for it.
308 IEEE80211_FC(WLAN_FC_TYPE_DATA
,
312 IEEE80211_FC(WLAN_FC_TYPE_DATA
,
313 WLAN_FC_STYPE_NULLFUNC
);
316 hdr
.frame_control
|= host_to_le16(WLAN_FC_FROMDS
);
317 os_memcpy(hdr
.IEEE80211_DA_FROMDS
, sta
->addr
, ETH_ALEN
);
318 os_memcpy(hdr
.IEEE80211_BSSID_FROMDS
, hapd
->own_addr
,
320 os_memcpy(hdr
.IEEE80211_SA_FROMDS
, hapd
->own_addr
, ETH_ALEN
);
322 if (hapd
->drv
.send_mgmt_frame(hapd
, &hdr
, sizeof(hdr
)) < 0)
323 perror("ap_handle_timer: send");
324 #endif /* CONFIG_NATIVE_WINDOWS */
325 } else if (sta
->timeout_next
!= STA_REMOVE
) {
326 int deauth
= sta
->timeout_next
== STA_DEAUTH
;
328 wpa_printf(MSG_DEBUG
, "Sending %s info to STA " MACSTR
,
329 deauth
? "deauthentication" : "disassociation",
333 hapd
->drv
.sta_deauth(hapd
, sta
->addr
,
334 WLAN_REASON_PREV_AUTH_NOT_VALID
);
336 hapd
->drv
.sta_disassoc(
338 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY
);
342 switch (sta
->timeout_next
) {
344 sta
->timeout_next
= STA_DISASSOC
;
345 eloop_register_timeout(AP_DISASSOC_DELAY
, 0, ap_handle_timer
,
349 sta
->flags
&= ~WLAN_STA_ASSOC
;
350 ieee802_1x_notify_port_enabled(sta
->eapol_sm
, 0);
351 if (!sta
->acct_terminate_cause
)
352 sta
->acct_terminate_cause
=
353 RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT
;
354 accounting_sta_stop(hapd
, sta
);
355 ieee802_1x_free_station(sta
);
356 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
357 HOSTAPD_LEVEL_INFO
, "disassociated due to "
359 sta
->timeout_next
= STA_DEAUTH
;
360 eloop_register_timeout(AP_DEAUTH_DELAY
, 0, ap_handle_timer
,
362 mlme_disassociate_indication(
363 hapd
, sta
, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY
);
367 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
368 HOSTAPD_LEVEL_INFO
, "deauthenticated due to "
370 if (!sta
->acct_terminate_cause
)
371 sta
->acct_terminate_cause
=
372 RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT
;
373 mlme_deauthenticate_indication(
375 WLAN_REASON_PREV_AUTH_NOT_VALID
);
376 ap_free_sta(hapd
, sta
);
382 static void ap_handle_session_timer(void *eloop_ctx
, void *timeout_ctx
)
384 struct hostapd_data
*hapd
= eloop_ctx
;
385 struct sta_info
*sta
= timeout_ctx
;
388 if (!(sta
->flags
& WLAN_STA_AUTH
))
391 mlme_deauthenticate_indication(hapd
, sta
,
392 WLAN_REASON_PREV_AUTH_NOT_VALID
);
393 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
394 HOSTAPD_LEVEL_INFO
, "deauthenticated due to "
396 sta
->acct_terminate_cause
=
397 RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT
;
398 os_memcpy(addr
, sta
->addr
, ETH_ALEN
);
399 ap_free_sta(hapd
, sta
);
400 hapd
->drv
.sta_deauth(hapd
, addr
, WLAN_REASON_PREV_AUTH_NOT_VALID
);
404 void ap_sta_session_timeout(struct hostapd_data
*hapd
, struct sta_info
*sta
,
407 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
408 HOSTAPD_LEVEL_DEBUG
, "setting session timeout to %d "
409 "seconds", session_timeout
);
410 eloop_cancel_timeout(ap_handle_session_timer
, hapd
, sta
);
411 eloop_register_timeout(session_timeout
, 0, ap_handle_session_timer
,
416 void ap_sta_no_session_timeout(struct hostapd_data
*hapd
, struct sta_info
*sta
)
418 eloop_cancel_timeout(ap_handle_session_timer
, hapd
, sta
);
422 struct sta_info
* ap_sta_add(struct hostapd_data
*hapd
, const u8
*addr
)
424 struct sta_info
*sta
;
426 sta
= ap_get_sta(hapd
, addr
);
430 wpa_printf(MSG_DEBUG
, " New STA");
431 if (hapd
->num_sta
>= hapd
->conf
->max_num_sta
) {
432 /* FIX: might try to remove some old STAs first? */
433 wpa_printf(MSG_DEBUG
, "no more room for new STAs (%d/%d)",
434 hapd
->num_sta
, hapd
->conf
->max_num_sta
);
438 sta
= os_zalloc(sizeof(struct sta_info
));
440 wpa_printf(MSG_ERROR
, "malloc failed");
443 sta
->acct_interim_interval
= hapd
->conf
->acct_interim_interval
;
445 /* initialize STA info data */
446 eloop_register_timeout(hapd
->conf
->ap_max_inactivity
, 0,
447 ap_handle_timer
, hapd
, sta
);
448 os_memcpy(sta
->addr
, addr
, ETH_ALEN
);
449 sta
->next
= hapd
->sta_list
;
450 hapd
->sta_list
= sta
;
452 ap_sta_hash_add(hapd
, sta
);
453 sta
->ssid
= &hapd
->conf
->ssid
;
454 ap_sta_remove_in_other_bss(hapd
, sta
);
460 static int ap_sta_remove(struct hostapd_data
*hapd
, struct sta_info
*sta
)
462 ieee802_1x_notify_port_enabled(sta
->eapol_sm
, 0);
464 wpa_printf(MSG_DEBUG
, "Removing STA " MACSTR
" from kernel driver",
466 if (hapd
->drv
.sta_remove(hapd
, sta
->addr
) &&
467 sta
->flags
& WLAN_STA_ASSOC
) {
468 wpa_printf(MSG_DEBUG
, "Could not remove station " MACSTR
469 " from kernel driver.", MAC2STR(sta
->addr
));
476 static void ap_sta_remove_in_other_bss(struct hostapd_data
*hapd
,
477 struct sta_info
*sta
)
479 struct hostapd_iface
*iface
= hapd
->iface
;
482 for (i
= 0; i
< iface
->num_bss
; i
++) {
483 struct hostapd_data
*bss
= iface
->bss
[i
];
484 struct sta_info
*sta2
;
485 /* bss should always be set during operation, but it may be
486 * NULL during reconfiguration. Assume the STA is not
487 * associated to another BSS in that case to avoid NULL pointer
489 if (bss
== hapd
|| bss
== NULL
)
491 sta2
= ap_get_sta(bss
, sta
->addr
);
495 ap_sta_disconnect(bss
, sta2
, sta2
->addr
,
496 WLAN_REASON_PREV_AUTH_NOT_VALID
);
501 void ap_sta_disassociate(struct hostapd_data
*hapd
, struct sta_info
*sta
,
504 wpa_printf(MSG_DEBUG
, "%s: disassociate STA " MACSTR
,
505 hapd
->conf
->iface
, MAC2STR(sta
->addr
));
506 sta
->flags
&= ~WLAN_STA_ASSOC
;
507 ap_sta_remove(hapd
, sta
);
508 sta
->timeout_next
= STA_DEAUTH
;
509 eloop_cancel_timeout(ap_handle_timer
, hapd
, sta
);
510 eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC
, 0,
511 ap_handle_timer
, hapd
, sta
);
512 accounting_sta_stop(hapd
, sta
);
513 ieee802_1x_free_station(sta
);
515 mlme_disassociate_indication(hapd
, sta
, reason
);
519 void ap_sta_deauthenticate(struct hostapd_data
*hapd
, struct sta_info
*sta
,
522 wpa_printf(MSG_DEBUG
, "%s: deauthenticate STA " MACSTR
,
523 hapd
->conf
->iface
, MAC2STR(sta
->addr
));
524 sta
->flags
&= ~(WLAN_STA_AUTH
| WLAN_STA_ASSOC
);
525 ap_sta_remove(hapd
, sta
);
526 sta
->timeout_next
= STA_REMOVE
;
527 eloop_cancel_timeout(ap_handle_timer
, hapd
, sta
);
528 eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH
, 0,
529 ap_handle_timer
, hapd
, sta
);
530 accounting_sta_stop(hapd
, sta
);
531 ieee802_1x_free_station(sta
);
533 mlme_deauthenticate_indication(hapd
, sta
, reason
);
537 int ap_sta_bind_vlan(struct hostapd_data
*hapd
, struct sta_info
*sta
,
540 #ifndef CONFIG_NO_VLAN
542 struct hostapd_vlan
*vlan
= NULL
;
546 * Do not proceed furthur if the vlan id remains same. We do not want
547 * duplicate dynamic vlan entries.
549 if (sta
->vlan_id
== old_vlanid
)
553 * During 1x reauth, if the vlan id changes, then remove the old id and
554 * proceed furthur to add the new one.
557 vlan_remove_dynamic(hapd
, old_vlanid
);
559 iface
= hapd
->conf
->iface
;
560 if (sta
->ssid
->vlan
[0])
561 iface
= sta
->ssid
->vlan
;
563 if (sta
->ssid
->dynamic_vlan
== DYNAMIC_VLAN_DISABLED
)
565 else if (sta
->vlan_id
> 0) {
566 vlan
= hapd
->conf
->vlan
;
568 if (vlan
->vlan_id
== sta
->vlan_id
||
569 vlan
->vlan_id
== VLAN_ID_WILDCARD
) {
570 iface
= vlan
->ifname
;
577 if (sta
->vlan_id
> 0 && vlan
== NULL
) {
578 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
579 HOSTAPD_LEVEL_DEBUG
, "could not find VLAN for "
580 "binding station to (vlan_id=%d)",
583 } else if (sta
->vlan_id
> 0 && vlan
->vlan_id
== VLAN_ID_WILDCARD
) {
584 vlan
= vlan_add_dynamic(hapd
, vlan
, sta
->vlan_id
);
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",
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",
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
);
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.
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",
632 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
633 HOSTAPD_LEVEL_DEBUG
, "binding station to interface "
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");
639 ret
= hapd
->drv
.set_sta_vlan(iface
, hapd
, sta
->addr
, sta
->vlan_id
);
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
);
646 #else /* CONFIG_NO_VLAN */
648 #endif /* CONFIG_NO_VLAN */
652 #ifdef CONFIG_IEEE80211W
654 int ap_check_sa_query_timeout(struct hostapd_data
*hapd
, struct sta_info
*sta
)
657 struct os_time now
, passed
;
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
,
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
);
678 static void ap_sa_query_timer(void *eloop_ctx
, void *timeout_ctx
)
680 struct hostapd_data
*hapd
= eloop_ctx
;
681 struct sta_info
*sta
= timeout_ctx
;
682 unsigned int timeout
, sec
, usec
;
685 if (sta
->sa_query_count
> 0 &&
686 ap_check_sa_query_timeout(hapd
, sta
))
689 nbuf
= os_realloc(sta
->sa_query_trans_id
,
690 (sta
->sa_query_count
+ 1) * WLAN_SA_QUERY_TR_ID_LEN
);
693 if (sta
->sa_query_count
== 0) {
694 /* Starting a new SA Query procedure */
695 os_get_time(&sta
->sa_query_start
);
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
++;
701 os_get_random(trans_id
, WLAN_SA_QUERY_TR_ID_LEN
);
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
);
708 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_IEEE80211
,
710 "association SA Query attempt %d", sta
->sa_query_count
);
713 ieee802_11_send_sa_query_req(hapd
, sta
->addr
, trans_id
);
714 #endif /* NEED_AP_MLME */
718 void ap_sta_start_sa_query(struct hostapd_data
*hapd
, struct sta_info
*sta
)
720 ap_sa_query_timer(hapd
, sta
);
724 void ap_sta_stop_sa_query(struct hostapd_data
*hapd
, struct sta_info
*sta
)
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;
732 #endif /* CONFIG_IEEE80211W */
735 void ap_sta_disconnect(struct hostapd_data
*hapd
, struct sta_info
*sta
,
736 const u8
*addr
, u16 reason
)
739 if (sta
== NULL
&& addr
)
740 sta
= ap_get_sta(hapd
, addr
);
743 hapd
->drv
.sta_deauth(hapd
, addr
, reason
);
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
;