1 /*
2 * hostapd / Station table
3 * Copyright (c) 2002-2017, 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/sae.h"
15 #include "crypto/crypto.h"
16 #include "hostapd.h"
17 #include "ieee802_1x.h"
18 #include "wpa_auth.h"
19 #include "ap_config.h"
20 #include "sta_info.h"
21 #include "esp_wps_i.h"
22
23 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
24 void hostapd_wps_eap_completed(struct hostapd_data *hapd);
25
ap_for_each_sta(struct hostapd_data * hapd,int (* cb)(struct hostapd_data * hapd,struct sta_info * sta,void * ctx),void * ctx)26 int ap_for_each_sta(struct hostapd_data *hapd,
27 int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
28 void *ctx),
29 void *ctx)
30 {
31 struct sta_info *sta;
32
33 for (sta = hapd->sta_list; sta; sta = sta->next) {
34 if (cb(hapd, sta, ctx))
35 return 1;
36 }
37
38 return 0;
39 }
40
41
ap_get_sta(struct hostapd_data * hapd,const u8 * sta)42 struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
43 {
44 struct sta_info *s;
45
46 s = hapd->sta_hash[STA_HASH(sta)];
47 while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
48 s = s->hnext;
49 return s;
50 }
51
52
ap_sta_list_del(struct hostapd_data * hapd,struct sta_info * sta)53 static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
54 {
55 struct sta_info *tmp;
56
57 if (hapd->sta_list == sta) {
58 hapd->sta_list = sta->next;
59 return;
60 }
61
62 tmp = hapd->sta_list;
63 while (tmp != NULL && tmp->next != sta)
64 tmp = tmp->next;
65 if (tmp == NULL) {
66 wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
67 "list.", MAC2STR(sta->addr));
68 } else
69 tmp->next = sta->next;
70 }
71
72
ap_sta_hash_add(struct hostapd_data * hapd,struct sta_info * sta)73 void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
74 {
75 sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
76 hapd->sta_hash[STA_HASH(sta->addr)] = sta;
77 }
78
79
ap_sta_hash_del(struct hostapd_data * hapd,struct sta_info * sta)80 static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
81 {
82 struct sta_info *s;
83
84 s = hapd->sta_hash[STA_HASH(sta->addr)];
85 if (s == NULL) return;
86 if (os_memcmp(s->addr, sta->addr, 6) == 0) {
87 hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
88 return;
89 }
90
91 while (s->hnext != NULL &&
92 os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
93 s = s->hnext;
94 if (s->hnext != NULL)
95 s->hnext = s->hnext->hnext;
96 else
97 wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
98 " from hash table", MAC2STR(sta->addr));
99 }
100
ap_free_sta(struct hostapd_data * hapd,struct sta_info * sta)101 void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
102 {
103 ap_sta_hash_del(hapd, sta);
104 ap_sta_list_del(hapd, sta);
105
106 hapd->num_sta--;
107
108 #ifdef CONFIG_SAE
109 sae_clear_data(sta->sae);
110 os_free(sta->sae);
111 if (sta->lock) {
112 os_semphr_give(sta->lock);
113 os_mutex_delete(sta->lock);
114 sta->lock = NULL;
115 }
116 #endif /* CONFIG_SAE */
117 wpa_auth_sta_deinit(sta->wpa_sm);
118 #ifdef CONFIG_WPS_REGISTRAR
119 if (ap_sta_pending_delayed_1x_auth_fail_disconnect(hapd, sta))
120 eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
121
122 ieee802_1x_free_station(hapd, sta);
123
124 wpabuf_free(sta->wps_ie);
125 #endif
126
127 os_free(sta);
128 }
129
130
hostapd_free_stas(struct hostapd_data * hapd)131 void hostapd_free_stas(struct hostapd_data *hapd)
132 {
133 struct sta_info *sta, *prev;
134
135 sta = hapd->sta_list;
136
137 while (sta) {
138 prev = sta;
139 sta = sta->next;
140 wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
141 MAC2STR(prev->addr));
142 ap_free_sta(hapd, prev);
143 }
144 }
145
146
ap_sta_add(struct hostapd_data * hapd,const u8 * addr)147 struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
148 {
149 struct sta_info *sta;
150
151 sta = ap_get_sta(hapd, addr);
152 if (sta)
153 return sta;
154
155 wpa_printf(MSG_DEBUG, " New STA");
156 if (hapd->num_sta >= hapd->conf->max_num_sta) {
157 /* FIX: might try to remove some old STAs first? */
158 wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
159 hapd->num_sta, hapd->conf->max_num_sta);
160 return NULL;
161 }
162
163 sta = os_zalloc(sizeof(struct sta_info));
164 if (sta == NULL) {
165 wpa_printf(MSG_ERROR, "malloc failed");
166 return NULL;
167 }
168
169 /* initialize STA info data */
170 os_memcpy(sta->addr, addr, ETH_ALEN);
171 sta->next = hapd->sta_list;
172 hapd->sta_list = sta;
173 hapd->num_sta++;
174 ap_sta_hash_add(hapd, sta);
175 #ifdef CONFIG_SAE
176 sta->sae_commit_processing = false;
177 sta->remove_pending = false;
178 sta->lock = os_semphr_create(1, 1);
179 #endif /* CONFIG_SAE */
180
181 return sta;
182 }
183
ap_sta_delayed_1x_auth_fail_cb(void * eloop_ctx,void * timeout_ctx)184 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
185 {
186 struct sta_info *sta = timeout_ctx;
187 u16 reason;
188
189 wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
190 "IEEE 802.1X: Scheduled disconnection of " MACSTR
191 " after EAP-Failure", MAC2STR(sta->addr));
192
193 reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
194 esp_wifi_ap_deauth_internal(sta->addr, reason);
195 }
196
197
ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data * hapd,struct sta_info * sta)198 void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
199 struct sta_info *sta)
200 {
201 wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
202 "IEEE 802.1X: Force disconnection of " MACSTR
203 " after EAP-Failure in 10 ms", MAC2STR(sta->addr));
204
205 /*
206 * Add a small sleep to increase likelihood of previously requested
207 * EAP-Failure TX getting out before this should the driver reorder
208 * operations.
209 */
210 eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
211 eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
212 hapd, sta);
213 if (wps_get_status() == WPS_STATUS_PENDING)
214 wps_set_status(WPS_STATUS_SUCCESS);
215 }
216
217
ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data * hapd,struct sta_info * sta)218 int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
219 struct sta_info *sta)
220 {
221 return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb,
222 hapd, sta);
223 }
224