Branch data Line data Source code
1 : : /*
2 : : * hostapd / IEEE 802.11 Management
3 : : * Copyright (c) 2002-2013, 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 : : #ifndef CONFIG_NATIVE_WINDOWS
12 : :
13 : : #include "utils/common.h"
14 : : #include "utils/eloop.h"
15 : : #include "crypto/crypto.h"
16 : : #include "crypto/sha256.h"
17 : : #include "crypto/random.h"
18 : : #include "common/ieee802_11_defs.h"
19 : : #include "common/ieee802_11_common.h"
20 : : #include "common/wpa_ctrl.h"
21 : : #include "common/sae.h"
22 : : #include "radius/radius.h"
23 : : #include "radius/radius_client.h"
24 : : #include "p2p/p2p.h"
25 : : #include "wps/wps.h"
26 : : #include "hostapd.h"
27 : : #include "beacon.h"
28 : : #include "ieee802_11_auth.h"
29 : : #include "sta_info.h"
30 : : #include "ieee802_1x.h"
31 : : #include "wpa_auth.h"
32 : : #include "wmm.h"
33 : : #include "ap_list.h"
34 : : #include "accounting.h"
35 : : #include "ap_config.h"
36 : : #include "ap_mlme.h"
37 : : #include "p2p_hostapd.h"
38 : : #include "ap_drv_ops.h"
39 : : #include "wnm_ap.h"
40 : : #include "ieee802_11.h"
41 : : #include "dfs.h"
42 : :
43 : :
44 : 2919 : u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
45 : : {
46 : 2919 : u8 *pos = eid;
47 : : int i, num, count;
48 : :
49 [ + + ]: 2919 : if (hapd->iface->current_rates == NULL)
50 : 4 : return eid;
51 : :
52 : 2915 : *pos++ = WLAN_EID_SUPP_RATES;
53 : 2915 : num = hapd->iface->num_rates;
54 [ + + ][ + + ]: 2915 : if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
55 : 3 : num++;
56 [ + + ][ - + ]: 2915 : if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
57 : 0 : num++;
58 [ + + ]: 2915 : if (num > 8) {
59 : : /* rest of the rates are encoded in Extended supported
60 : : * rates element */
61 : 1941 : num = 8;
62 : : }
63 : :
64 : 2915 : *pos++ = num;
65 : 2915 : count = 0;
66 [ + + ][ + + ]: 26231 : for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
67 : 23316 : i++) {
68 : 23316 : count++;
69 : 23316 : *pos = hapd->iface->current_rates[i].rate / 5;
70 [ + + ]: 23316 : if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
71 : 10685 : *pos |= 0x80;
72 : 23316 : pos++;
73 : : }
74 : :
75 [ + + ][ + + ]: 2915 : if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
[ - + ]
76 : 0 : count++;
77 : 0 : *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
78 : : }
79 : :
80 [ + + ][ - + ]: 2915 : if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
[ # # ]
81 : 0 : count++;
82 : 0 : *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
83 : : }
84 : :
85 : 2919 : return pos;
86 : : }
87 : :
88 : :
89 : 2919 : u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
90 : : {
91 : 2919 : u8 *pos = eid;
92 : : int i, num, count;
93 : :
94 [ + + ]: 2919 : if (hapd->iface->current_rates == NULL)
95 : 4 : return eid;
96 : :
97 : 2915 : num = hapd->iface->num_rates;
98 [ + + ][ + + ]: 2915 : if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
99 : 3 : num++;
100 [ + + ][ - + ]: 2915 : if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
101 : 0 : num++;
102 [ + + ]: 2915 : if (num <= 8)
103 : 974 : return eid;
104 : 1941 : num -= 8;
105 : :
106 : 1941 : *pos++ = WLAN_EID_EXT_SUPP_RATES;
107 : 1941 : *pos++ = num;
108 : 1941 : count = 0;
109 [ + + ][ + - ]: 25233 : for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
110 : 23292 : i++) {
111 : 23292 : count++;
112 [ + + ]: 23292 : if (count <= 8)
113 : 15528 : continue; /* already in SuppRates IE */
114 : 7764 : *pos = hapd->iface->current_rates[i].rate / 5;
115 [ - + ]: 7764 : if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
116 : 0 : *pos |= 0x80;
117 : 7764 : pos++;
118 : : }
119 : :
120 [ + - ][ + + ]: 1941 : if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
121 : 3 : count++;
122 [ + - ]: 3 : if (count > 8)
123 : 3 : *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
124 : : }
125 : :
126 [ - + ][ # # ]: 1941 : if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
127 : 0 : count++;
128 [ # # ]: 0 : if (count > 8)
129 : 0 : *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
130 : : }
131 : :
132 : 2919 : return pos;
133 : : }
134 : :
135 : :
136 : 2919 : u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
137 : : int probe)
138 : : {
139 : 2919 : int capab = WLAN_CAPABILITY_ESS;
140 : : int privacy;
141 : : int dfs;
142 : :
143 : : /* Check if any of configured channels require DFS */
144 : 2919 : dfs = hostapd_is_dfs_required(hapd->iface);
145 [ + + ]: 2919 : if (dfs < 0) {
146 : 1 : wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
147 : : dfs);
148 : 1 : dfs = 0;
149 : : }
150 : :
151 [ + - ][ - + ]: 2919 : if (hapd->iface->num_sta_no_short_preamble == 0 &&
152 : 2919 : hapd->iconf->preamble == SHORT_PREAMBLE)
153 : 0 : capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
154 : :
155 : 2919 : privacy = hapd->conf->ssid.wep.keys_set;
156 : :
157 [ + + ][ + + ]: 2919 : if (hapd->conf->ieee802_1x &&
158 [ - + ]: 614 : (hapd->conf->default_wep_key_len ||
159 : 614 : hapd->conf->individual_wep_key_len))
160 : 6 : privacy = 1;
161 : :
162 [ + + ]: 2919 : if (hapd->conf->wpa)
163 : 2235 : privacy = 1;
164 : :
165 : : #ifdef CONFIG_HS20
166 [ + + ]: 2919 : if (hapd->conf->osen)
167 : 3 : privacy = 1;
168 : : #endif /* CONFIG_HS20 */
169 : :
170 [ + + ]: 2919 : if (sta) {
171 : : int policy, def_klen;
172 [ + + ][ + - ]: 754 : if (probe && sta->ssid_probe) {
173 : 80 : policy = sta->ssid_probe->security_policy;
174 : 80 : def_klen = sta->ssid_probe->wep.default_len;
175 : : } else {
176 : 674 : policy = sta->ssid->security_policy;
177 : 674 : def_klen = sta->ssid->wep.default_len;
178 : : }
179 : 754 : privacy = policy != SECURITY_PLAINTEXT;
180 [ + + ][ + + ]: 754 : if (policy == SECURITY_IEEE_802_1X && def_klen == 0)
181 : 2 : privacy = 0;
182 : : }
183 : :
184 [ + + ]: 2919 : if (privacy)
185 : 2256 : capab |= WLAN_CAPABILITY_PRIVACY;
186 : :
187 [ + + ][ + + ]: 2919 : if (hapd->iface->current_mode &&
188 [ + - ]: 2917 : hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
189 : 2917 : hapd->iface->num_sta_no_short_slot_time == 0)
190 : 2917 : capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
191 : :
192 : : /*
193 : : * Currently, Spectrum Management capability bit is set when directly
194 : : * requested in configuration by spectrum_mgmt_required or when AP is
195 : : * running on DFS channel.
196 : : * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
197 : : */
198 [ + + ][ - + ]: 2919 : if (hapd->iface->current_mode &&
199 [ # # ]: 0 : hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
200 [ # # ]: 0 : (hapd->iconf->spectrum_mgmt_required || dfs))
201 : 0 : capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
202 : :
203 : 2919 : return capab;
204 : : }
205 : :
206 : :
207 : 4 : static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
208 : : u16 auth_transaction, const u8 *challenge,
209 : : int iswep)
210 : : {
211 : 4 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
212 : : HOSTAPD_LEVEL_DEBUG,
213 : : "authentication (shared key, transaction %d)",
214 : : auth_transaction);
215 : :
216 [ + + ]: 4 : if (auth_transaction == 1) {
217 [ + - ]: 2 : if (!sta->challenge) {
218 : : /* Generate a pseudo-random challenge */
219 : : u8 key[8];
220 : : struct os_time now;
221 : : int r;
222 : 2 : sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
223 [ - + ]: 2 : if (sta->challenge == NULL)
224 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
225 : :
226 : 2 : os_get_time(&now);
227 : 2 : r = os_random();
228 : 2 : os_memcpy(key, &now.sec, 4);
229 : 2 : os_memcpy(key + 4, &r, 4);
230 : 2 : rc4_skip(key, sizeof(key), 0,
231 : : sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
232 : : }
233 : 2 : return 0;
234 : : }
235 : :
236 [ - + ]: 2 : if (auth_transaction != 3)
237 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
238 : :
239 : : /* Transaction 3 */
240 [ + - ][ + - ]: 2 : if (!iswep || !sta->challenge || !challenge ||
[ + - ][ - + ]
241 : 2 : os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
242 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
243 : : HOSTAPD_LEVEL_INFO,
244 : : "shared key authentication - invalid "
245 : : "challenge-response");
246 : 0 : return WLAN_STATUS_CHALLENGE_FAIL;
247 : : }
248 : :
249 : 2 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
250 : : HOSTAPD_LEVEL_DEBUG,
251 : : "authentication OK (shared key)");
252 : 2 : sta->flags |= WLAN_STA_AUTH;
253 : 2 : wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
254 : 2 : os_free(sta->challenge);
255 : 2 : sta->challenge = NULL;
256 : :
257 : 4 : return 0;
258 : : }
259 : :
260 : :
261 : 695 : static void send_auth_reply(struct hostapd_data *hapd,
262 : : const u8 *dst, const u8 *bssid,
263 : : u16 auth_alg, u16 auth_transaction, u16 resp,
264 : : const u8 *ies, size_t ies_len)
265 : : {
266 : : struct ieee80211_mgmt *reply;
267 : : u8 *buf;
268 : : size_t rlen;
269 : :
270 : 695 : rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
271 : 695 : buf = os_zalloc(rlen);
272 [ - + ]: 695 : if (buf == NULL)
273 : 695 : return;
274 : :
275 : 695 : reply = (struct ieee80211_mgmt *) buf;
276 : 695 : reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
277 : : WLAN_FC_STYPE_AUTH);
278 : 695 : os_memcpy(reply->da, dst, ETH_ALEN);
279 : 695 : os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
280 : 695 : os_memcpy(reply->bssid, bssid, ETH_ALEN);
281 : :
282 : 695 : reply->u.auth.auth_alg = host_to_le16(auth_alg);
283 : 695 : reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
284 : 695 : reply->u.auth.status_code = host_to_le16(resp);
285 : :
286 [ + - ][ + + ]: 695 : if (ies && ies_len)
287 : 45 : os_memcpy(reply->u.auth.variable, ies, ies_len);
288 : :
289 : 695 : wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
290 : : " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
291 : 4170 : MAC2STR(dst), auth_alg, auth_transaction,
292 : : resp, (unsigned long) ies_len);
293 [ - + ]: 695 : if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
294 : 0 : wpa_printf(MSG_INFO, "send_auth_reply: send");
295 : :
296 : 695 : os_free(buf);
297 : : }
298 : :
299 : :
300 : : #ifdef CONFIG_IEEE80211R
301 : 10 : static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
302 : : u16 auth_transaction, u16 status,
303 : : const u8 *ies, size_t ies_len)
304 : : {
305 : 10 : struct hostapd_data *hapd = ctx;
306 : : struct sta_info *sta;
307 : :
308 : 10 : send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction,
309 : : status, ies, ies_len);
310 : :
311 [ - + ]: 10 : if (status != WLAN_STATUS_SUCCESS)
312 : 0 : return;
313 : :
314 : 10 : sta = ap_get_sta(hapd, dst);
315 [ - + ]: 10 : if (sta == NULL)
316 : 0 : return;
317 : :
318 : 10 : hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
319 : : HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
320 : 10 : sta->flags |= WLAN_STA_AUTH;
321 : 10 : mlme_authenticate_indication(hapd, sta);
322 : : }
323 : : #endif /* CONFIG_IEEE80211R */
324 : :
325 : :
326 : : #ifdef CONFIG_SAE
327 : :
328 : 16 : static struct wpabuf * auth_process_sae_commit(struct hostapd_data *hapd,
329 : : struct sta_info *sta)
330 : : {
331 : : struct wpabuf *buf;
332 : :
333 [ - + ]: 16 : if (hapd->conf->ssid.wpa_passphrase == NULL) {
334 : 0 : wpa_printf(MSG_DEBUG, "SAE: No password available");
335 : 0 : return NULL;
336 : : }
337 : :
338 [ - + ]: 16 : if (sae_prepare_commit(hapd->own_addr, sta->addr,
339 : 16 : (u8 *) hapd->conf->ssid.wpa_passphrase,
340 : 16 : os_strlen(hapd->conf->ssid.wpa_passphrase),
341 : : sta->sae) < 0) {
342 : 0 : wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
343 : 0 : return NULL;
344 : : }
345 : :
346 [ - + ]: 16 : if (sae_process_commit(sta->sae) < 0) {
347 : 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
348 : 0 : return NULL;
349 : : }
350 : :
351 : 16 : buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
352 [ - + ]: 16 : if (buf == NULL)
353 : 0 : return NULL;
354 : 16 : sae_write_commit(sta->sae, buf, NULL);
355 : :
356 : 16 : return buf;
357 : : }
358 : :
359 : :
360 : 16 : static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
361 : : struct sta_info *sta)
362 : : {
363 : : struct wpabuf *buf;
364 : :
365 : 16 : buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
366 [ - + ]: 16 : if (buf == NULL)
367 : 0 : return NULL;
368 : :
369 : 16 : sae_write_confirm(sta->sae, buf);
370 : :
371 : 16 : return buf;
372 : : }
373 : :
374 : :
375 : 16 : static int use_sae_anti_clogging(struct hostapd_data *hapd)
376 : : {
377 : : struct sta_info *sta;
378 : 16 : unsigned int open = 0;
379 : :
380 [ - + ]: 16 : if (hapd->conf->sae_anti_clogging_threshold == 0)
381 : 0 : return 1;
382 : :
383 [ + + ]: 32 : for (sta = hapd->sta_list; sta; sta = sta->next) {
384 [ - + ]: 17 : if (!sta->sae)
385 : 0 : continue;
386 [ + + ][ + - ]: 17 : if (sta->sae->state != SAE_COMMITTED &&
387 : 16 : sta->sae->state != SAE_CONFIRMED)
388 : 16 : continue;
389 : 1 : open++;
390 [ + - ]: 1 : if (open >= hapd->conf->sae_anti_clogging_threshold)
391 : 1 : return 1;
392 : : }
393 : :
394 : 16 : return 0;
395 : : }
396 : :
397 : :
398 : 1 : static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
399 : : const u8 *token, size_t token_len)
400 : : {
401 : : u8 mac[SHA256_MAC_LEN];
402 : :
403 [ - + ]: 1 : if (token_len != SHA256_MAC_LEN)
404 : 0 : return -1;
405 [ + - ]: 1 : if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
406 [ - + ]: 1 : addr, ETH_ALEN, mac) < 0 ||
407 : 1 : os_memcmp(token, mac, SHA256_MAC_LEN) != 0)
408 : 0 : return -1;
409 : :
410 : 1 : return 0;
411 : : }
412 : :
413 : :
414 : 1 : static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
415 : : const u8 *addr)
416 : : {
417 : : struct wpabuf *buf;
418 : : u8 *token;
419 : : struct os_reltime now;
420 : :
421 : 1 : os_get_reltime(&now);
422 [ - + # # ]: 1 : if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
423 : 0 : os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
424 [ - + ]: 1 : if (random_get_bytes(hapd->sae_token_key,
425 : : sizeof(hapd->sae_token_key)) < 0)
426 : 0 : return NULL;
427 : 1 : wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
428 : 1 : hapd->sae_token_key, sizeof(hapd->sae_token_key));
429 : 1 : hapd->last_sae_token_key_update = now;
430 : : }
431 : :
432 : 1 : buf = wpabuf_alloc(SHA256_MAC_LEN);
433 [ - + ]: 1 : if (buf == NULL)
434 : 0 : return NULL;
435 : :
436 : 1 : token = wpabuf_put(buf, SHA256_MAC_LEN);
437 : 1 : hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
438 : : addr, ETH_ALEN, token);
439 : :
440 : 1 : return buf;
441 : : }
442 : :
443 : :
444 : 36 : static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
445 : : const struct ieee80211_mgmt *mgmt, size_t len,
446 : : u8 auth_transaction)
447 : : {
448 : 36 : u16 resp = WLAN_STATUS_SUCCESS;
449 : 36 : struct wpabuf *data = NULL;
450 : :
451 [ + + ]: 36 : if (!sta->sae) {
452 [ - + ]: 16 : if (auth_transaction != 1)
453 : 0 : return;
454 : 16 : sta->sae = os_zalloc(sizeof(*sta->sae));
455 [ - + ]: 16 : if (sta->sae == NULL)
456 : 0 : return;
457 : 16 : sta->sae->state = SAE_NOTHING;
458 : : }
459 : :
460 [ + + ]: 36 : if (auth_transaction == 1) {
461 : 20 : const u8 *token = NULL;
462 : 20 : size_t token_len = 0;
463 : 20 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
464 : : HOSTAPD_LEVEL_DEBUG,
465 : : "start SAE authentication (RX commit)");
466 : 20 : resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
467 : 20 : ((const u8 *) mgmt) + len -
468 : : mgmt->u.auth.variable, &token,
469 : 20 : &token_len, hapd->conf->sae_groups);
470 [ - + ][ + + ]: 20 : if (token && check_sae_token(hapd, sta->addr, token, token_len)
471 : : < 0) {
472 : 0 : wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
473 : : "incorrect token from " MACSTR,
474 : 0 : MAC2STR(sta->addr));
475 : 0 : return;
476 : : }
477 : :
478 [ + + ]: 20 : if (resp == WLAN_STATUS_SUCCESS) {
479 [ + + ][ + + ]: 17 : if (!token && use_sae_anti_clogging(hapd)) {
480 : 1 : wpa_printf(MSG_DEBUG, "SAE: Request anti-"
481 : : "clogging token from " MACSTR,
482 : 6 : MAC2STR(sta->addr));
483 : 1 : data = auth_build_token_req(hapd, sta->addr);
484 : 1 : resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
485 : : } else {
486 : 16 : data = auth_process_sae_commit(hapd, sta);
487 [ - + ]: 16 : if (data == NULL)
488 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
489 : : else
490 : 20 : sta->sae->state = SAE_COMMITTED;
491 : : }
492 : : }
493 [ + - ]: 16 : } else if (auth_transaction == 2) {
494 [ - + ]: 16 : if (sta->sae->state != SAE_COMMITTED) {
495 : 0 : hostapd_logger(hapd, sta->addr,
496 : : HOSTAPD_MODULE_IEEE80211,
497 : : HOSTAPD_LEVEL_DEBUG,
498 : : "SAE confirm before commit");
499 : 0 : resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
500 : 0 : goto failed;
501 : : }
502 : 16 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
503 : : HOSTAPD_LEVEL_DEBUG,
504 : : "SAE authentication (RX confirm)");
505 [ - + ]: 16 : if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
506 : 16 : ((u8 *) mgmt) + len -
507 : : mgmt->u.auth.variable) < 0) {
508 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
509 : : } else {
510 : 16 : resp = WLAN_STATUS_SUCCESS;
511 : 16 : sta->flags |= WLAN_STA_AUTH;
512 : 16 : wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
513 : 16 : sta->auth_alg = WLAN_AUTH_SAE;
514 : 16 : mlme_authenticate_indication(hapd, sta);
515 : :
516 : 16 : data = auth_build_sae_confirm(hapd, sta);
517 [ - + ]: 16 : if (data == NULL)
518 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
519 : : else {
520 : 16 : sta->sae->state = SAE_ACCEPTED;
521 : 16 : sae_clear_temp_data(sta->sae);
522 : : }
523 : : }
524 : : } else {
525 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
526 : : HOSTAPD_LEVEL_DEBUG,
527 : : "unexpected SAE authentication transaction %u",
528 : : auth_transaction);
529 : 0 : resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
530 : : }
531 : :
532 : : failed:
533 : 36 : sta->auth_alg = WLAN_AUTH_SAE;
534 : :
535 [ + + ][ + + ]: 36 : send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
536 : : auth_transaction, resp,
537 : : data ? wpabuf_head(data) : (u8 *) "",
538 : : data ? wpabuf_len(data) : 0);
539 : 36 : wpabuf_free(data);
540 : : }
541 : : #endif /* CONFIG_SAE */
542 : :
543 : :
544 : 695 : static void handle_auth(struct hostapd_data *hapd,
545 : : const struct ieee80211_mgmt *mgmt, size_t len)
546 : : {
547 : : u16 auth_alg, auth_transaction, status_code;
548 : 695 : u16 resp = WLAN_STATUS_SUCCESS;
549 : 695 : struct sta_info *sta = NULL;
550 : : int res;
551 : : u16 fc;
552 : 695 : const u8 *challenge = NULL;
553 : : u32 session_timeout, acct_interim_interval;
554 : 695 : int vlan_id = 0;
555 : 695 : struct hostapd_sta_wpa_psk_short *psk = NULL;
556 : : u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
557 : 695 : size_t resp_ies_len = 0;
558 : 695 : char *identity = NULL;
559 : 695 : char *radius_cui = NULL;
560 : :
561 [ - + ]: 695 : if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
562 : 0 : wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
563 : : (unsigned long) len);
564 : 0 : return;
565 : : }
566 : :
567 : : #ifdef CONFIG_TESTING_OPTIONS
568 [ - + # # ]: 695 : if (hapd->iconf->ignore_auth_probability > 0.0d &&
569 : 0 : drand48() < hapd->iconf->ignore_auth_probability) {
570 : 0 : wpa_printf(MSG_INFO,
571 : : "TESTING: ignoring auth frame from " MACSTR,
572 : 0 : MAC2STR(mgmt->sa));
573 : 0 : return;
574 : : }
575 : : #endif /* CONFIG_TESTING_OPTIONS */
576 : :
577 : 695 : auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
578 : 695 : auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
579 : 695 : status_code = le_to_host16(mgmt->u.auth.status_code);
580 : 695 : fc = le_to_host16(mgmt->frame_control);
581 : :
582 [ + + ]: 695 : if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
583 [ + + ]: 21 : 2 + WLAN_AUTH_CHALLENGE_LEN &&
584 [ + - ]: 2 : mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
585 : 2 : mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
586 : 2 : challenge = &mgmt->u.auth.variable[2];
587 : :
588 [ + + ]: 695 : wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
589 : : "auth_transaction=%d status_code=%d wep=%d%s",
590 : 4170 : MAC2STR(mgmt->sa), auth_alg, auth_transaction,
591 : 695 : status_code, !!(fc & WLAN_FC_ISWEP),
592 : : challenge ? " challenge" : "");
593 : :
594 [ - + ]: 695 : if (hapd->tkip_countermeasures) {
595 : 0 : resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
596 : 0 : goto fail;
597 : : }
598 : :
599 [ + + ][ + + ]: 704 : if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
[ + + ]
600 [ + + ]: 55 : auth_alg == WLAN_AUTH_OPEN) ||
601 : : #ifdef CONFIG_IEEE80211R
602 [ + + ][ + + ]: 46 : (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
603 [ + + ]: 45 : auth_alg == WLAN_AUTH_FT) ||
604 : : #endif /* CONFIG_IEEE80211R */
605 : : #ifdef CONFIG_SAE
606 [ + - ][ - + ]: 36 : (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
607 : : auth_alg == WLAN_AUTH_SAE) ||
608 : : #endif /* CONFIG_SAE */
609 [ + + ]: 5 : ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
610 : : auth_alg == WLAN_AUTH_SHARED_KEY))) {
611 : 5 : wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
612 : : auth_alg);
613 : 5 : resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
614 : 5 : goto fail;
615 : : }
616 : :
617 [ + + ][ + + ]: 690 : if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
[ + - ]
618 [ - + ]: 2 : (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
619 : 0 : wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
620 : : auth_transaction);
621 : 0 : resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
622 : 0 : goto fail;
623 : : }
624 : :
625 [ - + ]: 690 : if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
626 : 0 : wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
627 : 0 : MAC2STR(mgmt->sa));
628 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
629 : 0 : goto fail;
630 : : }
631 : :
632 : 690 : res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
633 : : &session_timeout,
634 : : &acct_interim_interval, &vlan_id,
635 : : &psk, &identity, &radius_cui);
636 : :
637 [ - + ]: 690 : if (res == HOSTAPD_ACL_REJECT) {
638 : 0 : wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
639 : 0 : MAC2STR(mgmt->sa));
640 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
641 : 0 : goto fail;
642 : : }
643 [ - + ]: 690 : if (res == HOSTAPD_ACL_PENDING) {
644 : 0 : wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
645 : : " waiting for an external authentication",
646 : 0 : MAC2STR(mgmt->sa));
647 : : /* Authentication code will re-send the authentication frame
648 : : * after it has received (and cached) information from the
649 : : * external source. */
650 : 0 : return;
651 : : }
652 : :
653 : 690 : sta = ap_sta_add(hapd, mgmt->sa);
654 [ - + ]: 690 : if (!sta) {
655 : 0 : resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
656 : 0 : goto fail;
657 : : }
658 : :
659 [ - + ]: 690 : if (vlan_id > 0) {
660 [ # # ]: 0 : if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
661 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
662 : : HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
663 : : "%d received from RADIUS server",
664 : : vlan_id);
665 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
666 : 0 : goto fail;
667 : : }
668 : 0 : sta->vlan_id = vlan_id;
669 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
670 : : HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
671 : : }
672 : :
673 : 690 : hostapd_free_psk_list(sta->psk);
674 [ - + ]: 690 : if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
675 : 0 : sta->psk = psk;
676 : 0 : psk = NULL;
677 : : } else {
678 : 690 : sta->psk = NULL;
679 : : }
680 : :
681 : 690 : sta->identity = identity;
682 : 690 : identity = NULL;
683 : 690 : sta->radius_cui = radius_cui;
684 : 690 : radius_cui = NULL;
685 : :
686 : 690 : sta->flags &= ~WLAN_STA_PREAUTH;
687 : 690 : ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
688 : :
689 [ - + ][ + - ]: 690 : if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
690 : 0 : sta->acct_interim_interval = acct_interim_interval;
691 [ - + ]: 690 : if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
692 : 0 : ap_sta_session_timeout(hapd, sta, session_timeout);
693 : : else
694 : 690 : ap_sta_no_session_timeout(hapd, sta);
695 : :
696 [ + + + + : 690 : switch (auth_alg) {
- ]
697 : : case WLAN_AUTH_OPEN:
698 : 640 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
699 : : HOSTAPD_LEVEL_DEBUG,
700 : : "authentication OK (open system)");
701 : 640 : sta->flags |= WLAN_STA_AUTH;
702 : 640 : wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
703 : 640 : sta->auth_alg = WLAN_AUTH_OPEN;
704 : 640 : mlme_authenticate_indication(hapd, sta);
705 : 640 : break;
706 : : case WLAN_AUTH_SHARED_KEY:
707 : 4 : resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
708 : : fc & WLAN_FC_ISWEP);
709 : 4 : sta->auth_alg = WLAN_AUTH_SHARED_KEY;
710 : 4 : mlme_authenticate_indication(hapd, sta);
711 [ + - ][ + + ]: 4 : if (sta->challenge && auth_transaction == 1) {
712 : 2 : resp_ies[0] = WLAN_EID_CHALLENGE;
713 : 2 : resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
714 : 2 : os_memcpy(resp_ies + 2, sta->challenge,
715 : : WLAN_AUTH_CHALLENGE_LEN);
716 : 2 : resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
717 : : }
718 : 4 : break;
719 : : #ifdef CONFIG_IEEE80211R
720 : : case WLAN_AUTH_FT:
721 : 10 : sta->auth_alg = WLAN_AUTH_FT;
722 [ + + ]: 10 : if (sta->wpa_sm == NULL)
723 : 5 : sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
724 : 5 : sta->addr, NULL);
725 [ - + ]: 10 : if (sta->wpa_sm == NULL) {
726 : 0 : wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
727 : : "state machine");
728 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
729 : 0 : goto fail;
730 : : }
731 : 10 : wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
732 : 10 : auth_transaction, mgmt->u.auth.variable,
733 : : len - IEEE80211_HDRLEN -
734 : : sizeof(mgmt->u.auth),
735 : : handle_auth_ft_finish, hapd);
736 : : /* handle_auth_ft_finish() callback will complete auth. */
737 : 10 : return;
738 : : #endif /* CONFIG_IEEE80211R */
739 : : #ifdef CONFIG_SAE
740 : : case WLAN_AUTH_SAE:
741 : 36 : handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
742 : 36 : return;
743 : : #endif /* CONFIG_SAE */
744 : : }
745 : :
746 : : fail:
747 : 649 : os_free(identity);
748 : 649 : os_free(radius_cui);
749 : 649 : hostapd_free_psk_list(psk);
750 : :
751 : 695 : send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
752 : : auth_transaction + 1, resp, resp_ies, resp_ies_len);
753 : : }
754 : :
755 : :
756 : 674 : static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
757 : : {
758 : 674 : int i, j = 32, aid;
759 : :
760 : : /* get a unique AID */
761 [ + + ]: 674 : if (sta->aid > 0) {
762 : 28 : wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
763 : 28 : return 0;
764 : : }
765 : :
766 [ + - ]: 646 : for (i = 0; i < AID_WORDS; i++) {
767 [ - + ]: 646 : if (hapd->sta_aid[i] == (u32) -1)
768 : 0 : continue;
769 [ + - ]: 732 : for (j = 0; j < 32; j++) {
770 [ + + ]: 732 : if (!(hapd->sta_aid[i] & BIT(j)))
771 : 646 : break;
772 : : }
773 [ + - ]: 646 : if (j < 32)
774 : 646 : break;
775 : : }
776 [ - + ]: 646 : if (j == 32)
777 : 0 : return -1;
778 : 646 : aid = i * 32 + j + 1;
779 [ - + ]: 646 : if (aid > 2007)
780 : 0 : return -1;
781 : :
782 : 646 : sta->aid = aid;
783 : 646 : hapd->sta_aid[i] |= BIT(j);
784 : 646 : wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
785 : 674 : return 0;
786 : : }
787 : :
788 : :
789 : 674 : static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
790 : : const u8 *ssid_ie, size_t ssid_ie_len)
791 : : {
792 [ - + ]: 674 : if (ssid_ie == NULL)
793 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
794 : :
795 [ + - ][ - + ]: 674 : if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
796 : 674 : os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
797 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
798 : : HOSTAPD_LEVEL_INFO,
799 : : "Station tried to associate with unknown SSID "
800 : : "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
801 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
802 : : }
803 : :
804 : 674 : return WLAN_STATUS_SUCCESS;
805 : : }
806 : :
807 : :
808 : 674 : static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
809 : : const u8 *wmm_ie, size_t wmm_ie_len)
810 : : {
811 : 674 : sta->flags &= ~WLAN_STA_WMM;
812 : 674 : sta->qosinfo = 0;
813 [ + - ][ + - ]: 674 : if (wmm_ie && hapd->conf->wmm_enabled) {
814 : : struct wmm_information_element *wmm;
815 : :
816 [ - + ]: 674 : if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
817 : 0 : hostapd_logger(hapd, sta->addr,
818 : : HOSTAPD_MODULE_WPA,
819 : : HOSTAPD_LEVEL_DEBUG,
820 : : "invalid WMM element in association "
821 : : "request");
822 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
823 : : }
824 : :
825 : 674 : sta->flags |= WLAN_STA_WMM;
826 : 674 : wmm = (struct wmm_information_element *) wmm_ie;
827 : 674 : sta->qosinfo = wmm->qos_info;
828 : : }
829 : 674 : return WLAN_STATUS_SUCCESS;
830 : : }
831 : :
832 : :
833 : 674 : static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
834 : : struct ieee802_11_elems *elems)
835 : : {
836 [ - + ]: 674 : if (!elems->supp_rates) {
837 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
838 : : HOSTAPD_LEVEL_DEBUG,
839 : : "No supported rates element in AssocReq");
840 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
841 : : }
842 : :
843 [ - + ]: 674 : if (elems->supp_rates_len + elems->ext_supp_rates_len >
844 : : sizeof(sta->supported_rates)) {
845 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
846 : : HOSTAPD_LEVEL_DEBUG,
847 : : "Invalid supported rates element length %d+%d",
848 : 0 : elems->supp_rates_len,
849 : 0 : elems->ext_supp_rates_len);
850 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
851 : : }
852 : :
853 : 674 : sta->supported_rates_len = merge_byte_arrays(
854 : 674 : sta->supported_rates, sizeof(sta->supported_rates),
855 : 674 : elems->supp_rates, elems->supp_rates_len,
856 : 674 : elems->ext_supp_rates, elems->ext_supp_rates_len);
857 : :
858 : 674 : return WLAN_STATUS_SUCCESS;
859 : : }
860 : :
861 : :
862 : 674 : static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
863 : : const u8 *ext_capab_ie, size_t ext_capab_ie_len)
864 : : {
865 : : #ifdef CONFIG_INTERWORKING
866 : : /* check for QoS Map support */
867 [ + + ]: 674 : if (ext_capab_ie_len >= 5) {
868 [ + - ]: 658 : if (ext_capab_ie[4] & 0x01)
869 : 658 : sta->qos_map_enabled = 1;
870 : : }
871 : : #endif /* CONFIG_INTERWORKING */
872 : :
873 : 674 : return WLAN_STATUS_SUCCESS;
874 : : }
875 : :
876 : :
877 : 674 : static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
878 : : const u8 *ies, size_t ies_len, int reassoc)
879 : : {
880 : : struct ieee802_11_elems elems;
881 : : u16 resp;
882 : : const u8 *wpa_ie;
883 : : size_t wpa_ie_len;
884 : 674 : const u8 *p2p_dev_addr = NULL;
885 : :
886 [ - + ]: 674 : if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
887 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
888 : : HOSTAPD_LEVEL_INFO, "Station sent an invalid "
889 : : "association request");
890 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
891 : : }
892 : :
893 : 674 : resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
894 [ - + ]: 674 : if (resp != WLAN_STATUS_SUCCESS)
895 : 0 : return resp;
896 : 674 : resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
897 [ - + ]: 674 : if (resp != WLAN_STATUS_SUCCESS)
898 : 0 : return resp;
899 : 674 : resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
900 [ - + ]: 674 : if (resp != WLAN_STATUS_SUCCESS)
901 : 0 : return resp;
902 : 674 : resp = copy_supp_rates(hapd, sta, &elems);
903 [ - + ]: 674 : if (resp != WLAN_STATUS_SUCCESS)
904 : 0 : return resp;
905 : : #ifdef CONFIG_IEEE80211N
906 : 674 : resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities,
907 : 674 : elems.ht_capabilities_len);
908 [ - + ]: 674 : if (resp != WLAN_STATUS_SUCCESS)
909 : 0 : return resp;
910 [ + - ][ + + ]: 674 : if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
[ - + ]
911 : 1 : !(sta->flags & WLAN_STA_HT)) {
912 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
913 : : HOSTAPD_LEVEL_INFO, "Station does not support "
914 : : "mandatory HT PHY - reject association");
915 : 0 : return WLAN_STATUS_ASSOC_DENIED_NO_HT;
916 : : }
917 : : #endif /* CONFIG_IEEE80211N */
918 : :
919 : : #ifdef CONFIG_IEEE80211AC
920 : 481 : resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities,
921 : 481 : elems.vht_capabilities_len);
922 [ - + ]: 481 : if (resp != WLAN_STATUS_SUCCESS)
923 : 0 : return resp;
924 : :
925 : 481 : resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
926 [ - + ]: 481 : if (resp != WLAN_STATUS_SUCCESS)
927 : 0 : return resp;
928 : :
929 [ - + ][ # # ]: 481 : if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
[ # # ]
930 : 0 : !(sta->flags & WLAN_STA_VHT)) {
931 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
932 : : HOSTAPD_LEVEL_INFO, "Station does not support "
933 : : "mandatory VHT PHY - reject association");
934 : 0 : return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
935 : : }
936 : : #endif /* CONFIG_IEEE80211AC */
937 : :
938 : : #ifdef CONFIG_P2P
939 [ + + ]: 193 : if (elems.p2p) {
940 : 172 : wpabuf_free(sta->p2p_ie);
941 : 172 : sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
942 : : P2P_IE_VENDOR_TYPE);
943 [ + - ]: 172 : if (sta->p2p_ie)
944 : 172 : p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
945 : : } else {
946 : 21 : wpabuf_free(sta->p2p_ie);
947 : 21 : sta->p2p_ie = NULL;
948 : : }
949 : : #endif /* CONFIG_P2P */
950 : :
951 [ + + ][ + + ]: 674 : if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
952 : 419 : wpa_ie = elems.rsn_ie;
953 : 419 : wpa_ie_len = elems.rsn_ie_len;
954 [ + + ][ + + ]: 255 : } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
955 : 15 : elems.wpa_ie) {
956 : 7 : wpa_ie = elems.wpa_ie;
957 : 7 : wpa_ie_len = elems.wpa_ie_len;
958 : : } else {
959 : 248 : wpa_ie = NULL;
960 : 248 : wpa_ie_len = 0;
961 : : }
962 : :
963 : : #ifdef CONFIG_WPS
964 : 674 : sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
965 [ + + ][ + + ]: 674 : if (hapd->conf->wps_state && elems.wps_ie) {
966 : 144 : wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
967 : : "Request - assume WPS is used");
968 : 144 : sta->flags |= WLAN_STA_WPS;
969 : 144 : wpabuf_free(sta->wps_ie);
970 : 144 : sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
971 : : WPS_IE_VENDOR_TYPE);
972 [ + + ][ + - ]: 144 : if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
973 : 142 : wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
974 : 142 : sta->flags |= WLAN_STA_WPS2;
975 : : }
976 : 144 : wpa_ie = NULL;
977 : 144 : wpa_ie_len = 0;
978 [ + - ][ - + ]: 144 : if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
979 : 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
980 : : "(Re)Association Request - reject");
981 : 0 : return WLAN_STATUS_INVALID_IE;
982 : : }
983 [ + + ][ + + ]: 530 : } else if (hapd->conf->wps_state && wpa_ie == NULL) {
984 : 6 : wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
985 : : "(Re)Association Request - possible WPS use");
986 : 6 : sta->flags |= WLAN_STA_MAYBE_WPS;
987 : : } else
988 : : #endif /* CONFIG_WPS */
989 [ + + ][ - + ]: 524 : if (hapd->conf->wpa && wpa_ie == NULL) {
990 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
991 : : HOSTAPD_LEVEL_INFO,
992 : : "No WPA/RSN IE in association request");
993 : 0 : return WLAN_STATUS_INVALID_IE;
994 : : }
995 : :
996 [ + + ][ + + ]: 1100 : if (hapd->conf->wpa && wpa_ie) {
997 : : int res;
998 : 426 : wpa_ie -= 2;
999 : 426 : wpa_ie_len += 2;
1000 [ + + ]: 426 : if (sta->wpa_sm == NULL)
1001 : 395 : sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
1002 : 395 : sta->addr,
1003 : : p2p_dev_addr);
1004 [ - + ]: 426 : if (sta->wpa_sm == NULL) {
1005 : 0 : wpa_printf(MSG_WARNING, "Failed to initialize WPA "
1006 : : "state machine");
1007 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
1008 : : }
1009 : 426 : res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
1010 : : wpa_ie, wpa_ie_len,
1011 : 426 : elems.mdie, elems.mdie_len);
1012 [ - + ]: 426 : if (res == WPA_INVALID_GROUP)
1013 : 0 : resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1014 [ - + ]: 426 : else if (res == WPA_INVALID_PAIRWISE)
1015 : 0 : resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1016 [ - + ]: 426 : else if (res == WPA_INVALID_AKMP)
1017 : 0 : resp = WLAN_STATUS_AKMP_NOT_VALID;
1018 [ - + ]: 426 : else if (res == WPA_ALLOC_FAIL)
1019 : 0 : resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1020 : : #ifdef CONFIG_IEEE80211W
1021 [ - + ]: 426 : else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
1022 : 0 : resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1023 [ - + ]: 426 : else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
1024 : 0 : resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1025 : : #endif /* CONFIG_IEEE80211W */
1026 [ - + ]: 426 : else if (res == WPA_INVALID_MDIE)
1027 : 0 : resp = WLAN_STATUS_INVALID_MDIE;
1028 [ - + ]: 426 : else if (res != WPA_IE_OK)
1029 : 0 : resp = WLAN_STATUS_INVALID_IE;
1030 [ - + ]: 426 : if (resp != WLAN_STATUS_SUCCESS)
1031 : 0 : return resp;
1032 : : #ifdef CONFIG_IEEE80211W
1033 [ + + ][ + - ]: 426 : if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
[ - + ]
1034 : 2 : sta->sa_query_count > 0)
1035 : 0 : ap_check_sa_query_timeout(hapd, sta);
1036 [ + + ][ + - ]: 426 : if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
[ + - ]
1037 [ - + ]: 2 : (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
1038 : : /*
1039 : : * STA has already been associated with MFP and SA
1040 : : * Query timeout has not been reached. Reject the
1041 : : * association attempt temporarily and start SA Query,
1042 : : * if one is not pending.
1043 : : */
1044 : :
1045 [ # # ]: 0 : if (sta->sa_query_count == 0)
1046 : 0 : ap_sta_start_sa_query(hapd, sta);
1047 : :
1048 : 0 : return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
1049 : : }
1050 : :
1051 [ + + ]: 426 : if (wpa_auth_uses_mfp(sta->wpa_sm))
1052 : 19 : sta->flags |= WLAN_STA_MFP;
1053 : : else
1054 : 407 : sta->flags &= ~WLAN_STA_MFP;
1055 : : #endif /* CONFIG_IEEE80211W */
1056 : :
1057 : : #ifdef CONFIG_IEEE80211R
1058 [ + + ]: 426 : if (sta->auth_alg == WLAN_AUTH_FT) {
1059 [ - + ]: 16 : if (!reassoc) {
1060 : 0 : wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
1061 : : "to use association (not "
1062 : : "re-association) with FT auth_alg",
1063 : 0 : MAC2STR(sta->addr));
1064 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
1065 : : }
1066 : :
1067 : 16 : resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
1068 : : ies_len);
1069 [ - + ]: 16 : if (resp != WLAN_STATUS_SUCCESS)
1070 : 0 : return resp;
1071 : : }
1072 : : #endif /* CONFIG_IEEE80211R */
1073 : :
1074 : : #ifdef CONFIG_SAE
1075 [ + + ][ + + ]: 426 : if (wpa_auth_uses_sae(sta->wpa_sm) &&
1076 [ + - ]: 4 : sta->auth_alg != WLAN_AUTH_SAE &&
1077 [ - + ]: 4 : !(sta->auth_alg == WLAN_AUTH_FT &&
1078 : 4 : wpa_auth_uses_ft_sae(sta->wpa_sm))) {
1079 : 0 : wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
1080 : : "SAE AKM after non-SAE auth_alg %u",
1081 : 0 : MAC2STR(sta->addr), sta->auth_alg);
1082 : 0 : return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1083 : : }
1084 : : #endif /* CONFIG_SAE */
1085 : :
1086 : : #ifdef CONFIG_IEEE80211N
1087 [ + + - + ]: 844 : if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
1088 : 418 : wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
1089 : 0 : hostapd_logger(hapd, sta->addr,
1090 : : HOSTAPD_MODULE_IEEE80211,
1091 : : HOSTAPD_LEVEL_INFO,
1092 : : "Station tried to use TKIP with HT "
1093 : : "association");
1094 : 0 : return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
1095 : : }
1096 : : #endif /* CONFIG_IEEE80211N */
1097 : : #ifdef CONFIG_HS20
1098 [ + + ]: 248 : } else if (hapd->conf->osen) {
1099 [ - + ]: 1 : if (elems.osen == NULL) {
1100 : 0 : hostapd_logger(
1101 : 0 : hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1102 : : HOSTAPD_LEVEL_INFO,
1103 : : "No HS 2.0 OSEN element in association request");
1104 : 0 : return WLAN_STATUS_INVALID_IE;
1105 : : }
1106 : :
1107 : 1 : wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
1108 [ + - ]: 1 : if (sta->wpa_sm == NULL)
1109 : 1 : sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
1110 : 1 : sta->addr, NULL);
1111 [ - + ]: 1 : if (sta->wpa_sm == NULL) {
1112 : 0 : wpa_printf(MSG_WARNING, "Failed to initialize WPA "
1113 : : "state machine");
1114 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
1115 : : }
1116 [ - + ]: 1 : if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
1117 : 2 : elems.osen - 2, elems.osen_len + 2) < 0)
1118 : 0 : return WLAN_STATUS_INVALID_IE;
1119 : : #endif /* CONFIG_HS20 */
1120 : : } else
1121 : 247 : wpa_auth_sta_no_wpa(sta->wpa_sm);
1122 : :
1123 : : #ifdef CONFIG_P2P
1124 : 193 : p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
1125 : : #endif /* CONFIG_P2P */
1126 : :
1127 : : #ifdef CONFIG_HS20
1128 : 674 : wpabuf_free(sta->hs20_ie);
1129 [ + - ][ + + ]: 674 : if (elems.hs20 && elems.hs20_len > 4) {
1130 : 71 : sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
1131 : 71 : elems.hs20_len - 4);
1132 : : } else
1133 : 603 : sta->hs20_ie = NULL;
1134 : : #endif /* CONFIG_HS20 */
1135 : :
1136 : 674 : return WLAN_STATUS_SUCCESS;
1137 : : }
1138 : :
1139 : :
1140 : 0 : static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
1141 : : u16 reason_code)
1142 : : {
1143 : : int send_len;
1144 : : struct ieee80211_mgmt reply;
1145 : :
1146 : 0 : os_memset(&reply, 0, sizeof(reply));
1147 : 0 : reply.frame_control =
1148 : : IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
1149 : 0 : os_memcpy(reply.da, addr, ETH_ALEN);
1150 : 0 : os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
1151 : 0 : os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
1152 : :
1153 : 0 : send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
1154 : 0 : reply.u.deauth.reason_code = host_to_le16(reason_code);
1155 : :
1156 [ # # ]: 0 : if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
1157 : 0 : wpa_printf(MSG_INFO, "Failed to send deauth: %s",
1158 : 0 : strerror(errno));
1159 : 0 : }
1160 : :
1161 : :
1162 : 674 : static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
1163 : : u16 status_code, int reassoc, const u8 *ies,
1164 : : size_t ies_len)
1165 : : {
1166 : : int send_len;
1167 : : u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
1168 : : struct ieee80211_mgmt *reply;
1169 : : u8 *p;
1170 : :
1171 : 674 : os_memset(buf, 0, sizeof(buf));
1172 : 674 : reply = (struct ieee80211_mgmt *) buf;
1173 : 674 : reply->frame_control =
1174 [ + + ]: 674 : IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1175 : : (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
1176 : : WLAN_FC_STYPE_ASSOC_RESP));
1177 : 674 : os_memcpy(reply->da, sta->addr, ETH_ALEN);
1178 : 674 : os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
1179 : 674 : os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
1180 : :
1181 : 674 : send_len = IEEE80211_HDRLEN;
1182 : 674 : send_len += sizeof(reply->u.assoc_resp);
1183 : 674 : reply->u.assoc_resp.capab_info =
1184 : 674 : host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
1185 : 674 : reply->u.assoc_resp.status_code = host_to_le16(status_code);
1186 : 674 : reply->u.assoc_resp.aid = host_to_le16(sta->aid | BIT(14) | BIT(15));
1187 : : /* Supported rates */
1188 : 674 : p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
1189 : : /* Extended supported rates */
1190 : 674 : p = hostapd_eid_ext_supp_rates(hapd, p);
1191 : :
1192 : : #ifdef CONFIG_IEEE80211R
1193 [ + - ]: 674 : if (status_code == WLAN_STATUS_SUCCESS) {
1194 : : /* IEEE 802.11r: Mobility Domain Information, Fast BSS
1195 : : * Transition Information, RSN, [RIC Response] */
1196 : 674 : p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
1197 : 674 : buf + sizeof(buf) - p,
1198 : 674 : sta->auth_alg, ies, ies_len);
1199 : : }
1200 : : #endif /* CONFIG_IEEE80211R */
1201 : :
1202 : : #ifdef CONFIG_IEEE80211W
1203 [ - + ]: 674 : if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
1204 : 0 : p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
1205 : : #endif /* CONFIG_IEEE80211W */
1206 : :
1207 : : #ifdef CONFIG_IEEE80211N
1208 : 674 : p = hostapd_eid_ht_capabilities(hapd, p);
1209 : 674 : p = hostapd_eid_ht_operation(hapd, p);
1210 : : #endif /* CONFIG_IEEE80211N */
1211 : :
1212 : : #ifdef CONFIG_IEEE80211AC
1213 : 481 : p = hostapd_eid_vht_capabilities(hapd, p);
1214 : 481 : p = hostapd_eid_vht_operation(hapd, p);
1215 : : #endif /* CONFIG_IEEE80211AC */
1216 : :
1217 : 674 : p = hostapd_eid_ext_capab(hapd, p);
1218 : 674 : p = hostapd_eid_bss_max_idle_period(hapd, p);
1219 [ + + ]: 674 : if (sta->qos_map_enabled)
1220 : 666 : p = hostapd_eid_qos_map_set(hapd, p);
1221 : :
1222 [ + - ]: 674 : if (sta->flags & WLAN_STA_WMM)
1223 : 674 : p = hostapd_eid_wmm(hapd, p);
1224 : :
1225 : : #ifdef CONFIG_WPS
1226 [ + + ][ + + ]: 674 : if ((sta->flags & WLAN_STA_WPS) ||
1227 [ - + ]: 6 : ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa)) {
1228 : 144 : struct wpabuf *wps = wps_build_assoc_resp_ie();
1229 [ + - ]: 144 : if (wps) {
1230 : 144 : os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
1231 : 144 : p += wpabuf_len(wps);
1232 : 144 : wpabuf_free(wps);
1233 : : }
1234 : : }
1235 : : #endif /* CONFIG_WPS */
1236 : :
1237 : : #ifdef CONFIG_P2P
1238 [ + + ]: 193 : if (sta->p2p_ie) {
1239 : : struct wpabuf *p2p_resp_ie;
1240 : : enum p2p_status_code status;
1241 [ + - - ]: 172 : switch (status_code) {
1242 : : case WLAN_STATUS_SUCCESS:
1243 : 172 : status = P2P_SC_SUCCESS;
1244 : 172 : break;
1245 : : case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
1246 : 0 : status = P2P_SC_FAIL_LIMIT_REACHED;
1247 : 0 : break;
1248 : : default:
1249 : 0 : status = P2P_SC_FAIL_INVALID_PARAMS;
1250 : 0 : break;
1251 : : }
1252 : 172 : p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
1253 [ + - ]: 172 : if (p2p_resp_ie) {
1254 : 172 : os_memcpy(p, wpabuf_head(p2p_resp_ie),
1255 : : wpabuf_len(p2p_resp_ie));
1256 : 172 : p += wpabuf_len(p2p_resp_ie);
1257 : 172 : wpabuf_free(p2p_resp_ie);
1258 : : }
1259 : : }
1260 : : #endif /* CONFIG_P2P */
1261 : :
1262 : : #ifdef CONFIG_P2P_MANAGER
1263 [ + + ]: 481 : if (hapd->conf->p2p & P2P_MANAGE)
1264 : 2 : p = hostapd_eid_p2p_manage(hapd, p);
1265 : : #endif /* CONFIG_P2P_MANAGER */
1266 : :
1267 : 674 : send_len += p - reply->u.assoc_resp.variable;
1268 : :
1269 [ - + ]: 674 : if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
1270 : 0 : wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
1271 : 0 : strerror(errno));
1272 : 674 : }
1273 : :
1274 : :
1275 : 674 : static void handle_assoc(struct hostapd_data *hapd,
1276 : : const struct ieee80211_mgmt *mgmt, size_t len,
1277 : : int reassoc)
1278 : : {
1279 : : u16 capab_info, listen_interval;
1280 : 674 : u16 resp = WLAN_STATUS_SUCCESS;
1281 : : const u8 *pos;
1282 : : int left, i;
1283 : : struct sta_info *sta;
1284 : :
1285 [ + + ][ - + ]: 674 : if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
1286 : : sizeof(mgmt->u.assoc_req))) {
1287 : 0 : wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
1288 : : reassoc, (unsigned long) len);
1289 : 0 : return;
1290 : : }
1291 : :
1292 : : #ifdef CONFIG_TESTING_OPTIONS
1293 [ + + ]: 674 : if (reassoc) {
1294 [ - + # # ]: 26 : if (hapd->iconf->ignore_reassoc_probability > 0.0d &&
1295 : 0 : drand48() < hapd->iconf->ignore_reassoc_probability) {
1296 : 0 : wpa_printf(MSG_INFO,
1297 : : "TESTING: ignoring reassoc request from "
1298 : 0 : MACSTR, MAC2STR(mgmt->sa));
1299 : 0 : return;
1300 : : }
1301 : : } else {
1302 [ - + # # ]: 648 : if (hapd->iconf->ignore_assoc_probability > 0.0d &&
1303 : 0 : drand48() < hapd->iconf->ignore_assoc_probability) {
1304 : 0 : wpa_printf(MSG_INFO,
1305 : : "TESTING: ignoring assoc request from "
1306 : 0 : MACSTR, MAC2STR(mgmt->sa));
1307 : 0 : return;
1308 : : }
1309 : : }
1310 : : #endif /* CONFIG_TESTING_OPTIONS */
1311 : :
1312 [ + + ]: 674 : if (reassoc) {
1313 : 26 : capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
1314 : 26 : listen_interval = le_to_host16(
1315 : : mgmt->u.reassoc_req.listen_interval);
1316 : 26 : wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
1317 : : " capab_info=0x%02x listen_interval=%d current_ap="
1318 : : MACSTR,
1319 : 156 : MAC2STR(mgmt->sa), capab_info, listen_interval,
1320 : 156 : MAC2STR(mgmt->u.reassoc_req.current_ap));
1321 : 26 : left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
1322 : 26 : pos = mgmt->u.reassoc_req.variable;
1323 : : } else {
1324 : 648 : capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
1325 : 648 : listen_interval = le_to_host16(
1326 : : mgmt->u.assoc_req.listen_interval);
1327 : 648 : wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
1328 : : " capab_info=0x%02x listen_interval=%d",
1329 : 3888 : MAC2STR(mgmt->sa), capab_info, listen_interval);
1330 : 648 : left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
1331 : 648 : pos = mgmt->u.assoc_req.variable;
1332 : : }
1333 : :
1334 : 674 : sta = ap_get_sta(hapd, mgmt->sa);
1335 : : #ifdef CONFIG_IEEE80211R
1336 [ + + ][ + + ]: 674 : if (sta && sta->auth_alg == WLAN_AUTH_FT &&
[ + - ]
1337 : 16 : (sta->flags & WLAN_STA_AUTH) == 0) {
1338 : 3 : wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
1339 : : "prior to authentication since it is using "
1340 : 18 : "over-the-DS FT", MAC2STR(mgmt->sa));
1341 : : } else
1342 : : #endif /* CONFIG_IEEE80211R */
1343 [ + - ][ - + ]: 671 : if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
1344 [ # # ][ # # ]: 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1345 : : HOSTAPD_LEVEL_INFO, "Station tried to "
1346 : : "associate before authentication "
1347 : : "(aid=%d flags=0x%x)",
1348 : 0 : sta ? sta->aid : -1,
1349 : : sta ? sta->flags : 0);
1350 : 0 : send_deauth(hapd, mgmt->sa,
1351 : : WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
1352 : 0 : return;
1353 : : }
1354 : :
1355 [ - + ]: 674 : if (hapd->tkip_countermeasures) {
1356 : 0 : resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
1357 : 0 : goto fail;
1358 : : }
1359 : :
1360 [ - + ]: 674 : if (listen_interval > hapd->conf->max_listen_interval) {
1361 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1362 : : HOSTAPD_LEVEL_DEBUG,
1363 : : "Too large Listen Interval (%d)",
1364 : : listen_interval);
1365 : 0 : resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
1366 : 0 : goto fail;
1367 : : }
1368 : :
1369 : : /* followed by SSID and Supported rates; and HT capabilities if 802.11n
1370 : : * is used */
1371 : 674 : resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
1372 [ - + ]: 674 : if (resp != WLAN_STATUS_SUCCESS)
1373 : 0 : goto fail;
1374 : :
1375 [ - + ]: 674 : if (hostapd_get_aid(hapd, sta) < 0) {
1376 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1377 : : HOSTAPD_LEVEL_INFO, "No room for more AIDs");
1378 : 0 : resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1379 : 0 : goto fail;
1380 : : }
1381 : :
1382 : 674 : sta->capability = capab_info;
1383 : 674 : sta->listen_interval = listen_interval;
1384 : :
1385 [ + - ]: 674 : if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
1386 : 674 : sta->flags |= WLAN_STA_NONERP;
1387 [ + - ]: 4018 : for (i = 0; i < sta->supported_rates_len; i++) {
1388 [ + + ]: 4018 : if ((sta->supported_rates[i] & 0x7f) > 22) {
1389 : 674 : sta->flags &= ~WLAN_STA_NONERP;
1390 : 674 : break;
1391 : : }
1392 : : }
1393 [ - + ][ # # ]: 674 : if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
1394 : 0 : sta->nonerp_set = 1;
1395 : 0 : hapd->iface->num_sta_non_erp++;
1396 [ # # ]: 0 : if (hapd->iface->num_sta_non_erp == 1)
1397 : 0 : ieee802_11_set_beacons(hapd->iface);
1398 : : }
1399 : :
1400 [ - + ][ # # ]: 674 : if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
1401 : 0 : !sta->no_short_slot_time_set) {
1402 : 0 : sta->no_short_slot_time_set = 1;
1403 : 0 : hapd->iface->num_sta_no_short_slot_time++;
1404 [ # # ]: 0 : if (hapd->iface->current_mode->mode ==
1405 [ # # ]: 0 : HOSTAPD_MODE_IEEE80211G &&
1406 : 0 : hapd->iface->num_sta_no_short_slot_time == 1)
1407 : 0 : ieee802_11_set_beacons(hapd->iface);
1408 : : }
1409 : :
1410 [ + - ]: 674 : if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1411 : 674 : sta->flags |= WLAN_STA_SHORT_PREAMBLE;
1412 : : else
1413 : 0 : sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1414 : :
1415 [ - + ][ # # ]: 674 : if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
1416 : 0 : !sta->no_short_preamble_set) {
1417 : 0 : sta->no_short_preamble_set = 1;
1418 : 0 : hapd->iface->num_sta_no_short_preamble++;
1419 [ # # ]: 0 : if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
1420 [ # # ]: 0 : && hapd->iface->num_sta_no_short_preamble == 1)
1421 : 0 : ieee802_11_set_beacons(hapd->iface);
1422 : : }
1423 : :
1424 : : #ifdef CONFIG_IEEE80211N
1425 : 674 : update_ht_state(hapd, sta);
1426 : : #endif /* CONFIG_IEEE80211N */
1427 : :
1428 : 674 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1429 : : HOSTAPD_LEVEL_DEBUG,
1430 : 674 : "association OK (aid %d)", sta->aid);
1431 : : /* Station will be marked associated, after it acknowledges AssocResp
1432 : : */
1433 : 674 : sta->flags |= WLAN_STA_ASSOC_REQ_OK;
1434 : :
1435 : : #ifdef CONFIG_IEEE80211W
1436 [ - + ][ + + ]: 674 : if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
1437 [ # # ]: 0 : wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
1438 : : "SA Query procedure", reassoc ? "re" : "");
1439 : : /* TODO: Send a protected Disassociate frame to the STA using
1440 : : * the old key and Reason Code "Previous Authentication no
1441 : : * longer valid". Make sure this is only sent protected since
1442 : : * unprotected frame would be received by the STA that is now
1443 : : * trying to associate.
1444 : : */
1445 : : }
1446 : : #endif /* CONFIG_IEEE80211W */
1447 : :
1448 [ + + ]: 674 : if (reassoc) {
1449 : 26 : os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap,
1450 : : ETH_ALEN);
1451 : : }
1452 : :
1453 [ - + ]: 674 : if (sta->last_assoc_req)
1454 : 0 : os_free(sta->last_assoc_req);
1455 : 674 : sta->last_assoc_req = os_malloc(len);
1456 [ + - ]: 674 : if (sta->last_assoc_req)
1457 : 674 : os_memcpy(sta->last_assoc_req, mgmt, len);
1458 : :
1459 : : /* Make sure that the previously registered inactivity timer will not
1460 : : * remove the STA immediately. */
1461 : 674 : sta->timeout_next = STA_NULLFUNC;
1462 : :
1463 : : fail:
1464 : 674 : send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
1465 : : }
1466 : :
1467 : :
1468 : 0 : static void handle_disassoc(struct hostapd_data *hapd,
1469 : : const struct ieee80211_mgmt *mgmt, size_t len)
1470 : : {
1471 : : struct sta_info *sta;
1472 : :
1473 [ # # ]: 0 : if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
1474 : 0 : wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
1475 : : (unsigned long) len);
1476 : 0 : return;
1477 : : }
1478 : :
1479 : 0 : wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
1480 : 0 : MAC2STR(mgmt->sa),
1481 : 0 : le_to_host16(mgmt->u.disassoc.reason_code));
1482 : :
1483 : 0 : sta = ap_get_sta(hapd, mgmt->sa);
1484 [ # # ]: 0 : if (sta == NULL) {
1485 : 0 : wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
1486 : 0 : MAC2STR(mgmt->sa));
1487 : 0 : return;
1488 : : }
1489 : :
1490 : 0 : ap_sta_set_authorized(hapd, sta, 0);
1491 : 0 : sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
1492 : 0 : wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
1493 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1494 : : HOSTAPD_LEVEL_INFO, "disassociated");
1495 : 0 : sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1496 : 0 : ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1497 : : /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
1498 : : * authenticated. */
1499 : 0 : accounting_sta_stop(hapd, sta);
1500 : 0 : ieee802_1x_free_station(sta);
1501 : 0 : hostapd_drv_sta_remove(hapd, sta->addr);
1502 : :
1503 [ # # ][ # # ]: 0 : if (sta->timeout_next == STA_NULLFUNC ||
1504 : 0 : sta->timeout_next == STA_DISASSOC) {
1505 : 0 : sta->timeout_next = STA_DEAUTH;
1506 : 0 : eloop_cancel_timeout(ap_handle_timer, hapd, sta);
1507 : 0 : eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
1508 : : hapd, sta);
1509 : : }
1510 : :
1511 : 0 : mlme_disassociate_indication(
1512 : 0 : hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
1513 : : }
1514 : :
1515 : :
1516 : 545 : static void handle_deauth(struct hostapd_data *hapd,
1517 : : const struct ieee80211_mgmt *mgmt, size_t len)
1518 : : {
1519 : : struct sta_info *sta;
1520 : :
1521 [ - + ]: 545 : if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
1522 : 0 : wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
1523 : : "payload (len=%lu)", (unsigned long) len);
1524 : 0 : return;
1525 : : }
1526 : :
1527 : 545 : wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
1528 : : " reason_code=%d",
1529 : 3815 : MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
1530 : :
1531 : 545 : sta = ap_get_sta(hapd, mgmt->sa);
1532 [ - + ]: 545 : if (sta == NULL) {
1533 : 0 : wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
1534 : : "to deauthenticate, but it is not authenticated",
1535 : 0 : MAC2STR(mgmt->sa));
1536 : 0 : return;
1537 : : }
1538 : :
1539 : 545 : ap_sta_set_authorized(hapd, sta, 0);
1540 : 545 : sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
1541 : : WLAN_STA_ASSOC_REQ_OK);
1542 : 545 : wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
1543 : 545 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1544 : : HOSTAPD_LEVEL_DEBUG, "deauthenticated");
1545 : 545 : mlme_deauthenticate_indication(
1546 : 545 : hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
1547 : 545 : sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1548 : 545 : ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1549 : 545 : ap_free_sta(hapd, sta);
1550 : : }
1551 : :
1552 : :
1553 : 1349 : static void handle_beacon(struct hostapd_data *hapd,
1554 : : const struct ieee80211_mgmt *mgmt, size_t len,
1555 : : struct hostapd_frame_info *fi)
1556 : : {
1557 : : struct ieee802_11_elems elems;
1558 : :
1559 [ - + ]: 1349 : if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
1560 : 0 : wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
1561 : : (unsigned long) len);
1562 : 1349 : return;
1563 : : }
1564 : :
1565 : 1349 : (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
1566 : : len - (IEEE80211_HDRLEN +
1567 : : sizeof(mgmt->u.beacon)), &elems,
1568 : : 0);
1569 : :
1570 : 1349 : ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
1571 : : }
1572 : :
1573 : :
1574 : : #ifdef CONFIG_IEEE80211W
1575 : :
1576 : 2 : static int hostapd_sa_query_action(struct hostapd_data *hapd,
1577 : : const struct ieee80211_mgmt *mgmt,
1578 : : size_t len)
1579 : : {
1580 : : const u8 *end;
1581 : :
1582 : 2 : end = mgmt->u.action.u.sa_query_resp.trans_id +
1583 : : WLAN_SA_QUERY_TR_ID_LEN;
1584 [ - + ]: 2 : if (((u8 *) mgmt) + len < end) {
1585 : 0 : wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
1586 : : "frame (len=%lu)", (unsigned long) len);
1587 : 0 : return 0;
1588 : : }
1589 : :
1590 : 2 : ieee802_11_sa_query_action(hapd, mgmt->sa,
1591 : 2 : mgmt->u.action.u.sa_query_resp.action,
1592 : 2 : mgmt->u.action.u.sa_query_resp.trans_id);
1593 : 2 : return 1;
1594 : : }
1595 : :
1596 : :
1597 : 0 : static int robust_action_frame(u8 category)
1598 : : {
1599 [ # # ][ # # ]: 0 : return category != WLAN_ACTION_PUBLIC &&
1600 : : category != WLAN_ACTION_HT;
1601 : : }
1602 : : #endif /* CONFIG_IEEE80211W */
1603 : :
1604 : :
1605 : 243 : static int handle_action(struct hostapd_data *hapd,
1606 : : const struct ieee80211_mgmt *mgmt, size_t len)
1607 : : {
1608 : : struct sta_info *sta;
1609 : 243 : sta = ap_get_sta(hapd, mgmt->sa);
1610 : :
1611 [ - + ]: 243 : if (len < IEEE80211_HDRLEN + 1) {
1612 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1613 : : HOSTAPD_LEVEL_DEBUG,
1614 : : "handle_action - too short payload (len=%lu)",
1615 : : (unsigned long) len);
1616 : 0 : return 0;
1617 : : }
1618 : :
1619 [ + + ][ + - ]: 243 : if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
1620 [ - + ]: 21 : (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
1621 : 0 : wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
1622 : : "frame (category=%u) from unassociated STA " MACSTR,
1623 : 0 : MAC2STR(mgmt->sa), mgmt->u.action.category);
1624 : 0 : return 0;
1625 : : }
1626 : :
1627 : : #ifdef CONFIG_IEEE80211W
1628 [ + + ][ + + ]: 243 : if (sta && (sta->flags & WLAN_STA_MFP) &&
[ - + ]
1629 [ # # ]: 0 : !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
1630 : 0 : robust_action_frame(mgmt->u.action.category)) {
1631 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1632 : : HOSTAPD_LEVEL_DEBUG,
1633 : : "Dropped unprotected Robust Action frame from "
1634 : : "an MFP STA");
1635 : 0 : return 0;
1636 : : }
1637 : : #endif /* CONFIG_IEEE80211W */
1638 : :
1639 [ + - + + : 243 : switch (mgmt->u.action.category) {
+ + - ]
1640 : : #ifdef CONFIG_IEEE80211R
1641 : : case WLAN_ACTION_FT:
1642 [ - + ]: 6 : if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
1643 : : len - IEEE80211_HDRLEN))
1644 : 0 : break;
1645 : 6 : return 1;
1646 : : #endif /* CONFIG_IEEE80211R */
1647 : : case WLAN_ACTION_WMM:
1648 : 0 : hostapd_wmm_action(hapd, mgmt, len);
1649 : 0 : return 1;
1650 : : #ifdef CONFIG_IEEE80211W
1651 : : case WLAN_ACTION_SA_QUERY:
1652 : 2 : return hostapd_sa_query_action(hapd, mgmt, len);
1653 : : #endif /* CONFIG_IEEE80211W */
1654 : : #ifdef CONFIG_WNM
1655 : : case WLAN_ACTION_WNM:
1656 : 11 : ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
1657 : 11 : return 1;
1658 : : #endif /* CONFIG_WNM */
1659 : : case WLAN_ACTION_PUBLIC:
1660 : : case WLAN_ACTION_PROTECTED_DUAL:
1661 [ + + ]: 223 : if (hapd->public_action_cb) {
1662 : 32 : hapd->public_action_cb(hapd->public_action_cb_ctx,
1663 : : (u8 *) mgmt, len,
1664 : 32 : hapd->iface->freq);
1665 : : }
1666 [ + - ]: 223 : if (hapd->public_action_cb2) {
1667 : 223 : hapd->public_action_cb2(hapd->public_action_cb2_ctx,
1668 : : (u8 *) mgmt, len,
1669 : 223 : hapd->iface->freq);
1670 : : }
1671 [ + + ][ + - ]: 223 : if (hapd->public_action_cb || hapd->public_action_cb2)
1672 : 223 : return 1;
1673 : 0 : break;
1674 : : case WLAN_ACTION_VENDOR_SPECIFIC:
1675 [ + - ]: 1 : if (hapd->vendor_action_cb) {
1676 [ + - ]: 1 : if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
1677 : : (u8 *) mgmt, len,
1678 : 1 : hapd->iface->freq) == 0)
1679 : 1 : return 1;
1680 : : }
1681 : 0 : break;
1682 : : }
1683 : :
1684 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1685 : : HOSTAPD_LEVEL_DEBUG,
1686 : : "handle_action - unknown action category %d or invalid "
1687 : : "frame",
1688 : 0 : mgmt->u.action.category);
1689 [ # # ][ # # ]: 0 : if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
[ # # ]
1690 : 0 : !(mgmt->sa[0] & 0x01)) {
1691 : : struct ieee80211_mgmt *resp;
1692 : :
1693 : : /*
1694 : : * IEEE 802.11-REVma/D9.0 - 7.3.1.11
1695 : : * Return the Action frame to the source without change
1696 : : * except that MSB of the Category set to 1.
1697 : : */
1698 : 0 : wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
1699 : : "frame back to sender");
1700 : 0 : resp = os_malloc(len);
1701 [ # # ]: 0 : if (resp == NULL)
1702 : 0 : return 0;
1703 : 0 : os_memcpy(resp, mgmt, len);
1704 : 0 : os_memcpy(resp->da, resp->sa, ETH_ALEN);
1705 : 0 : os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
1706 : 0 : os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
1707 : 0 : resp->u.action.category |= 0x80;
1708 : :
1709 [ # # ]: 0 : if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
1710 : 0 : wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
1711 : : "Action frame");
1712 : : }
1713 : 0 : os_free(resp);
1714 : : }
1715 : :
1716 : 243 : return 1;
1717 : : }
1718 : :
1719 : :
1720 : : /**
1721 : : * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
1722 : : * @hapd: hostapd BSS data structure (the BSS to which the management frame was
1723 : : * sent to)
1724 : : * @buf: management frame data (starting from IEEE 802.11 header)
1725 : : * @len: length of frame data in octets
1726 : : * @fi: meta data about received frame (signal level, etc.)
1727 : : *
1728 : : * Process all incoming IEEE 802.11 management frames. This will be called for
1729 : : * each frame received from the kernel driver through wlan#ap interface. In
1730 : : * addition, it can be called to re-inserted pending frames (e.g., when using
1731 : : * external RADIUS server as an MAC ACL).
1732 : : */
1733 : 4691 : int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
1734 : : struct hostapd_frame_info *fi)
1735 : : {
1736 : : struct ieee80211_mgmt *mgmt;
1737 : : int broadcast;
1738 : : u16 fc, stype;
1739 : 4691 : int ret = 0;
1740 : :
1741 [ - + ]: 4691 : if (len < 24)
1742 : 0 : return 0;
1743 : :
1744 : 4691 : mgmt = (struct ieee80211_mgmt *) buf;
1745 : 4691 : fc = le_to_host16(mgmt->frame_control);
1746 : 4691 : stype = WLAN_FC_GET_STYPE(fc);
1747 : :
1748 [ + + ]: 4691 : if (stype == WLAN_FC_STYPE_BEACON) {
1749 : 1349 : handle_beacon(hapd, mgmt, len, fi);
1750 : 1349 : return 1;
1751 : : }
1752 : :
1753 [ + + ][ + - ]: 4485 : broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
[ + - ]
1754 [ + - ][ + - ]: 1143 : mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
1755 [ + - ]: 1143 : mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
1756 : :
1757 [ + + ][ + + ]: 3342 : if (!broadcast &&
1758 : : #ifdef CONFIG_P2P
1759 : : /* Invitation responses can be sent with the peer MAC as BSSID */
1760 [ + + ]: 495 : !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
1761 [ - + ]: 510 : stype == WLAN_FC_STYPE_ACTION) &&
1762 : : #endif /* CONFIG_P2P */
1763 : 2166 : os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
1764 : 0 : wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
1765 : 0 : MAC2STR(mgmt->bssid));
1766 : 0 : return 0;
1767 : : }
1768 : :
1769 : :
1770 [ + + ]: 3342 : if (stype == WLAN_FC_STYPE_PROBE_REQ) {
1771 : 1185 : handle_probe_req(hapd, mgmt, len, fi->ssi_signal);
1772 : 1185 : return 1;
1773 : : }
1774 : :
1775 [ - + ]: 2157 : if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
1776 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1777 : : HOSTAPD_LEVEL_DEBUG,
1778 : : "MGMT: DA=" MACSTR " not our address",
1779 : 0 : MAC2STR(mgmt->da));
1780 : 0 : return 0;
1781 : : }
1782 : :
1783 [ + + + - : 2157 : switch (stype) {
+ + - ]
1784 : : case WLAN_FC_STYPE_AUTH:
1785 : 695 : wpa_printf(MSG_DEBUG, "mgmt::auth");
1786 : 695 : handle_auth(hapd, mgmt, len);
1787 : 695 : ret = 1;
1788 : 695 : break;
1789 : : case WLAN_FC_STYPE_ASSOC_REQ:
1790 : 648 : wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
1791 : 648 : handle_assoc(hapd, mgmt, len, 0);
1792 : 648 : ret = 1;
1793 : 648 : break;
1794 : : case WLAN_FC_STYPE_REASSOC_REQ:
1795 : 26 : wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
1796 : 26 : handle_assoc(hapd, mgmt, len, 1);
1797 : 26 : ret = 1;
1798 : 26 : break;
1799 : : case WLAN_FC_STYPE_DISASSOC:
1800 : 0 : wpa_printf(MSG_DEBUG, "mgmt::disassoc");
1801 : 0 : handle_disassoc(hapd, mgmt, len);
1802 : 0 : ret = 1;
1803 : 0 : break;
1804 : : case WLAN_FC_STYPE_DEAUTH:
1805 : 545 : wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
1806 : 545 : handle_deauth(hapd, mgmt, len);
1807 : 545 : ret = 1;
1808 : 545 : break;
1809 : : case WLAN_FC_STYPE_ACTION:
1810 : 243 : wpa_printf(MSG_DEBUG, "mgmt::action");
1811 : 243 : ret = handle_action(hapd, mgmt, len);
1812 : 243 : break;
1813 : : default:
1814 : 0 : hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1815 : : HOSTAPD_LEVEL_DEBUG,
1816 : : "unknown mgmt frame subtype %d", stype);
1817 : 0 : break;
1818 : : }
1819 : :
1820 : 4691 : return ret;
1821 : : }
1822 : :
1823 : :
1824 : 695 : static void handle_auth_cb(struct hostapd_data *hapd,
1825 : : const struct ieee80211_mgmt *mgmt,
1826 : : size_t len, int ok)
1827 : : {
1828 : : u16 auth_alg, auth_transaction, status_code;
1829 : : struct sta_info *sta;
1830 : :
1831 [ - + ]: 695 : if (!ok) {
1832 : 0 : hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1833 : : HOSTAPD_LEVEL_NOTICE,
1834 : : "did not acknowledge authentication response");
1835 : 0 : return;
1836 : : }
1837 : :
1838 [ - + ]: 695 : if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
1839 : 0 : wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
1840 : : (unsigned long) len);
1841 : 0 : return;
1842 : : }
1843 : :
1844 : 695 : auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1845 : 695 : auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1846 : 695 : status_code = le_to_host16(mgmt->u.auth.status_code);
1847 : :
1848 : 695 : sta = ap_get_sta(hapd, mgmt->da);
1849 [ + + ]: 695 : if (!sta) {
1850 : 5 : wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
1851 : 30 : MAC2STR(mgmt->da));
1852 : 5 : return;
1853 : : }
1854 : :
1855 [ + + ][ + + ]: 690 : if (status_code == WLAN_STATUS_SUCCESS &&
1856 [ - + ][ + + ]: 686 : ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
1857 [ + + ]: 4 : (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
1858 : 642 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1859 : : HOSTAPD_LEVEL_INFO, "authenticated");
1860 : 695 : sta->flags |= WLAN_STA_AUTH;
1861 : : }
1862 : : }
1863 : :
1864 : :
1865 : 0 : static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
1866 : : struct sta_info *sta,
1867 : : char *ifname_wds)
1868 : : {
1869 : : int i;
1870 : 0 : struct hostapd_ssid *ssid = sta->ssid;
1871 : :
1872 [ # # ][ # # ]: 0 : if (hapd->conf->ieee802_1x || hapd->conf->wpa)
1873 : 0 : return;
1874 : :
1875 [ # # ]: 0 : for (i = 0; i < 4; i++) {
1876 [ # # # # ]: 0 : if (ssid->wep.key[i] &&
1877 : 0 : hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
1878 : 0 : i == ssid->wep.idx, NULL, 0,
1879 : 0 : ssid->wep.key[i], ssid->wep.len[i])) {
1880 : 0 : wpa_printf(MSG_WARNING,
1881 : : "Could not set WEP keys for WDS interface; %s",
1882 : : ifname_wds);
1883 : 0 : break;
1884 : : }
1885 : : }
1886 : : }
1887 : :
1888 : :
1889 : 674 : static void handle_assoc_cb(struct hostapd_data *hapd,
1890 : : const struct ieee80211_mgmt *mgmt,
1891 : : size_t len, int reassoc, int ok)
1892 : : {
1893 : : u16 status;
1894 : : struct sta_info *sta;
1895 : 674 : int new_assoc = 1;
1896 : : struct ieee80211_ht_capabilities ht_cap;
1897 : : struct ieee80211_vht_capabilities vht_cap;
1898 : :
1899 [ - + ]: 674 : if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
1900 : : sizeof(mgmt->u.assoc_resp))) {
1901 : 0 : wpa_printf(MSG_INFO, "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
1902 : : reassoc, (unsigned long) len);
1903 : 0 : return;
1904 : : }
1905 : :
1906 : 674 : sta = ap_get_sta(hapd, mgmt->da);
1907 [ - + ]: 674 : if (!sta) {
1908 : 0 : wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
1909 : 0 : MAC2STR(mgmt->da));
1910 : 0 : return;
1911 : : }
1912 : :
1913 [ - + ]: 674 : if (!ok) {
1914 : 0 : hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1915 : : HOSTAPD_LEVEL_DEBUG,
1916 : : "did not acknowledge association response");
1917 : 0 : sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
1918 : 0 : return;
1919 : : }
1920 : :
1921 [ + + ]: 674 : if (reassoc)
1922 : 26 : status = le_to_host16(mgmt->u.reassoc_resp.status_code);
1923 : : else
1924 : 648 : status = le_to_host16(mgmt->u.assoc_resp.status_code);
1925 : :
1926 [ - + ]: 674 : if (status != WLAN_STATUS_SUCCESS)
1927 : 0 : goto fail;
1928 : :
1929 : : /* Stop previous accounting session, if one is started, and allocate
1930 : : * new session id for the new session. */
1931 : 674 : accounting_sta_stop(hapd, sta);
1932 : :
1933 : 674 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1934 : : HOSTAPD_LEVEL_INFO,
1935 : : "associated (aid %d)",
1936 : 674 : sta->aid);
1937 : :
1938 [ - + ]: 674 : if (sta->flags & WLAN_STA_ASSOC)
1939 : 0 : new_assoc = 0;
1940 : 674 : sta->flags |= WLAN_STA_ASSOC;
1941 : 674 : sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
1942 [ + + ][ + + ]: 674 : if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) ||
[ + + ][ + + ]
1943 : 565 : sta->auth_alg == WLAN_AUTH_FT) {
1944 : : /*
1945 : : * Open, static WEP, or FT protocol; no separate authorization
1946 : : * step.
1947 : : */
1948 : 125 : ap_sta_set_authorized(hapd, sta, 1);
1949 : : }
1950 : :
1951 [ + + ]: 674 : if (reassoc)
1952 : 26 : mlme_reassociate_indication(hapd, sta);
1953 : : else
1954 : 648 : mlme_associate_indication(hapd, sta);
1955 : :
1956 : : #ifdef CONFIG_IEEE80211W
1957 : 674 : sta->sa_query_timed_out = 0;
1958 : : #endif /* CONFIG_IEEE80211W */
1959 : :
1960 : : /*
1961 : : * Remove the STA entry in order to make sure the STA PS state gets
1962 : : * cleared and configuration gets updated in case of reassociation back
1963 : : * to the same AP.
1964 : : */
1965 : 674 : hostapd_drv_sta_remove(hapd, sta->addr);
1966 : :
1967 : : #ifdef CONFIG_IEEE80211N
1968 [ + + ]: 674 : if (sta->flags & WLAN_STA_HT)
1969 : 660 : hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
1970 : : #endif /* CONFIG_IEEE80211N */
1971 : : #ifdef CONFIG_IEEE80211AC
1972 [ - + ]: 481 : if (sta->flags & WLAN_STA_VHT)
1973 : 0 : hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
1974 : : #endif /* CONFIG_IEEE80211AC */
1975 : :
1976 [ - + ][ + + ]: 674 : if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
[ - + ]
1977 : 1348 : sta->supported_rates, sta->supported_rates_len,
1978 : 674 : sta->listen_interval,
1979 : 674 : sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
1980 : 674 : sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
1981 : 1348 : sta->flags, sta->qosinfo, sta->vht_opmode)) {
1982 : 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1983 : : HOSTAPD_LEVEL_NOTICE,
1984 : : "Could not add STA to kernel driver");
1985 : :
1986 : 0 : ap_sta_disconnect(hapd, sta, sta->addr,
1987 : : WLAN_REASON_DISASSOC_AP_BUSY);
1988 : :
1989 : 0 : goto fail;
1990 : : }
1991 : :
1992 [ - + ]: 674 : if (sta->flags & WLAN_STA_WDS) {
1993 : : int ret;
1994 : : char ifname_wds[IFNAMSIZ + 1];
1995 : :
1996 : 0 : ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
1997 : 0 : sta->aid, 1);
1998 [ # # ]: 0 : if (!ret)
1999 : 0 : hostapd_set_wds_encryption(hapd, sta, ifname_wds);
2000 : : }
2001 : :
2002 [ + + ]: 674 : if (sta->eapol_sm == NULL) {
2003 : : /*
2004 : : * This STA does not use RADIUS server for EAP authentication,
2005 : : * so bind it to the selected VLAN interface now, since the
2006 : : * interface selection is not going to change anymore.
2007 : : */
2008 [ - + ]: 670 : if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
2009 : 0 : goto fail;
2010 [ - + ]: 4 : } else if (sta->vlan_id) {
2011 : : /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
2012 [ # # ]: 0 : if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
2013 : 0 : goto fail;
2014 : : }
2015 : :
2016 : 674 : hostapd_set_sta_flags(hapd, sta);
2017 : :
2018 [ + + ]: 674 : if (sta->auth_alg == WLAN_AUTH_FT)
2019 : 16 : wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
2020 : : else
2021 : 658 : wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
2022 : 674 : hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
2023 : :
2024 : 674 : ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
2025 : :
2026 : : fail:
2027 : : /* Copy of the association request is not needed anymore */
2028 [ + - ]: 674 : if (sta->last_assoc_req) {
2029 : 674 : os_free(sta->last_assoc_req);
2030 : 674 : sta->last_assoc_req = NULL;
2031 : : }
2032 : : }
2033 : :
2034 : :
2035 : 202 : static void handle_deauth_cb(struct hostapd_data *hapd,
2036 : : const struct ieee80211_mgmt *mgmt,
2037 : : size_t len, int ok)
2038 : : {
2039 : : struct sta_info *sta;
2040 [ + + ]: 202 : if (mgmt->da[0] & 0x01)
2041 : 15 : return;
2042 : 187 : sta = ap_get_sta(hapd, mgmt->da);
2043 [ + + ]: 187 : if (!sta) {
2044 : 134 : wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
2045 : 804 : " not found", MAC2STR(mgmt->da));
2046 : 134 : return;
2047 : : }
2048 [ + + ]: 53 : if (ok)
2049 : 38 : wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
2050 : 228 : MAC2STR(sta->addr));
2051 : : else
2052 : 15 : wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
2053 : 90 : "deauth", MAC2STR(sta->addr));
2054 : :
2055 : 202 : ap_sta_deauth_cb(hapd, sta);
2056 : : }
2057 : :
2058 : :
2059 : 1 : static void handle_disassoc_cb(struct hostapd_data *hapd,
2060 : : const struct ieee80211_mgmt *mgmt,
2061 : : size_t len, int ok)
2062 : : {
2063 : : struct sta_info *sta;
2064 [ - + ]: 1 : if (mgmt->da[0] & 0x01)
2065 : 0 : return;
2066 : 1 : sta = ap_get_sta(hapd, mgmt->da);
2067 [ - + ]: 1 : if (!sta) {
2068 : 0 : wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
2069 : 0 : " not found", MAC2STR(mgmt->da));
2070 : 0 : return;
2071 : : }
2072 [ + - ]: 1 : if (ok)
2073 : 1 : wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
2074 : 6 : MAC2STR(sta->addr));
2075 : : else
2076 : 0 : wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
2077 : 0 : "disassoc", MAC2STR(sta->addr));
2078 : :
2079 : 1 : ap_sta_disassoc_cb(hapd, sta);
2080 : : }
2081 : :
2082 : :
2083 : : /**
2084 : : * ieee802_11_mgmt_cb - Process management frame TX status callback
2085 : : * @hapd: hostapd BSS data structure (the BSS from which the management frame
2086 : : * was sent from)
2087 : : * @buf: management frame data (starting from IEEE 802.11 header)
2088 : : * @len: length of frame data in octets
2089 : : * @stype: management frame subtype from frame control field
2090 : : * @ok: Whether the frame was ACK'ed
2091 : : */
2092 : 2088 : void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
2093 : : u16 stype, int ok)
2094 : : {
2095 : : const struct ieee80211_mgmt *mgmt;
2096 : 2088 : mgmt = (const struct ieee80211_mgmt *) buf;
2097 : :
2098 : : #ifdef CONFIG_TESTING_OPTIONS
2099 [ + + ]: 2088 : if (hapd->ext_mgmt_frame_handling) {
2100 : 170 : wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-TX-STATUS stype=%u ok=%d",
2101 : : stype, ok);
2102 : 2088 : return;
2103 : : }
2104 : : #endif /* CONFIG_TESTING_OPTIONS */
2105 : :
2106 [ + + + + : 1918 : switch (stype) {
+ + + - ]
2107 : : case WLAN_FC_STYPE_AUTH:
2108 : 695 : wpa_printf(MSG_DEBUG, "mgmt::auth cb");
2109 : 695 : handle_auth_cb(hapd, mgmt, len, ok);
2110 : 695 : break;
2111 : : case WLAN_FC_STYPE_ASSOC_RESP:
2112 : 648 : wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
2113 : 648 : handle_assoc_cb(hapd, mgmt, len, 0, ok);
2114 : 648 : break;
2115 : : case WLAN_FC_STYPE_REASSOC_RESP:
2116 : 26 : wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
2117 : 26 : handle_assoc_cb(hapd, mgmt, len, 1, ok);
2118 : 26 : break;
2119 : : case WLAN_FC_STYPE_PROBE_RESP:
2120 : 134 : wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb");
2121 : 134 : break;
2122 : : case WLAN_FC_STYPE_DEAUTH:
2123 : 202 : wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
2124 : 202 : handle_deauth_cb(hapd, mgmt, len, ok);
2125 : 202 : break;
2126 : : case WLAN_FC_STYPE_DISASSOC:
2127 : 1 : wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
2128 : 1 : handle_disassoc_cb(hapd, mgmt, len, ok);
2129 : 1 : break;
2130 : : case WLAN_FC_STYPE_ACTION:
2131 : 212 : wpa_printf(MSG_DEBUG, "mgmt::action cb");
2132 : 212 : break;
2133 : : default:
2134 : 0 : wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
2135 : 0 : break;
2136 : : }
2137 : : }
2138 : :
2139 : :
2140 : 3 : int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
2141 : : {
2142 : : /* TODO */
2143 : 3 : return 0;
2144 : : }
2145 : :
2146 : :
2147 : 19 : int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
2148 : : char *buf, size_t buflen)
2149 : : {
2150 : : /* TODO */
2151 : 19 : return 0;
2152 : : }
2153 : :
2154 : :
2155 : 785 : void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
2156 : : const u8 *buf, size_t len, int ack)
2157 : : {
2158 : : struct sta_info *sta;
2159 : 785 : struct hostapd_iface *iface = hapd->iface;
2160 : :
2161 : 785 : sta = ap_get_sta(hapd, addr);
2162 [ # # ][ - + ]: 785 : if (sta == NULL && iface->num_bss > 1) {
2163 : : size_t j;
2164 [ # # ]: 0 : for (j = 0; j < iface->num_bss; j++) {
2165 : 0 : hapd = iface->bss[j];
2166 : 0 : sta = ap_get_sta(hapd, addr);
2167 [ # # ]: 0 : if (sta)
2168 : 0 : break;
2169 : : }
2170 : : }
2171 [ + - ][ + + ]: 785 : if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
2172 : 785 : return;
2173 [ - + ]: 698 : if (sta->flags & WLAN_STA_PENDING_POLL) {
2174 [ # # ]: 0 : wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
2175 : 0 : "activity poll", MAC2STR(sta->addr),
2176 : : ack ? "ACKed" : "did not ACK");
2177 [ # # ]: 0 : if (ack)
2178 : 0 : sta->flags &= ~WLAN_STA_PENDING_POLL;
2179 : : }
2180 : :
2181 : 698 : ieee802_1x_tx_status(hapd, sta, buf, len, ack);
2182 : : }
2183 : :
2184 : :
2185 : 2322 : void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
2186 : : const u8 *data, size_t len, int ack)
2187 : : {
2188 : : struct sta_info *sta;
2189 : 2322 : struct hostapd_iface *iface = hapd->iface;
2190 : :
2191 : 2322 : sta = ap_get_sta(hapd, dst);
2192 [ + + ][ + + ]: 2322 : if (sta == NULL && iface->num_bss > 1) {
2193 : : size_t j;
2194 [ + - ]: 13 : for (j = 0; j < iface->num_bss; j++) {
2195 : 13 : hapd = iface->bss[j];
2196 : 13 : sta = ap_get_sta(hapd, dst);
2197 [ + + ]: 13 : if (sta)
2198 : 5 : break;
2199 : : }
2200 : : }
2201 [ + + ][ + + ]: 2322 : if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
2202 : 82 : wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
2203 : : MACSTR " that is not currently associated",
2204 : 492 : MAC2STR(dst));
2205 : 2322 : return;
2206 : : }
2207 : :
2208 : 2240 : ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
2209 : : }
2210 : :
2211 : :
2212 : 0 : void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
2213 : : {
2214 : : struct sta_info *sta;
2215 : 0 : struct hostapd_iface *iface = hapd->iface;
2216 : :
2217 : 0 : sta = ap_get_sta(hapd, addr);
2218 [ # # ][ # # ]: 0 : if (sta == NULL && iface->num_bss > 1) {
2219 : : size_t j;
2220 [ # # ]: 0 : for (j = 0; j < iface->num_bss; j++) {
2221 : 0 : hapd = iface->bss[j];
2222 : 0 : sta = ap_get_sta(hapd, addr);
2223 [ # # ]: 0 : if (sta)
2224 : 0 : break;
2225 : : }
2226 : : }
2227 [ # # ]: 0 : if (sta == NULL)
2228 : 0 : return;
2229 [ # # ]: 0 : if (!(sta->flags & WLAN_STA_PENDING_POLL))
2230 : 0 : return;
2231 : :
2232 : 0 : wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
2233 : 0 : "activity poll", MAC2STR(sta->addr));
2234 : 0 : sta->flags &= ~WLAN_STA_PENDING_POLL;
2235 : : }
2236 : :
2237 : :
2238 : 0 : void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
2239 : : int wds)
2240 : : {
2241 : : struct sta_info *sta;
2242 : :
2243 : 0 : sta = ap_get_sta(hapd, src);
2244 [ # # ][ # # ]: 0 : if (sta && (sta->flags & WLAN_STA_ASSOC)) {
2245 [ # # ]: 0 : if (!hapd->conf->wds_sta)
2246 : 0 : return;
2247 : :
2248 [ # # ][ # # ]: 0 : if (wds && !(sta->flags & WLAN_STA_WDS)) {
2249 : : int ret;
2250 : : char ifname_wds[IFNAMSIZ + 1];
2251 : :
2252 : 0 : wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
2253 : : "STA " MACSTR " (aid %u)",
2254 : 0 : MAC2STR(sta->addr), sta->aid);
2255 : 0 : sta->flags |= WLAN_STA_WDS;
2256 : 0 : ret = hostapd_set_wds_sta(hapd, ifname_wds,
2257 : 0 : sta->addr, sta->aid, 1);
2258 [ # # ]: 0 : if (!ret)
2259 : 0 : hostapd_set_wds_encryption(hapd, sta,
2260 : : ifname_wds);
2261 : : }
2262 : 0 : return;
2263 : : }
2264 : :
2265 : 0 : wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
2266 : 0 : MACSTR, MAC2STR(src));
2267 [ # # ]: 0 : if (src[0] & 0x01) {
2268 : : /* Broadcast bit set in SA?! Ignore the frame silently. */
2269 : 0 : return;
2270 : : }
2271 : :
2272 [ # # ][ # # ]: 0 : if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
2273 : 0 : wpa_printf(MSG_DEBUG, "Association Response to the STA has "
2274 : : "already been sent, but no TX status yet known - "
2275 : : "ignore Class 3 frame issue with " MACSTR,
2276 : 0 : MAC2STR(src));
2277 : 0 : return;
2278 : : }
2279 : :
2280 [ # # ][ # # ]: 0 : if (sta && (sta->flags & WLAN_STA_AUTH))
2281 : 0 : hostapd_drv_sta_disassoc(
2282 : : hapd, src,
2283 : : WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
2284 : : else
2285 : 0 : hostapd_drv_sta_deauth(
2286 : : hapd, src,
2287 : : WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
2288 : : }
2289 : :
2290 : :
2291 : : #endif /* CONFIG_NATIVE_WINDOWS */
|