]> git.ipfire.org Git - thirdparty/hostap.git/blame - hostapd/ieee802_11.c
Mark IE input to hostapd_eid_wmm_valid() const
[thirdparty/hostap.git] / hostapd / ieee802_11.c
CommitLineData
6fc6879b
JM
1/*
2 * hostapd / IEEE 802.11 Management
a49148fd 3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
71b6ae14 4 * Copyright (c) 2007-2008, Intel Corporation
6fc6879b
JM
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Alternatively, this software may be distributed under the terms of BSD
11 * license.
12 *
13 * See README and COPYING for more details.
14 */
15
16#include "includes.h"
17
18#ifndef CONFIG_NATIVE_WINDOWS
19
20#include <net/if.h>
21
4dbfe5c5 22#include "common.h"
6fc6879b
JM
23#include "eloop.h"
24#include "hostapd.h"
25#include "ieee802_11.h"
26#include "beacon.h"
27#include "hw_features.h"
28#include "radius/radius.h"
29#include "radius/radius_client.h"
30#include "ieee802_11_auth.h"
bcd154c3 31#include "sta_flags.h"
6fc6879b 32#include "sta_info.h"
ac73690c 33#include "crypto.h"
6fc6879b
JM
34#include "ieee802_1x.h"
35#include "wpa.h"
36#include "wme.h"
37#include "ap_list.h"
38#include "accounting.h"
bfddd95c 39#include "driver_i.h"
6fc6879b 40#include "mlme.h"
90973fb2 41#include "common/wpa_ctrl.h"
6fc6879b
JM
42
43
44u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
45{
46 u8 *pos = eid;
47 int i, num, count;
48
49 if (hapd->iface->current_rates == NULL)
50 return eid;
51
52 *pos++ = WLAN_EID_SUPP_RATES;
53 num = hapd->iface->num_rates;
54 if (num > 8) {
55 /* rest of the rates are encoded in Extended supported
56 * rates element */
57 num = 8;
58 }
59
60 *pos++ = num;
61 count = 0;
62 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
63 i++) {
64 count++;
65 *pos = hapd->iface->current_rates[i].rate / 5;
66 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
67 *pos |= 0x80;
68 pos++;
69 }
70
71 return pos;
72}
73
74
75u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
76{
77 u8 *pos = eid;
78 int i, num, count;
79
80 if (hapd->iface->current_rates == NULL)
81 return eid;
82
83 num = hapd->iface->num_rates;
84 if (num <= 8)
85 return eid;
86 num -= 8;
87
88 *pos++ = WLAN_EID_EXT_SUPP_RATES;
89 *pos++ = num;
90 count = 0;
91 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
92 i++) {
93 count++;
94 if (count <= 8)
95 continue; /* already in SuppRates IE */
96 *pos = hapd->iface->current_rates[i].rate / 5;
97 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
98 *pos |= 0x80;
99 pos++;
100 }
101
102 return pos;
103}
104
105
a49148fd 106u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
de9289c8 107{
9d2a76a2 108#ifdef CONFIG_IEEE80211N
a49148fd 109 struct ieee80211_ht_capabilities *cap;
de9289c8 110 u8 *pos = eid;
edd360e1 111
9d2a76a2 112 if (!hapd->iconf->ieee80211n)
edd360e1
JM
113 return eid;
114
115 *pos++ = WLAN_EID_HT_CAP;
116 *pos++ = sizeof(*cap);
117
a49148fd 118 cap = (struct ieee80211_ht_capabilities *) pos;
edd360e1 119 os_memset(cap, 0, sizeof(*cap));
a49148fd 120 cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab);
be8eb8ab 121 cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params;
08eb154d
JM
122 os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set,
123 16);
edd360e1 124
a49148fd
JM
125 /* TODO: ht_extended_capabilities (now fully disabled) */
126 /* TODO: tx_bf_capability_info (now fully disabled) */
127 /* TODO: asel_capabilities (now fully disabled) */
128
edd360e1
JM
129 pos += sizeof(*cap);
130
de9289c8 131 return pos;
9d2a76a2
JM
132#else /* CONFIG_IEEE80211N */
133 return eid;
134#endif /* CONFIG_IEEE80211N */
de9289c8
JM
135}
136
137
138u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
139{
9d2a76a2 140#ifdef CONFIG_IEEE80211N
edd360e1 141 struct ieee80211_ht_operation *oper;
de9289c8 142 u8 *pos = eid;
edd360e1 143
9d2a76a2 144 if (!hapd->iconf->ieee80211n)
edd360e1
JM
145 return eid;
146
147 *pos++ = WLAN_EID_HT_OPERATION;
148 *pos++ = sizeof(*oper);
149
150 oper = (struct ieee80211_ht_operation *) pos;
151 os_memset(oper, 0, sizeof(*oper));
152
a8d8410e 153 oper->control_chan = hapd->iconf->channel;
edd360e1 154 oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
a8d8410e 155 if (hapd->iconf->secondary_channel == 1)
cd587cce
JM
156 oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
157 HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
a8d8410e 158 if (hapd->iconf->secondary_channel == -1)
cd587cce
JM
159 oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
160 HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
edd360e1
JM
161
162 pos += sizeof(*oper);
163
de9289c8 164 return pos;
9d2a76a2
JM
165#else /* CONFIG_IEEE80211N */
166 return eid;
167#endif /* CONFIG_IEEE80211N */
de9289c8
JM
168}
169
170
9d2a76a2
JM
171#ifdef CONFIG_IEEE80211N
172
de9289c8
JM
173/*
174op_mode
175Set to 0 (HT pure) under the followign conditions
176 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
177 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
178Set to 1 (HT non-member protection) if there may be non-HT STAs
179 in both the primary and the secondary channel
180Set to 2 if only HT STAs are associated in BSS,
181 however and at least one 20 MHz HT STA is associated
182Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
183 (currently non-GF HT station is considered as non-HT STA also)
184*/
185int hostapd_ht_operation_update(struct hostapd_iface *iface)
186{
de9289c8
JM
187 u16 cur_op_mode, new_op_mode;
188 int op_mode_changes = 0;
de9289c8 189
9d2a76a2 190 if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
de9289c8
JM
191 return 0;
192
de9289c8 193 wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
edd360e1 194 __func__, iface->ht_op_mode);
de9289c8 195
edd360e1 196 if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
de9289c8 197 && iface->num_sta_ht_no_gf) {
edd360e1
JM
198 iface->ht_op_mode |=
199 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
de9289c8 200 op_mode_changes++;
edd360e1 201 } else if ((iface->ht_op_mode &
de9289c8
JM
202 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
203 iface->num_sta_ht_no_gf == 0) {
edd360e1
JM
204 iface->ht_op_mode &=
205 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
de9289c8
JM
206 op_mode_changes++;
207 }
208
edd360e1
JM
209 if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
210 (iface->num_sta_no_ht || iface->olbc_ht)) {
211 iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
de9289c8 212 op_mode_changes++;
edd360e1
JM
213 } else if ((iface->ht_op_mode &
214 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
215 (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
216 iface->ht_op_mode &=
217 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
de9289c8
JM
218 op_mode_changes++;
219 }
220
221 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
222 * station is associated. Probably it's a theoretical case, since
223 * it looks like all known HT STAs support greenfield.
224 */
225 new_op_mode = 0;
226 if (iface->num_sta_no_ht ||
edd360e1 227 (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
de9289c8 228 new_op_mode = OP_MODE_MIXED;
9d2a76a2
JM
229 else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
230 && iface->num_sta_ht_20mhz)
de9289c8
JM
231 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
232 else if (iface->olbc_ht)
233 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
234 else
235 new_op_mode = OP_MODE_PURE;
236
edd360e1 237 cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
de9289c8 238 if (cur_op_mode != new_op_mode) {
edd360e1
JM
239 iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
240 iface->ht_op_mode |= new_op_mode;
de9289c8
JM
241 op_mode_changes++;
242 }
243
244 wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
edd360e1 245 __func__, iface->ht_op_mode, op_mode_changes);
de9289c8
JM
246
247 return op_mode_changes;
248}
249
250#endif /* CONFIG_IEEE80211N */
251
252
6fc6879b
JM
253u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
254 int probe)
255{
256 int capab = WLAN_CAPABILITY_ESS;
257 int privacy;
258
259 if (hapd->iface->num_sta_no_short_preamble == 0 &&
260 hapd->iconf->preamble == SHORT_PREAMBLE)
261 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
262
263 privacy = hapd->conf->ssid.wep.keys_set;
264
265 if (hapd->conf->ieee802_1x &&
266 (hapd->conf->default_wep_key_len ||
267 hapd->conf->individual_wep_key_len))
268 privacy = 1;
269
270 if (hapd->conf->wpa)
271 privacy = 1;
272
273 if (sta) {
274 int policy, def_klen;
275 if (probe && sta->ssid_probe) {
276 policy = sta->ssid_probe->security_policy;
277 def_klen = sta->ssid_probe->wep.default_len;
278 } else {
279 policy = sta->ssid->security_policy;
280 def_klen = sta->ssid->wep.default_len;
281 }
282 privacy = policy != SECURITY_PLAINTEXT;
283 if (policy == SECURITY_IEEE_802_1X && def_klen == 0)
284 privacy = 0;
285 }
286
287 if (privacy)
288 capab |= WLAN_CAPABILITY_PRIVACY;
289
290 if (hapd->iface->current_mode &&
291 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
292 hapd->iface->num_sta_no_short_slot_time == 0)
293 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
294
6fc6879b
JM
295 return capab;
296}
297
298
5d22a1d5
JM
299#ifdef CONFIG_IEEE80211W
300static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
301 struct sta_info *sta, u8 *eid)
302{
303 u8 *pos = eid;
45c94154
JM
304 u32 timeout, tu;
305 struct os_time now, passed;
5d22a1d5 306
adddffd1
JM
307 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
308 *pos++ = 5;
309 *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
45c94154
JM
310 os_get_time(&now);
311 os_time_sub(&now, &sta->sa_query_start, &passed);
312 tu = (passed.sec * 1000000 + passed.usec) / 1024;
313 if (hapd->conf->assoc_sa_query_max_timeout > tu)
314 timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
315 else
316 timeout = 0;
317 if (timeout < hapd->conf->assoc_sa_query_max_timeout)
318 timeout++; /* add some extra time for local timers */
5d22a1d5
JM
319 WPA_PUT_LE32(pos, timeout);
320 pos += 4;
321
322 return pos;
323}
324#endif /* CONFIG_IEEE80211W */
325
326
6fc6879b
JM
327void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
328{
329 int i;
330 if (len > HOSTAPD_MAX_SSID_LEN)
331 len = HOSTAPD_MAX_SSID_LEN;
332 for (i = 0; i < len; i++) {
333 if (ssid[i] >= 32 && ssid[i] < 127)
334 buf[i] = ssid[i];
335 else
336 buf[i] = '.';
337 }
338 buf[len] = '\0';
339}
340
341
1c6e69cc
JM
342/**
343 * ieee802_11_send_deauth - Send Deauthentication frame
344 * @hapd: hostapd BSS data
345 * @addr: Address of the destination STA
346 * @reason: Reason code for Deauthentication
347 */
6fc6879b
JM
348void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
349{
350 struct ieee80211_mgmt mgmt;
6fc6879b
JM
351
352 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
353 HOSTAPD_LEVEL_DEBUG,
354 "deauthenticate - reason %d", reason);
6fc6879b
JM
355 os_memset(&mgmt, 0, sizeof(mgmt));
356 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
357 WLAN_FC_STYPE_DEAUTH);
358 os_memcpy(mgmt.da, addr, ETH_ALEN);
359 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
360 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
361 mgmt.u.deauth.reason_code = host_to_le16(reason);
362 if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN +
83421302 363 sizeof(mgmt.u.deauth)) < 0)
6fc6879b
JM
364 perror("ieee802_11_send_deauth: send");
365}
366
367
6fc6879b
JM
368static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
369 u16 auth_transaction, u8 *challenge, int iswep)
370{
371 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
372 HOSTAPD_LEVEL_DEBUG,
373 "authentication (shared key, transaction %d)",
374 auth_transaction);
375
376 if (auth_transaction == 1) {
377 if (!sta->challenge) {
378 /* Generate a pseudo-random challenge */
379 u8 key[8];
380 time_t now;
381 int r;
382 sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
383 if (sta->challenge == NULL)
384 return WLAN_STATUS_UNSPECIFIED_FAILURE;
385
386 now = time(NULL);
387 r = random();
388 os_memcpy(key, &now, 4);
389 os_memcpy(key + 4, &r, 4);
8ef16831
JM
390 rc4_skip(key, sizeof(key), 0,
391 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
6fc6879b
JM
392 }
393 return 0;
394 }
395
396 if (auth_transaction != 3)
397 return WLAN_STATUS_UNSPECIFIED_FAILURE;
398
399 /* Transaction 3 */
400 if (!iswep || !sta->challenge || !challenge ||
401 os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
402 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
403 HOSTAPD_LEVEL_INFO,
404 "shared key authentication - invalid "
405 "challenge-response");
406 return WLAN_STATUS_CHALLENGE_FAIL;
407 }
408
409 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
410 HOSTAPD_LEVEL_DEBUG,
411 "authentication OK (shared key)");
412#ifdef IEEE80211_REQUIRE_AUTH_ACK
413 /* Station will be marked authenticated if it ACKs the
414 * authentication reply. */
415#else
416 sta->flags |= WLAN_STA_AUTH;
417 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
418#endif
419 os_free(sta->challenge);
420 sta->challenge = NULL;
421
422 return 0;
423}
424
425
426static void send_auth_reply(struct hostapd_data *hapd,
427 const u8 *dst, const u8 *bssid,
428 u16 auth_alg, u16 auth_transaction, u16 resp,
429 const u8 *ies, size_t ies_len)
430{
431 struct ieee80211_mgmt *reply;
432 u8 *buf;
433 size_t rlen;
434
435 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
436 buf = os_zalloc(rlen);
437 if (buf == NULL)
438 return;
439
440 reply = (struct ieee80211_mgmt *) buf;
441 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
442 WLAN_FC_STYPE_AUTH);
6fc6879b
JM
443 os_memcpy(reply->da, dst, ETH_ALEN);
444 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
445 os_memcpy(reply->bssid, bssid, ETH_ALEN);
446
447 reply->u.auth.auth_alg = host_to_le16(auth_alg);
448 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
449 reply->u.auth.status_code = host_to_le16(resp);
450
451 if (ies && ies_len)
452 os_memcpy(reply->u.auth.variable, ies, ies_len);
453
454 wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
455 " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
456 MAC2STR(dst), auth_alg, auth_transaction,
457 resp, (unsigned long) ies_len);
83421302 458 if (hostapd_send_mgmt_frame(hapd, reply, rlen) < 0)
6fc6879b
JM
459 perror("send_auth_reply: send");
460
461 os_free(buf);
462}
463
464
465#ifdef CONFIG_IEEE80211R
466static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
467 u16 auth_transaction, u16 status,
468 const u8 *ies, size_t ies_len)
469{
470 struct hostapd_data *hapd = ctx;
471 struct sta_info *sta;
472
473 send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction,
474 status, ies, ies_len);
475
476 if (status != WLAN_STATUS_SUCCESS)
477 return;
478
479 sta = ap_get_sta(hapd, dst);
480 if (sta == NULL)
481 return;
482
483 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
484 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
485 sta->flags |= WLAN_STA_AUTH;
486 mlme_authenticate_indication(hapd, sta);
487}
488#endif /* CONFIG_IEEE80211R */
489
490
491static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
492 size_t len)
493{
494 u16 auth_alg, auth_transaction, status_code;
495 u16 resp = WLAN_STATUS_SUCCESS;
496 struct sta_info *sta = NULL;
497 int res;
498 u16 fc;
499 u8 *challenge = NULL;
500 u32 session_timeout, acct_interim_interval;
501 int vlan_id = 0;
502 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
503 size_t resp_ies_len = 0;
504
505 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
506 printf("handle_auth - too short payload (len=%lu)\n",
507 (unsigned long) len);
508 return;
509 }
510
511 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
512 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
513 status_code = le_to_host16(mgmt->u.auth.status_code);
514 fc = le_to_host16(mgmt->frame_control);
515
516 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
517 2 + WLAN_AUTH_CHALLENGE_LEN &&
518 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
519 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
520 challenge = &mgmt->u.auth.variable[2];
521
522 wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
523 "auth_transaction=%d status_code=%d wep=%d%s",
524 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
525 status_code, !!(fc & WLAN_FC_ISWEP),
526 challenge ? " challenge" : "");
527
6fc6879b
JM
528 if (hapd->tkip_countermeasures) {
529 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
530 goto fail;
531 }
532
533 if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
534 auth_alg == WLAN_AUTH_OPEN) ||
535#ifdef CONFIG_IEEE80211R
536 (hapd->conf->wpa &&
537 (hapd->conf->wpa_key_mgmt &
538 (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) &&
539 auth_alg == WLAN_AUTH_FT) ||
540#endif /* CONFIG_IEEE80211R */
541 ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
542 auth_alg == WLAN_AUTH_SHARED_KEY))) {
543 printf("Unsupported authentication algorithm (%d)\n",
544 auth_alg);
545 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
546 goto fail;
547 }
548
549 if (!(auth_transaction == 1 ||
550 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
551 printf("Unknown authentication transaction number (%d)\n",
552 auth_transaction);
553 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
554 goto fail;
555 }
556
557 if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
558 printf("Station " MACSTR " not allowed to authenticate.\n",
559 MAC2STR(mgmt->sa));
560 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
561 goto fail;
562 }
563
564 res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
565 &session_timeout,
566 &acct_interim_interval, &vlan_id);
567 if (res == HOSTAPD_ACL_REJECT) {
568 printf("Station " MACSTR " not allowed to authenticate.\n",
569 MAC2STR(mgmt->sa));
570 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
571 goto fail;
572 }
573 if (res == HOSTAPD_ACL_PENDING) {
574 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
575 " waiting for an external authentication",
576 MAC2STR(mgmt->sa));
577 /* Authentication code will re-send the authentication frame
578 * after it has received (and cached) information from the
579 * external source. */
580 return;
581 }
582
583 sta = ap_sta_add(hapd, mgmt->sa);
584 if (!sta) {
585 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
586 goto fail;
587 }
588
589 if (vlan_id > 0) {
590 if (hostapd_get_vlan_id_ifname(hapd->conf->vlan,
1066c1ee 591 vlan_id) == NULL) {
6fc6879b
JM
592 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
593 HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
594 "%d received from RADIUS server",
595 vlan_id);
596 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
597 goto fail;
598 }
599 sta->vlan_id = vlan_id;
600 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
601 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
602 }
603
604 sta->flags &= ~WLAN_STA_PREAUTH;
605 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
606
5843e1c9 607 if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
6fc6879b
JM
608 sta->acct_interim_interval = acct_interim_interval;
609 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
610 ap_sta_session_timeout(hapd, sta, session_timeout);
611 else
612 ap_sta_no_session_timeout(hapd, sta);
613
614 switch (auth_alg) {
615 case WLAN_AUTH_OPEN:
616 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
617 HOSTAPD_LEVEL_DEBUG,
618 "authentication OK (open system)");
619#ifdef IEEE80211_REQUIRE_AUTH_ACK
620 /* Station will be marked authenticated if it ACKs the
621 * authentication reply. */
622#else
623 sta->flags |= WLAN_STA_AUTH;
624 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
625 sta->auth_alg = WLAN_AUTH_OPEN;
626 mlme_authenticate_indication(hapd, sta);
627#endif
628 break;
629 case WLAN_AUTH_SHARED_KEY:
630 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
631 fc & WLAN_FC_ISWEP);
632 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
633 mlme_authenticate_indication(hapd, sta);
634 if (sta->challenge && auth_transaction == 1) {
635 resp_ies[0] = WLAN_EID_CHALLENGE;
636 resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
637 os_memcpy(resp_ies + 2, sta->challenge,
638 WLAN_AUTH_CHALLENGE_LEN);
639 resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
640 }
641 break;
642#ifdef CONFIG_IEEE80211R
643 case WLAN_AUTH_FT:
644 sta->auth_alg = WLAN_AUTH_FT;
645 if (sta->wpa_sm == NULL)
646 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
647 sta->addr);
648 if (sta->wpa_sm == NULL) {
649 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
650 "state machine");
651 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
652 goto fail;
653 }
654 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
655 auth_transaction, mgmt->u.auth.variable,
656 len - IEEE80211_HDRLEN -
657 sizeof(mgmt->u.auth),
658 handle_auth_ft_finish, hapd);
659 /* handle_auth_ft_finish() callback will complete auth. */
660 return;
661#endif /* CONFIG_IEEE80211R */
662 }
663
664 fail:
665 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
666 auth_transaction + 1, resp, resp_ies, resp_ies_len);
667}
668
669
d42a62b3
JM
670static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
671{
2991469c
JM
672 int i, j = 32, aid;
673
d42a62b3
JM
674 /* get a unique AID */
675 if (sta->aid > 0) {
676 wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
677 return 0;
678 }
679
2991469c
JM
680 for (i = 0; i < AID_WORDS; i++) {
681 if (hapd->sta_aid[i] == (u32) -1)
682 continue;
683 for (j = 0; j < 32; j++) {
684 if (!(hapd->sta_aid[i] & BIT(j)))
685 break;
686 }
687 if (j < 32)
d42a62b3 688 break;
d42a62b3 689 }
2991469c
JM
690 if (j == 32)
691 return -1;
692 aid = i * 32 + j + 1;
693 if (aid > 2007)
694 return -1;
d42a62b3 695
2991469c
JM
696 sta->aid = aid;
697 hapd->sta_aid[i] |= BIT(j);
d42a62b3
JM
698 wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
699 return 0;
700}
701
702
6fc6879b
JM
703static void handle_assoc(struct hostapd_data *hapd,
704 struct ieee80211_mgmt *mgmt, size_t len, int reassoc)
705{
706 u16 capab_info, listen_interval;
707 u16 resp = WLAN_STATUS_SUCCESS;
708 u8 *pos, *wpa_ie;
709 size_t wpa_ie_len;
710 int send_deauth = 0, send_len, left, i;
711 struct sta_info *sta;
712 struct ieee802_11_elems elems;
f238cf9f 713 u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
6fc6879b
JM
714 struct ieee80211_mgmt *reply;
715
716 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
717 sizeof(mgmt->u.assoc_req))) {
718 printf("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
719 "\n", reassoc, (unsigned long) len);
720 return;
721 }
722
723 if (reassoc) {
724 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
725 listen_interval = le_to_host16(
726 mgmt->u.reassoc_req.listen_interval);
727 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
728 " capab_info=0x%02x listen_interval=%d current_ap="
729 MACSTR,
730 MAC2STR(mgmt->sa), capab_info, listen_interval,
731 MAC2STR(mgmt->u.reassoc_req.current_ap));
732 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
733 pos = mgmt->u.reassoc_req.variable;
734 } else {
735 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
736 listen_interval = le_to_host16(
737 mgmt->u.assoc_req.listen_interval);
738 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
739 " capab_info=0x%02x listen_interval=%d",
740 MAC2STR(mgmt->sa), capab_info, listen_interval);
741 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
742 pos = mgmt->u.assoc_req.variable;
743 }
744
745 sta = ap_get_sta(hapd, mgmt->sa);
746#ifdef CONFIG_IEEE80211R
747 if (sta && sta->auth_alg == WLAN_AUTH_FT &&
748 (sta->flags & WLAN_STA_AUTH) == 0) {
749 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
750 "prior to authentication since it is using "
751 "over-the-DS FT", MAC2STR(mgmt->sa));
752 } else
753#endif /* CONFIG_IEEE80211R */
754 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
755 printf("STA " MACSTR " trying to associate before "
756 "authentication\n", MAC2STR(mgmt->sa));
757 if (sta) {
758 printf(" sta: addr=" MACSTR " aid=%d flags=0x%04x\n",
759 MAC2STR(sta->addr), sta->aid, sta->flags);
760 }
761 send_deauth = 1;
762 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
763 goto fail;
764 }
765
766 if (hapd->tkip_countermeasures) {
767 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
768 goto fail;
769 }
770
b0194fe0
JM
771 if (listen_interval > hapd->conf->max_listen_interval) {
772 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
773 HOSTAPD_LEVEL_DEBUG,
774 "Too large Listen Interval (%d)",
775 listen_interval);
776 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
777 goto fail;
778 }
779
6fc6879b 780 sta->capability = capab_info;
39e50be0 781 sta->listen_interval = listen_interval;
6fc6879b 782
de9289c8
JM
783 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
784 * is used */
3d536eb4
JM
785 if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
786 !elems.ssid) {
6fc6879b
JM
787 printf("STA " MACSTR " sent invalid association request\n",
788 MAC2STR(sta->addr));
789 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
790 goto fail;
791 }
792
793 if (elems.ssid_len != hapd->conf->ssid.ssid_len ||
794 os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 0)
795 {
796 char ssid_txt[33];
797 ieee802_11_print_ssid(ssid_txt, elems.ssid, elems.ssid_len);
798 printf("Station " MACSTR " tried to associate with "
799 "unknown SSID '%s'\n", MAC2STR(sta->addr), ssid_txt);
800 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
801 goto fail;
802 }
803
3ae0800c
JM
804 sta->flags &= ~WLAN_STA_WMM;
805 if (elems.wmm && hapd->conf->wmm_enabled) {
806 if (hostapd_eid_wmm_valid(hapd, elems.wmm, elems.wmm_len))
6fc6879b
JM
807 hostapd_logger(hapd, sta->addr,
808 HOSTAPD_MODULE_WPA,
809 HOSTAPD_LEVEL_DEBUG,
3ae0800c 810 "invalid WMM element in association "
6fc6879b
JM
811 "request");
812 else
3ae0800c 813 sta->flags |= WLAN_STA_WMM;
6fc6879b
JM
814 }
815
816 if (!elems.supp_rates) {
817 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
818 HOSTAPD_LEVEL_DEBUG,
819 "No supported rates element in AssocReq");
820 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
821 goto fail;
822 }
823
824 if (elems.supp_rates_len > sizeof(sta->supported_rates)) {
825 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
826 HOSTAPD_LEVEL_DEBUG,
827 "Invalid supported rates element length %d",
828 elems.supp_rates_len);
829 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
830 goto fail;
831 }
832
833 os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
834 os_memcpy(sta->supported_rates, elems.supp_rates,
835 elems.supp_rates_len);
836 sta->supported_rates_len = elems.supp_rates_len;
837
838 if (elems.ext_supp_rates) {
839 if (elems.supp_rates_len + elems.ext_supp_rates_len >
840 sizeof(sta->supported_rates)) {
841 hostapd_logger(hapd, mgmt->sa,
842 HOSTAPD_MODULE_IEEE80211,
843 HOSTAPD_LEVEL_DEBUG,
844 "Invalid supported rates element length"
845 " %d+%d", elems.supp_rates_len,
846 elems.ext_supp_rates_len);
847 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
848 goto fail;
849 }
850
851 os_memcpy(sta->supported_rates + elems.supp_rates_len,
852 elems.ext_supp_rates, elems.ext_supp_rates_len);
853 sta->supported_rates_len += elems.ext_supp_rates_len;
854 }
855
de9289c8
JM
856#ifdef CONFIG_IEEE80211N
857 /* save HT capabilities in the sta object */
de9289c8 858 if (elems.ht_capabilities &&
f130ba9b 859 elems.ht_capabilities_len >=
a49148fd 860 sizeof(struct ieee80211_ht_capabilities)) {
df84268a
JM
861 if (sta->ht_capabilities) {
862 os_memset(sta->ht_capabilities, 0,
863 sizeof(*sta->ht_capabilities));
864 } else {
865 sta->ht_capabilities =
866 os_zalloc(sizeof(*sta->ht_capabilities));
867 if (sta->ht_capabilities == NULL) {
868 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
869 goto fail;
870 }
871 }
de9289c8 872 sta->flags |= WLAN_STA_HT;
df84268a 873 os_memcpy(sta->ht_capabilities, elems.ht_capabilities,
a49148fd 874 sizeof(struct ieee80211_ht_capabilities));
df84268a 875 } else {
de9289c8 876 sta->flags &= ~WLAN_STA_HT;
df84268a
JM
877 os_free(sta->ht_capabilities);
878 sta->ht_capabilities = NULL;
879 }
de9289c8
JM
880#endif /* CONFIG_IEEE80211N */
881
6fc6879b
JM
882 if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
883 wpa_ie = elems.rsn_ie;
884 wpa_ie_len = elems.rsn_ie_len;
885 } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
886 elems.wpa_ie) {
887 wpa_ie = elems.wpa_ie;
888 wpa_ie_len = elems.wpa_ie_len;
889 } else {
890 wpa_ie = NULL;
891 wpa_ie_len = 0;
892 }
ad08c363 893#ifdef CONFIG_WPS
a8d05fca 894 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
ad08c363
JM
895 if (hapd->conf->wps_state && wpa_ie == NULL) {
896 if (elems.wps_ie) {
897 wpa_printf(MSG_DEBUG, "STA included WPS IE in "
898 "(Re)Association Request - assume WPS is "
899 "used");
900 sta->flags |= WLAN_STA_WPS;
eb76b7e3
JM
901 wpabuf_free(sta->wps_ie);
902 sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4,
903 elems.wps_ie_len - 4);
ad08c363
JM
904 } else {
905 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE "
906 "in (Re)Association Request - possible WPS "
907 "use");
908 sta->flags |= WLAN_STA_MAYBE_WPS;
909 }
910 } else
911#endif /* CONFIG_WPS */
6fc6879b
JM
912 if (hapd->conf->wpa && wpa_ie == NULL) {
913 printf("STA " MACSTR ": No WPA/RSN IE in association "
914 "request\n", MAC2STR(sta->addr));
915 resp = WLAN_STATUS_INVALID_IE;
916 goto fail;
917 }
918
919 if (hapd->conf->wpa && wpa_ie) {
920 int res;
921 wpa_ie -= 2;
922 wpa_ie_len += 2;
923 if (sta->wpa_sm == NULL)
924 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
925 sta->addr);
926 if (sta->wpa_sm == NULL) {
927 printf("Failed to initialize WPA state machine\n");
928 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
929 goto fail;
930 }
931 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
932 wpa_ie, wpa_ie_len,
933 elems.mdie, elems.mdie_len);
934 if (res == WPA_INVALID_GROUP)
935 resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
936 else if (res == WPA_INVALID_PAIRWISE)
937 resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
938 else if (res == WPA_INVALID_AKMP)
939 resp = WLAN_STATUS_AKMP_NOT_VALID;
940 else if (res == WPA_ALLOC_FAIL)
941 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
942#ifdef CONFIG_IEEE80211W
943 else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
9a9876bf 944 resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
6fc6879b 945 else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
9a9876bf 946 resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
6fc6879b
JM
947#endif /* CONFIG_IEEE80211W */
948 else if (res == WPA_INVALID_MDIE)
949 resp = WLAN_STATUS_INVALID_MDIE;
950 else if (res != WPA_IE_OK)
951 resp = WLAN_STATUS_INVALID_IE;
952 if (resp != WLAN_STATUS_SUCCESS)
953 goto fail;
f3f7540e 954#ifdef CONFIG_IEEE80211W
45c94154
JM
955 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
956 sta->sa_query_count > 0)
957 ap_check_sa_query_timeout(hapd, sta);
8f4617c6
JM
958 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
959 (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
5d22a1d5 960 /*
93b76319
JM
961 * STA has already been associated with MFP and SA
962 * Query timeout has not been reached. Reject the
963 * association attempt temporarily and start SA Query,
964 * if one is not pending.
5d22a1d5
JM
965 */
966
93b76319
JM
967 if (sta->sa_query_count == 0)
968 ap_sta_start_sa_query(hapd, sta);
5d22a1d5
JM
969
970 resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
971 goto fail;
972 }
973
f3f7540e
JM
974 if (wpa_auth_uses_mfp(sta->wpa_sm))
975 sta->flags |= WLAN_STA_MFP;
976 else
977 sta->flags &= ~WLAN_STA_MFP;
978#endif /* CONFIG_IEEE80211W */
6fc6879b
JM
979
980#ifdef CONFIG_IEEE80211R
981 if (sta->auth_alg == WLAN_AUTH_FT) {
982 if (!reassoc) {
983 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
984 "to use association (not "
985 "re-association) with FT auth_alg",
986 MAC2STR(sta->addr));
987 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
988 goto fail;
989 }
990
991 resp = wpa_ft_validate_reassoc(sta->wpa_sm, pos, left);
992 if (resp != WLAN_STATUS_SUCCESS)
993 goto fail;
994 }
995#endif /* CONFIG_IEEE80211R */
ff36ff00
JM
996#ifdef CONFIG_IEEE80211N
997 if ((sta->flags & WLAN_STA_HT) &&
998 wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
999 wpa_printf(MSG_DEBUG, "HT: " MACSTR " tried to "
1000 "use TKIP with HT association",
1001 MAC2STR(sta->addr));
1002 resp = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
1003 goto fail;
1004 }
1005#endif /* CONFIG_IEEE80211N */
a8d05fca
JM
1006 } else
1007 wpa_auth_sta_no_wpa(sta->wpa_sm);
6fc6879b 1008
6fc6879b
JM
1009 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
1010 sta->flags |= WLAN_STA_NONERP;
1011 for (i = 0; i < sta->supported_rates_len; i++) {
1012 if ((sta->supported_rates[i] & 0x7f) > 22) {
1013 sta->flags &= ~WLAN_STA_NONERP;
1014 break;
1015 }
1016 }
1017 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
1018 sta->nonerp_set = 1;
1019 hapd->iface->num_sta_non_erp++;
1020 if (hapd->iface->num_sta_non_erp == 1)
1021 ieee802_11_set_beacons(hapd->iface);
1022 }
1023
1024 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
1025 !sta->no_short_slot_time_set) {
1026 sta->no_short_slot_time_set = 1;
1027 hapd->iface->num_sta_no_short_slot_time++;
1028 if (hapd->iface->current_mode->mode ==
1029 HOSTAPD_MODE_IEEE80211G &&
1030 hapd->iface->num_sta_no_short_slot_time == 1)
1031 ieee802_11_set_beacons(hapd->iface);
1032 }
1033
1034 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1035 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
1036 else
1037 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1038
1039 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
1040 !sta->no_short_preamble_set) {
1041 sta->no_short_preamble_set = 1;
1042 hapd->iface->num_sta_no_short_preamble++;
1043 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
1044 && hapd->iface->num_sta_no_short_preamble == 1)
1045 ieee802_11_set_beacons(hapd->iface);
1046 }
1047
2a3c6f50
JM
1048 if (hostapd_get_aid(hapd, sta) < 0) {
1049 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1050 wpa_printf(MSG_ERROR, " no room for more AIDs");
1051 goto fail;
1052 }
1053
de9289c8 1054#ifdef CONFIG_IEEE80211N
df84268a 1055 if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
8725598c 1056 u16 ht_capab = le_to_host16(
df84268a 1057 sta->ht_capabilities->ht_capabilities_info);
8725598c
JM
1058 wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities "
1059 "Info: 0x%04x", MAC2STR(sta->addr), ht_capab);
1060 if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) {
e8ff1e59
JM
1061 if (!sta->no_ht_gf_set) {
1062 sta->no_ht_gf_set = 1;
1063 hapd->iface->num_sta_ht_no_gf++;
1064 }
de9289c8
JM
1065 wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no "
1066 "greenfield, num of non-gf stations %d",
1067 __func__, MAC2STR(sta->addr),
1068 hapd->iface->num_sta_ht_no_gf);
1069 }
8725598c 1070 if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) {
e8ff1e59
JM
1071 if (!sta->ht_20mhz_set) {
1072 sta->ht_20mhz_set = 1;
1073 hapd->iface->num_sta_ht_20mhz++;
1074 }
de9289c8
JM
1075 wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, "
1076 "num of 20MHz HT STAs %d",
1077 __func__, MAC2STR(sta->addr),
1078 hapd->iface->num_sta_ht_20mhz);
1079 }
1080 } else {
e8ff1e59
JM
1081 if (!sta->no_ht_set) {
1082 sta->no_ht_set = 1;
1083 hapd->iface->num_sta_no_ht++;
1084 }
9d2a76a2 1085 if (hapd->iconf->ieee80211n) {
de9289c8
JM
1086 wpa_printf(MSG_DEBUG, "%s STA " MACSTR
1087 " - no HT, num of non-HT stations %d",
1088 __func__, MAC2STR(sta->addr),
1089 hapd->iface->num_sta_no_ht);
1090 }
1091 }
1092
1093 if (hostapd_ht_operation_update(hapd->iface) > 0)
1094 ieee802_11_set_beacons(hapd->iface);
1095#endif /* CONFIG_IEEE80211N */
1096
6fc6879b
JM
1097 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1098 HOSTAPD_LEVEL_DEBUG,
1099 "association OK (aid %d)", sta->aid);
1100 /* Station will be marked associated, after it acknowledges AssocResp
1101 */
1102
6f5c8dbd
JM
1103#ifdef CONFIG_IEEE80211W
1104 if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
1105 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
1106 "SA Query procedure", reassoc ? "re" : "");
1107 /* TODO: Send a protected Disassociate frame to the STA using
1108 * the old key and Reason Code "Previous Authentication no
1109 * longer valid". Make sure this is only sent protected since
1110 * unprotected frame would be received by the STA that is now
1111 * trying to associate.
1112 */
1113 }
1114#endif /* CONFIG_IEEE80211W */
1115
1e858f69
JM
1116 if (reassoc) {
1117 os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap,
1118 ETH_ALEN);
1119 }
1120
6fc6879b
JM
1121 if (sta->last_assoc_req)
1122 os_free(sta->last_assoc_req);
1123 sta->last_assoc_req = os_malloc(len);
1124 if (sta->last_assoc_req)
1125 os_memcpy(sta->last_assoc_req, mgmt, len);
1126
1127 /* Make sure that the previously registered inactivity timer will not
1128 * remove the STA immediately. */
1129 sta->timeout_next = STA_NULLFUNC;
1130
1131 fail:
1132 os_memset(buf, 0, sizeof(buf));
1133 reply = (struct ieee80211_mgmt *) buf;
1134 reply->frame_control =
1135 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1136 (send_deauth ? WLAN_FC_STYPE_DEAUTH :
1137 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
1138 WLAN_FC_STYPE_ASSOC_RESP)));
1139 os_memcpy(reply->da, mgmt->sa, ETH_ALEN);
1140 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
1141 os_memcpy(reply->bssid, mgmt->bssid, ETH_ALEN);
1142
1143 send_len = IEEE80211_HDRLEN;
1144 if (send_deauth) {
1145 send_len += sizeof(reply->u.deauth);
1146 reply->u.deauth.reason_code = host_to_le16(resp);
1147 } else {
1148 u8 *p;
1149 send_len += sizeof(reply->u.assoc_resp);
1150 reply->u.assoc_resp.capab_info =
1151 host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
1152 reply->u.assoc_resp.status_code = host_to_le16(resp);
1153 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0)
1154 | BIT(14) | BIT(15));
1155 /* Supported rates */
1156 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
1157 /* Extended supported rates */
1158 p = hostapd_eid_ext_supp_rates(hapd, p);
3ae0800c
JM
1159 if (sta->flags & WLAN_STA_WMM)
1160 p = hostapd_eid_wmm(hapd, p);
6fc6879b 1161
a49148fd 1162 p = hostapd_eid_ht_capabilities(hapd, p);
9d2a76a2 1163 p = hostapd_eid_ht_operation(hapd, p);
de9289c8 1164
6fc6879b
JM
1165#ifdef CONFIG_IEEE80211R
1166 if (resp == WLAN_STATUS_SUCCESS) {
1167 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
f238cf9f 1168 * Transition Information, RSN, [RIC Response] */
6fc6879b
JM
1169 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
1170 buf + sizeof(buf) - p,
f238cf9f
JM
1171 sta->auth_alg,
1172 pos, left);
6fc6879b
JM
1173 }
1174#endif /* CONFIG_IEEE80211R */
1175
5d22a1d5
JM
1176#ifdef CONFIG_IEEE80211W
1177 if (resp == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
1178 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
1179#endif /* CONFIG_IEEE80211W */
1180
6fc6879b 1181 send_len += p - reply->u.assoc_resp.variable;
6fc6879b
JM
1182 }
1183
83421302 1184 if (hostapd_send_mgmt_frame(hapd, reply, send_len) < 0)
6fc6879b
JM
1185 perror("handle_assoc: send");
1186}
1187
1188
6fc6879b
JM
1189static void handle_disassoc(struct hostapd_data *hapd,
1190 struct ieee80211_mgmt *mgmt, size_t len)
1191{
1192 struct sta_info *sta;
1193
1194 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
1195 printf("handle_disassoc - too short payload (len=%lu)\n",
1196 (unsigned long) len);
1197 return;
1198 }
1199
1200 wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
1201 MAC2STR(mgmt->sa),
1202 le_to_host16(mgmt->u.disassoc.reason_code));
1203
6fc6879b
JM
1204 sta = ap_get_sta(hapd, mgmt->sa);
1205 if (sta == NULL) {
1206 printf("Station " MACSTR " trying to disassociate, but it "
1207 "is not associated.\n", MAC2STR(mgmt->sa));
1208 return;
1209 }
1210
1211 sta->flags &= ~WLAN_STA_ASSOC;
20bd9547
JM
1212 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
1213 MAC2STR(sta->addr));
6fc6879b
JM
1214 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
1215 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1216 HOSTAPD_LEVEL_INFO, "disassociated");
1217 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1218 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1219 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
1220 * authenticated. */
1221 accounting_sta_stop(hapd, sta);
1222 ieee802_1x_free_station(sta);
1223 hostapd_sta_remove(hapd, sta->addr);
1224
1225 if (sta->timeout_next == STA_NULLFUNC ||
1226 sta->timeout_next == STA_DISASSOC) {
1227 sta->timeout_next = STA_DEAUTH;
1228 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
1229 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
1230 hapd, sta);
1231 }
1232
1233 mlme_disassociate_indication(
1234 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
1235}
1236
1237
1238static void handle_deauth(struct hostapd_data *hapd,
1239 struct ieee80211_mgmt *mgmt, size_t len)
1240{
1241 struct sta_info *sta;
1242
1243 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
1244 printf("handle_deauth - too short payload (len=%lu)\n",
1245 (unsigned long) len);
1246 return;
1247 }
1248
1249 wpa_printf(MSG_DEBUG, "deauthentication: STA=" MACSTR
1250 " reason_code=%d",
1251 MAC2STR(mgmt->sa),
1252 le_to_host16(mgmt->u.deauth.reason_code));
1253
6fc6879b
JM
1254 sta = ap_get_sta(hapd, mgmt->sa);
1255 if (sta == NULL) {
1256 printf("Station " MACSTR " trying to deauthenticate, but it "
1257 "is not authenticated.\n", MAC2STR(mgmt->sa));
1258 return;
1259 }
1260
1261 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
20bd9547
JM
1262 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
1263 MAC2STR(sta->addr));
6fc6879b
JM
1264 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
1265 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1266 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
1267 mlme_deauthenticate_indication(
1268 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
1269 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1270 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1271 ap_free_sta(hapd, sta);
1272}
1273
1274
1275static void handle_beacon(struct hostapd_data *hapd,
1276 struct ieee80211_mgmt *mgmt, size_t len,
1277 struct hostapd_frame_info *fi)
1278{
1279 struct ieee802_11_elems elems;
1280
1281 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
1282 printf("handle_beacon - too short payload (len=%lu)\n",
1283 (unsigned long) len);
1284 return;
1285 }
1286
3d536eb4 1287 (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
6fc6879b
JM
1288 len - (IEEE80211_HDRLEN +
1289 sizeof(mgmt->u.beacon)), &elems,
1290 0);
1291
6fc6879b
JM
1292 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
1293}
1294
1295
5d22a1d5 1296#ifdef CONFIG_IEEE80211W
88b4b424
JM
1297
1298/* MLME-SAQuery.request */
1299void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
1300 const u8 *addr, const u8 *trans_id)
1301{
1302 struct ieee80211_mgmt mgmt;
1303 u8 *end;
1304
92305c5d
JM
1305 wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
1306 MACSTR, MAC2STR(addr));
1307 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
1308 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
1309
88b4b424
JM
1310 os_memset(&mgmt, 0, sizeof(mgmt));
1311 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1312 WLAN_FC_STYPE_ACTION);
1313 os_memcpy(mgmt.da, addr, ETH_ALEN);
1314 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
1315 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
1316 mgmt.u.action.category = WLAN_ACTION_SA_QUERY;
1317 mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
1318 os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
1319 WLAN_SA_QUERY_TR_ID_LEN);
1320 end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
83421302 1321 if (hostapd_send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
88b4b424
JM
1322 perror("ieee802_11_send_sa_query_req: send");
1323}
1324
1325
93b76319
JM
1326static void hostapd_sa_query_action(struct hostapd_data *hapd,
1327 struct ieee80211_mgmt *mgmt, size_t len)
5d22a1d5
JM
1328{
1329 struct sta_info *sta;
1330 u8 *end;
1331 int i;
1332
93b76319
JM
1333 end = mgmt->u.action.u.sa_query_resp.trans_id +
1334 WLAN_SA_QUERY_TR_ID_LEN;
5d22a1d5 1335 if (((u8 *) mgmt) + len < end) {
93b76319 1336 wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
5d22a1d5
JM
1337 "frame (len=%lu)", (unsigned long) len);
1338 return;
1339 }
1340
93b76319
JM
1341 if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) {
1342 wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
1343 "Action %d", mgmt->u.action.u.sa_query_resp.action);
5d22a1d5
JM
1344 return;
1345 }
1346
92305c5d
JM
1347 wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
1348 MACSTR, MAC2STR(mgmt->sa));
1349 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
1350 mgmt->u.action.u.sa_query_resp.trans_id,
1351 WLAN_SA_QUERY_TR_ID_LEN);
1352
93b76319 1353 /* MLME-SAQuery.confirm */
5d22a1d5
JM
1354
1355 sta = ap_get_sta(hapd, mgmt->sa);
93b76319 1356 if (sta == NULL || sta->sa_query_trans_id == NULL) {
5d22a1d5 1357 wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
93b76319 1358 "pending SA Query request found");
5d22a1d5
JM
1359 return;
1360 }
1361
93b76319
JM
1362 for (i = 0; i < sta->sa_query_count; i++) {
1363 if (os_memcmp(sta->sa_query_trans_id +
1364 i * WLAN_SA_QUERY_TR_ID_LEN,
1365 mgmt->u.action.u.sa_query_resp.trans_id,
1366 WLAN_SA_QUERY_TR_ID_LEN) == 0)
5d22a1d5
JM
1367 break;
1368 }
1369
93b76319
JM
1370 if (i >= sta->sa_query_count) {
1371 wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
5d22a1d5
JM
1372 "transaction identifier found");
1373 return;
1374 }
1375
1376 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
93b76319
JM
1377 HOSTAPD_LEVEL_DEBUG,
1378 "Reply to pending SA Query received");
1379 ap_sta_stop_sa_query(hapd, sta);
5d22a1d5 1380}
5d22a1d5
JM
1381
1382
c4e281fd
JM
1383static int robust_action_frame(u8 category)
1384{
1385 return category != WLAN_ACTION_PUBLIC &&
1386 category != WLAN_ACTION_HT;
1387}
9f64b827 1388#endif /* CONFIG_IEEE80211W */
c4e281fd
JM
1389
1390
6fc6879b
JM
1391static void handle_action(struct hostapd_data *hapd,
1392 struct ieee80211_mgmt *mgmt, size_t len)
1393{
c4e281fd
JM
1394 struct sta_info *sta;
1395
6fc6879b
JM
1396 if (len < IEEE80211_HDRLEN + 1) {
1397 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1398 HOSTAPD_LEVEL_DEBUG,
1399 "handle_action - too short payload (len=%lu)",
1400 (unsigned long) len);
1401 return;
1402 }
1403
c4e281fd
JM
1404 sta = ap_get_sta(hapd, mgmt->sa);
1405#ifdef CONFIG_IEEE80211W
1406 if (sta && (sta->flags & WLAN_STA_MFP) &&
1407 !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) &&
1408 robust_action_frame(mgmt->u.action.category))) {
1409 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1410 HOSTAPD_LEVEL_DEBUG,
1411 "Dropped unprotected Robust Action frame from "
1412 "an MFP STA");
1413 return;
1414 }
1415#endif /* CONFIG_IEEE80211W */
1416
6fc6879b
JM
1417 switch (mgmt->u.action.category) {
1418#ifdef CONFIG_IEEE80211R
1419 case WLAN_ACTION_FT:
1420 {
6fc6879b
JM
1421 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
1422 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action "
1423 "frame from unassociated STA " MACSTR,
1424 MAC2STR(mgmt->sa));
1425 return;
1426 }
1427
1428 if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
1429 len - IEEE80211_HDRLEN))
1430 break;
1431
1432 return;
1433 }
1434#endif /* CONFIG_IEEE80211R */
c2a71408 1435 case WLAN_ACTION_WMM:
3ae0800c 1436 hostapd_wmm_action(hapd, mgmt, len);
6fc6879b 1437 return;
5d22a1d5 1438#ifdef CONFIG_IEEE80211W
93b76319
JM
1439 case WLAN_ACTION_SA_QUERY:
1440 hostapd_sa_query_action(hapd, mgmt, len);
5d22a1d5
JM
1441 return;
1442#endif /* CONFIG_IEEE80211W */
6fc6879b
JM
1443 }
1444
1445 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1446 HOSTAPD_LEVEL_DEBUG,
1447 "handle_action - unknown action category %d or invalid "
1448 "frame",
1449 mgmt->u.action.category);
1450 if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
1451 !(mgmt->sa[0] & 0x01)) {
1452 /*
1453 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
1454 * Return the Action frame to the source without change
1455 * except that MSB of the Category set to 1.
1456 */
1457 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
1458 "frame back to sender");
1459 os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
1460 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
1461 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
1462 mgmt->u.action.category |= 0x80;
1463
83421302 1464 hostapd_send_mgmt_frame(hapd, mgmt, len);
6fc6879b
JM
1465 }
1466}
1467
1468
1469/**
1470 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
1471 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
1472 * sent to)
1473 * @buf: management frame data (starting from IEEE 802.11 header)
1474 * @len: length of frame data in octets
1475 * @stype: management frame subtype from frame control field
a17df5fb 1476 * @fi: meta data about received frame (signal level, etc.)
6fc6879b
JM
1477 *
1478 * Process all incoming IEEE 802.11 management frames. This will be called for
1479 * each frame received from the kernel driver through wlan#ap interface. In
1480 * addition, it can be called to re-inserted pending frames (e.g., when using
1481 * external RADIUS server as an MAC ACL).
1482 */
1483void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
1484 struct hostapd_frame_info *fi)
1485{
1486 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
1487 int broadcast;
1488
1489 if (stype == WLAN_FC_STYPE_BEACON) {
1490 handle_beacon(hapd, mgmt, len, fi);
1491 return;
1492 }
1493
6fc6879b
JM
1494 broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
1495 mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
1496 mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
1497
1498 if (!broadcast &&
fe2c5241 1499 os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
6fc6879b
JM
1500 printf("MGMT: BSSID=" MACSTR " not our address\n",
1501 MAC2STR(mgmt->bssid));
1502 return;
1503 }
1504
1505
1506 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
1507 handle_probe_req(hapd, mgmt, len);
1508 return;
1509 }
1510
1511 if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
1512 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1513 HOSTAPD_LEVEL_DEBUG,
1514 "MGMT: DA=" MACSTR " not our address",
1515 MAC2STR(mgmt->da));
1516 return;
1517 }
1518
1519 switch (stype) {
1520 case WLAN_FC_STYPE_AUTH:
1521 wpa_printf(MSG_DEBUG, "mgmt::auth");
1522 handle_auth(hapd, mgmt, len);
1523 break;
1524 case WLAN_FC_STYPE_ASSOC_REQ:
1525 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
1526 handle_assoc(hapd, mgmt, len, 0);
1527 break;
6fc6879b
JM
1528 case WLAN_FC_STYPE_REASSOC_REQ:
1529 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
1530 handle_assoc(hapd, mgmt, len, 1);
1531 break;
1532 case WLAN_FC_STYPE_DISASSOC:
1533 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
1534 handle_disassoc(hapd, mgmt, len);
1535 break;
1536 case WLAN_FC_STYPE_DEAUTH:
1537 wpa_printf(MSG_DEBUG, "mgmt::deauth");
1538 handle_deauth(hapd, mgmt, len);
1539 break;
1540 case WLAN_FC_STYPE_ACTION:
1541 wpa_printf(MSG_DEBUG, "mgmt::action");
1542 handle_action(hapd, mgmt, len);
1543 break;
1544 default:
1545 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1546 HOSTAPD_LEVEL_DEBUG,
1547 "unknown mgmt frame subtype %d", stype);
1548 break;
1549 }
1550}
1551
1552
1553static void handle_auth_cb(struct hostapd_data *hapd,
1554 struct ieee80211_mgmt *mgmt,
1555 size_t len, int ok)
1556{
1557 u16 auth_alg, auth_transaction, status_code;
1558 struct sta_info *sta;
1559
1560 if (!ok) {
1561 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1562 HOSTAPD_LEVEL_NOTICE,
1563 "did not acknowledge authentication response");
1564 return;
1565 }
1566
1567 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
1568 printf("handle_auth_cb - too short payload (len=%lu)\n",
1569 (unsigned long) len);
1570 return;
1571 }
1572
1573 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1574 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1575 status_code = le_to_host16(mgmt->u.auth.status_code);
1576
1577 sta = ap_get_sta(hapd, mgmt->da);
1578 if (!sta) {
1579 printf("handle_auth_cb: STA " MACSTR " not found\n",
1580 MAC2STR(mgmt->da));
1581 return;
1582 }
1583
1584 if (status_code == WLAN_STATUS_SUCCESS &&
1585 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
1586 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
1587 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1588 HOSTAPD_LEVEL_INFO, "authenticated");
1589 sta->flags |= WLAN_STA_AUTH;
1590 }
1591}
1592
1593
35463eae 1594#ifdef CONFIG_IEEE80211N
1595static void
1596hostapd_get_ht_capab(struct hostapd_data *hapd,
fc4e2d95
JM
1597 struct ieee80211_ht_capabilities *ht_cap,
1598 struct ieee80211_ht_capabilities *neg_ht_cap)
35463eae 1599{
9510f00f 1600 u16 cap;
35463eae 1601
df84268a
JM
1602 if (ht_cap == NULL)
1603 return;
fc4e2d95
JM
1604 os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
1605 cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
9510f00f
FF
1606 cap &= hapd->iconf->ht_capab;
1607 cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
35463eae 1608
1609 /* FIXME: Rx STBC needs to be handled specially */
9510f00f 1610 cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK);
fc4e2d95 1611 neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
35463eae 1612}
1613#endif /* CONFIG_IEEE80211N */
1614
1615
6fc6879b
JM
1616static void handle_assoc_cb(struct hostapd_data *hapd,
1617 struct ieee80211_mgmt *mgmt,
1618 size_t len, int reassoc, int ok)
1619{
1620 u16 status;
1621 struct sta_info *sta;
1622 int new_assoc = 1;
37d8922e 1623#ifdef CONFIG_IEEE80211N
fc4e2d95 1624 struct ieee80211_ht_capabilities ht_cap;
37d8922e 1625#endif /* CONFIG_IEEE80211N */
fc4e2d95 1626 struct ieee80211_ht_capabilities *ht_cap_ptr = NULL;
eddd8010 1627 int set_flags, flags_and, flags_or;
6fc6879b
JM
1628
1629 if (!ok) {
1630 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1631 HOSTAPD_LEVEL_DEBUG,
1632 "did not acknowledge association response");
1633 return;
1634 }
1635
1636 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
1637 sizeof(mgmt->u.assoc_resp))) {
1638 printf("handle_assoc_cb(reassoc=%d) - too short payload "
1639 "(len=%lu)\n", reassoc, (unsigned long) len);
1640 return;
1641 }
1642
1643 if (reassoc)
1644 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
1645 else
1646 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1647
1648 sta = ap_get_sta(hapd, mgmt->da);
1649 if (!sta) {
1650 printf("handle_assoc_cb: STA " MACSTR " not found\n",
1651 MAC2STR(mgmt->da));
1652 return;
1653 }
1654
1655 if (status != WLAN_STATUS_SUCCESS)
1656 goto fail;
1657
1658 /* Stop previous accounting session, if one is started, and allocate
1659 * new session id for the new session. */
1660 accounting_sta_stop(hapd, sta);
6fc6879b
JM
1661
1662 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1663 HOSTAPD_LEVEL_INFO,
2fc98d02
JM
1664 "associated (aid %d)",
1665 sta->aid);
6fc6879b
JM
1666
1667 if (sta->flags & WLAN_STA_ASSOC)
1668 new_assoc = 0;
1669 sta->flags |= WLAN_STA_ASSOC;
515cf93f
JM
1670 if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) {
1671 /* Open or static WEP; no separate authorization */
1672 sta->flags |= WLAN_STA_AUTHORIZED;
20bd9547
JM
1673 wpa_msg(hapd->msg_ctx, MSG_INFO,
1674 AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
515cf93f 1675 }
6fc6879b
JM
1676
1677 if (reassoc)
1678 mlme_reassociate_indication(hapd, sta);
1679 else
1680 mlme_associate_indication(hapd, sta);
1681
de9289c8 1682#ifdef CONFIG_IEEE80211N
37d8922e
JM
1683 if (sta->flags & WLAN_STA_HT) {
1684 ht_cap_ptr = &ht_cap;
df84268a 1685 hostapd_get_ht_capab(hapd, sta->ht_capabilities, ht_cap_ptr);
37d8922e 1686 }
de9289c8
JM
1687#endif /* CONFIG_IEEE80211N */
1688
5d22a1d5 1689#ifdef CONFIG_IEEE80211W
93b76319 1690 sta->sa_query_timed_out = 0;
5d22a1d5
JM
1691#endif /* CONFIG_IEEE80211W */
1692
c140a228
JM
1693 /*
1694 * Remove the STA entry in order to make sure the STA PS state gets
1695 * cleared and configuration gets updated in case of reassociation back
1696 * to the same AP.
1697 */
1698 hostapd_sta_remove(hapd, sta->addr);
1699
6fc6879b
JM
1700 if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
1701 sta->capability, sta->supported_rates,
de9289c8 1702 sta->supported_rates_len, 0, sta->listen_interval,
37d8922e 1703 ht_cap_ptr))
dc366e8e 1704 {
6fc6879b
JM
1705 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1706 HOSTAPD_LEVEL_NOTICE,
1707 "Could not add STA to kernel driver");
1708 }
1709
1710 if (sta->eapol_sm == NULL) {
1711 /*
1712 * This STA does not use RADIUS server for EAP authentication,
1713 * so bind it to the selected VLAN interface now, since the
1714 * interface selection is not going to change anymore.
1715 */
1716 ap_sta_bind_vlan(hapd, sta, 0);
1717 } else if (sta->vlan_id) {
1718 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
1719 ap_sta_bind_vlan(hapd, sta, 0);
1720 }
eddd8010
JM
1721
1722 set_flags = WLAN_STA_SHORT_PREAMBLE | WLAN_STA_WMM | WLAN_STA_MFP;
8077a800
JM
1723 if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
1724 sta->flags & WLAN_STA_AUTHORIZED)
1725 set_flags |= WLAN_STA_AUTHORIZED;
eddd8010
JM
1726 flags_or = sta->flags & set_flags;
1727 flags_and = sta->flags | ~set_flags;
1728 hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
1729 flags_or, flags_and);
6fc6879b
JM
1730
1731 if (sta->auth_alg == WLAN_AUTH_FT)
1732 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
1733 else
1734 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
1735 hostapd_new_assoc_sta(hapd, sta, !new_assoc);
1736
1737 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
1738
1739 fail:
1740 /* Copy of the association request is not needed anymore */
1741 if (sta->last_assoc_req) {
1742 os_free(sta->last_assoc_req);
1743 sta->last_assoc_req = NULL;
1744 }
1745}
1746
1747
1c6e69cc
JM
1748/**
1749 * ieee802_11_mgmt_cb - Process management frame TX status callback
1750 * @hapd: hostapd BSS data structure (the BSS from which the management frame
1751 * was sent from)
1752 * @buf: management frame data (starting from IEEE 802.11 header)
1753 * @len: length of frame data in octets
1754 * @stype: management frame subtype from frame control field
1755 * @ok: Whether the frame was ACK'ed
1756 */
6fc6879b
JM
1757void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
1758 u16 stype, int ok)
1759{
1760 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
1761
1762 switch (stype) {
1763 case WLAN_FC_STYPE_AUTH:
1764 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
1765 handle_auth_cb(hapd, mgmt, len, ok);
1766 break;
1767 case WLAN_FC_STYPE_ASSOC_RESP:
1768 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
1769 handle_assoc_cb(hapd, mgmt, len, 0, ok);
1770 break;
1771 case WLAN_FC_STYPE_REASSOC_RESP:
1772 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
1773 handle_assoc_cb(hapd, mgmt, len, 1, ok);
1774 break;
1775 case WLAN_FC_STYPE_PROBE_RESP:
1776 wpa_printf(MSG_DEBUG, "mgmt::proberesp cb");
1777 break;
1778 case WLAN_FC_STYPE_DEAUTH:
1779 /* ignore */
1780 break;
5d22a1d5
JM
1781 case WLAN_FC_STYPE_ACTION:
1782 wpa_printf(MSG_DEBUG, "mgmt::action cb");
1783 break;
6fc6879b
JM
1784 default:
1785 printf("unknown mgmt cb frame subtype %d\n", stype);
1786 break;
1787 }
1788}
1789
1790
6fc6879b
JM
1791int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
1792{
1793 /* TODO */
1794 return 0;
1795}
1796
1797
1798int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
1799 char *buf, size_t buflen)
1800{
1801 /* TODO */
1802 return 0;
1803}
1804
1805#endif /* CONFIG_NATIVE_WINDOWS */