math.3: Mention f{max,min,dim}.
[dragonfly.git] / contrib / hostapd-0.5.8 / ieee802_11.c
blob6dec2891832097d0a9ef5a07d1f598e412c92d6c
1 /*
2 * hostapd / IEEE 802.11 Management
3 * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #ifndef CONFIG_NATIVE_WINDOWS
19 #include <net/if.h>
21 #include "eloop.h"
22 #include "hostapd.h"
23 #include "ieee802_11.h"
24 #include "beacon.h"
25 #include "hw_features.h"
26 #include "radius.h"
27 #include "radius_client.h"
28 #include "ieee802_11_auth.h"
29 #include "sta_info.h"
30 #include "eapol_sm.h"
31 #include "rc4.h"
32 #include "ieee802_1x.h"
33 #include "wpa.h"
34 #include "wme.h"
35 #include "ap_list.h"
36 #include "accounting.h"
37 #include "driver.h"
38 #include "ieee802_11h.h"
39 #include "mlme.h"
42 u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
44 u8 *pos = eid;
45 int i, num, count;
47 if (hapd->iface->current_rates == NULL)
48 return eid;
50 *pos++ = WLAN_EID_SUPP_RATES;
51 num = hapd->iface->num_rates;
52 if (num > 8) {
53 /* rest of the rates are encoded in Extended supported
54 * rates element */
55 num = 8;
58 *pos++ = num;
59 count = 0;
60 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
61 i++) {
62 count++;
63 *pos = hapd->iface->current_rates[i].rate / 5;
64 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
65 *pos |= 0x80;
66 pos++;
69 return pos;
73 u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
75 u8 *pos = eid;
76 int i, num, count;
78 if (hapd->iface->current_rates == NULL)
79 return eid;
81 num = hapd->iface->num_rates;
82 if (num <= 8)
83 return eid;
84 num -= 8;
86 *pos++ = WLAN_EID_EXT_SUPP_RATES;
87 *pos++ = num;
88 count = 0;
89 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
90 i++) {
91 count++;
92 if (count <= 8)
93 continue; /* already in SuppRates IE */
94 *pos = hapd->iface->current_rates[i].rate / 5;
95 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
96 *pos |= 0x80;
97 pos++;
100 return pos;
104 u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
105 int probe)
107 int capab = WLAN_CAPABILITY_ESS;
108 int privacy;
110 if (hapd->iface->num_sta_no_short_preamble == 0 &&
111 hapd->iconf->preamble == SHORT_PREAMBLE)
112 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
114 privacy = hapd->conf->ssid.wep.keys_set;
116 if (hapd->conf->ieee802_1x &&
117 (hapd->conf->default_wep_key_len ||
118 hapd->conf->individual_wep_key_len))
119 privacy = 1;
121 if (hapd->conf->wpa)
122 privacy = 1;
124 if (sta) {
125 int policy, def_klen;
126 if (probe && sta->ssid_probe) {
127 policy = sta->ssid_probe->security_policy;
128 def_klen = sta->ssid_probe->wep.default_len;
129 } else {
130 policy = sta->ssid->security_policy;
131 def_klen = sta->ssid->wep.default_len;
133 privacy = policy != SECURITY_PLAINTEXT;
134 if (policy == SECURITY_IEEE_802_1X && def_klen == 0)
135 privacy = 0;
138 if (privacy)
139 capab |= WLAN_CAPABILITY_PRIVACY;
141 if (hapd->iface && hapd->iface->current_mode &&
142 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
143 hapd->iface->num_sta_no_short_slot_time == 0)
144 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
146 if (hapd->iface->dfs_enable)
147 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
149 return capab;
153 #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
154 * 00:50:F2 */
156 static int ieee802_11_parse_vendor_specific(struct hostapd_data *hapd,
157 u8 *pos, size_t elen,
158 struct ieee802_11_elems *elems,
159 int show_errors)
161 unsigned int oui;
163 /* first 3 bytes in vendor specific information element are the IEEE
164 * OUI of the vendor. The following byte is used a vendor specific
165 * sub-type. */
166 if (elen < 4) {
167 if (show_errors) {
168 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, "short vendor "
169 "specific information element ignored "
170 "(len=%lu)\n", (unsigned long) elen);
172 return -1;
175 oui = (pos[0] << 16) | (pos[1] << 8) | pos[2];
176 switch (oui) {
177 case OUI_MICROSOFT:
178 /* Microsoft/Wi-Fi information elements are further typed and
179 * subtyped */
180 switch (pos[3]) {
181 case 1:
182 /* Microsoft OUI (00:50:F2) with OUI Type 1:
183 * real WPA information element */
184 elems->wpa_ie = pos;
185 elems->wpa_ie_len = elen;
186 break;
187 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
188 if (elen < 5) {
189 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS,
190 "short WME information element "
191 "ignored (len=%lu)\n",
192 (unsigned long) elen);
193 return -1;
195 switch (pos[4]) {
196 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
197 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
198 elems->wme = pos;
199 elems->wme_len = elen;
200 break;
201 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
202 elems->wme_tspec = pos;
203 elems->wme_tspec_len = elen;
204 break;
205 default:
206 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS,
207 "unknown WME information element"
208 " ignored (subtype=%d "
209 "len=%lu)\n",
210 pos[4], (unsigned long) elen);
211 return -1;
213 break;
214 default:
215 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS,
216 "Unknown Microsoft information element "
217 "ignored (type=%d len=%lu)\n",
218 pos[3], (unsigned long) elen);
219 return -1;
221 break;
223 default:
224 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS,
225 "unknown vendor specific information element "
226 "ignored (vendor OUI %02x:%02x:%02x len=%lu)\n",
227 pos[0], pos[1], pos[2], (unsigned long) elen);
228 return -1;
231 return 0;
235 ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start,
236 size_t len,
237 struct ieee802_11_elems *elems,
238 int show_errors)
240 size_t left = len;
241 u8 *pos = start;
242 int unknown = 0;
244 memset(elems, 0, sizeof(*elems));
246 while (left >= 2) {
247 u8 id, elen;
249 id = *pos++;
250 elen = *pos++;
251 left -= 2;
253 if (elen > left) {
254 if (show_errors) {
255 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
256 "IEEE 802.11 element parse "
257 "failed (id=%d elen=%d "
258 "left=%lu)\n",
259 id, elen, (unsigned long) left);
260 wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
262 return ParseFailed;
265 switch (id) {
266 case WLAN_EID_SSID:
267 elems->ssid = pos;
268 elems->ssid_len = elen;
269 break;
270 case WLAN_EID_SUPP_RATES:
271 elems->supp_rates = pos;
272 elems->supp_rates_len = elen;
273 break;
274 case WLAN_EID_FH_PARAMS:
275 elems->fh_params = pos;
276 elems->fh_params_len = elen;
277 break;
278 case WLAN_EID_DS_PARAMS:
279 elems->ds_params = pos;
280 elems->ds_params_len = elen;
281 break;
282 case WLAN_EID_CF_PARAMS:
283 elems->cf_params = pos;
284 elems->cf_params_len = elen;
285 break;
286 case WLAN_EID_TIM:
287 elems->tim = pos;
288 elems->tim_len = elen;
289 break;
290 case WLAN_EID_IBSS_PARAMS:
291 elems->ibss_params = pos;
292 elems->ibss_params_len = elen;
293 break;
294 case WLAN_EID_CHALLENGE:
295 elems->challenge = pos;
296 elems->challenge_len = elen;
297 break;
298 case WLAN_EID_ERP_INFO:
299 elems->erp_info = pos;
300 elems->erp_info_len = elen;
301 break;
302 case WLAN_EID_EXT_SUPP_RATES:
303 elems->ext_supp_rates = pos;
304 elems->ext_supp_rates_len = elen;
305 break;
306 case WLAN_EID_VENDOR_SPECIFIC:
307 if (ieee802_11_parse_vendor_specific(hapd, pos, elen,
308 elems,
309 show_errors))
310 unknown++;
311 break;
312 case WLAN_EID_RSN:
313 elems->rsn_ie = pos;
314 elems->rsn_ie_len = elen;
315 break;
316 case WLAN_EID_PWR_CAPABILITY:
317 elems->power_cap = pos;
318 elems->power_cap_len = elen;
319 break;
320 case WLAN_EID_SUPPORTED_CHANNELS:
321 elems->supp_channels = pos;
322 elems->supp_channels_len = elen;
323 break;
324 default:
325 unknown++;
326 if (!show_errors)
327 break;
328 HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE,
329 "IEEE 802.11 element parse ignored "
330 "unknown element (id=%d elen=%d)\n",
331 id, elen);
332 break;
335 left -= elen;
336 pos += elen;
339 if (left)
340 return ParseFailed;
342 return unknown ? ParseUnknown : ParseOK;
346 void ieee802_11_print_ssid(const u8 *ssid, u8 len)
348 int i;
349 for (i = 0; i < len; i++) {
350 if (ssid[i] >= 32 && ssid[i] < 127)
351 printf("%c", ssid[i]);
352 else
353 printf("<%02x>", ssid[i]);
358 void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
360 struct ieee80211_mgmt mgmt;
361 char buf[30];
363 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
364 HOSTAPD_LEVEL_DEBUG,
365 "deauthenticate - reason %d", reason);
366 snprintf(buf, sizeof(buf), "SEND-DEAUTHENTICATE %d", reason);
367 memset(&mgmt, 0, sizeof(mgmt));
368 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
369 WLAN_FC_STYPE_DEAUTH);
370 memcpy(mgmt.da, addr, ETH_ALEN);
371 memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
372 memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
373 mgmt.u.deauth.reason_code = host_to_le16(reason);
374 if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN +
375 sizeof(mgmt.u.deauth), 0) < 0)
376 perror("ieee802_11_send_deauth: send");
380 static void ieee802_11_sta_authenticate(void *eloop_ctx, void *timeout_ctx)
382 struct hostapd_data *hapd = eloop_ctx;
383 struct ieee80211_mgmt mgmt;
385 if (hapd->assoc_ap_state == WAIT_BEACON)
386 hapd->assoc_ap_state = AUTHENTICATE;
387 if (hapd->assoc_ap_state != AUTHENTICATE)
388 return;
390 printf("Authenticate with AP " MACSTR " SSID=",
391 MAC2STR(hapd->conf->assoc_ap_addr));
392 ieee802_11_print_ssid((u8 *) hapd->assoc_ap_ssid,
393 hapd->assoc_ap_ssid_len);
394 printf(" (as station)\n");
396 memset(&mgmt, 0, sizeof(mgmt));
397 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
398 WLAN_FC_STYPE_AUTH);
399 /* Request TX callback */
400 mgmt.frame_control |= host_to_le16(BIT(1));
401 memcpy(mgmt.da, hapd->conf->assoc_ap_addr, ETH_ALEN);
402 memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
403 memcpy(mgmt.bssid, hapd->conf->assoc_ap_addr, ETH_ALEN);
404 mgmt.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN);
405 mgmt.u.auth.auth_transaction = host_to_le16(1);
406 mgmt.u.auth.status_code = host_to_le16(0);
407 if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN +
408 sizeof(mgmt.u.auth), 0) < 0)
409 perror("ieee802_11_sta_authenticate: send");
411 /* Try to authenticate again, if this attempt fails or times out. */
412 eloop_register_timeout(5, 0, ieee802_11_sta_authenticate, hapd, NULL);
416 static void ieee802_11_sta_associate(void *eloop_ctx, void *timeout_ctx)
418 struct hostapd_data *hapd = eloop_ctx;
419 u8 buf[256];
420 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
421 u8 *p;
423 if (hapd->assoc_ap_state == AUTHENTICATE)
424 hapd->assoc_ap_state = ASSOCIATE;
425 if (hapd->assoc_ap_state != ASSOCIATE)
426 return;
428 printf("Associate with AP " MACSTR " SSID=",
429 MAC2STR(hapd->conf->assoc_ap_addr));
430 ieee802_11_print_ssid((u8 *) hapd->assoc_ap_ssid,
431 hapd->assoc_ap_ssid_len);
432 printf(" (as station)\n");
434 memset(mgmt, 0, sizeof(*mgmt));
435 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
436 WLAN_FC_STYPE_ASSOC_REQ);
437 /* Request TX callback */
438 mgmt->frame_control |= host_to_le16(BIT(1));
439 memcpy(mgmt->da, hapd->conf->assoc_ap_addr, ETH_ALEN);
440 memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
441 memcpy(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN);
442 mgmt->u.assoc_req.capab_info = host_to_le16(0);
443 mgmt->u.assoc_req.listen_interval = host_to_le16(1);
444 p = &mgmt->u.assoc_req.variable[0];
446 *p++ = WLAN_EID_SSID;
447 *p++ = hapd->assoc_ap_ssid_len;
448 memcpy(p, hapd->assoc_ap_ssid, hapd->assoc_ap_ssid_len);
449 p += hapd->assoc_ap_ssid_len;
451 p = hostapd_eid_supp_rates(hapd, p);
452 p = hostapd_eid_ext_supp_rates(hapd, p);
454 if (hostapd_send_mgmt_frame(hapd, mgmt, p - (u8 *) mgmt, 0) < 0)
455 perror("ieee802_11_sta_associate: send");
457 /* Try to authenticate again, if this attempt fails or times out. */
458 eloop_register_timeout(5, 0, ieee802_11_sta_associate, hapd, NULL);
462 static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
463 u16 auth_transaction, u8 *challenge, int iswep)
465 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
466 HOSTAPD_LEVEL_DEBUG,
467 "authentication (shared key, transaction %d)",
468 auth_transaction);
470 if (auth_transaction == 1) {
471 if (!sta->challenge) {
472 /* Generate a pseudo-random challenge */
473 u8 key[8];
474 time_t now;
475 int r;
476 sta->challenge = wpa_zalloc(WLAN_AUTH_CHALLENGE_LEN);
477 if (sta->challenge == NULL)
478 return WLAN_STATUS_UNSPECIFIED_FAILURE;
480 now = time(NULL);
481 r = random();
482 memcpy(key, &now, 4);
483 memcpy(key + 4, &r, 4);
484 rc4(sta->challenge, WLAN_AUTH_CHALLENGE_LEN,
485 key, sizeof(key));
487 return 0;
490 if (auth_transaction != 3)
491 return WLAN_STATUS_UNSPECIFIED_FAILURE;
493 /* Transaction 3 */
494 if (!iswep || !sta->challenge || !challenge ||
495 memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
496 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
497 HOSTAPD_LEVEL_INFO,
498 "shared key authentication - invalid "
499 "challenge-response");
500 return WLAN_STATUS_CHALLENGE_FAIL;
503 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
504 HOSTAPD_LEVEL_DEBUG,
505 "authentication OK (shared key)");
506 #ifdef IEEE80211_REQUIRE_AUTH_ACK
507 /* Station will be marked authenticated if it ACKs the
508 * authentication reply. */
509 #else
510 sta->flags |= WLAN_STA_AUTH;
511 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
512 #endif
513 free(sta->challenge);
514 sta->challenge = NULL;
516 return 0;
520 static void send_auth_reply(struct hostapd_data *hapd,
521 struct ieee80211_mgmt *mgmt,
522 u16 auth_alg, u16 auth_transaction, u16 resp,
523 u8 *challenge)
525 u8 buf[IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2 +
526 WLAN_AUTH_CHALLENGE_LEN];
527 struct ieee80211_mgmt *reply;
528 size_t rlen;
530 memset(buf, 0, sizeof(buf));
531 reply = (struct ieee80211_mgmt *) buf;
532 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
533 WLAN_FC_STYPE_AUTH);
534 /* Request TX callback */
535 reply->frame_control |= host_to_le16(BIT(1));
536 memcpy(reply->da, mgmt->sa, ETH_ALEN);
537 memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
538 memcpy(reply->bssid, mgmt->bssid, ETH_ALEN);
540 reply->u.auth.auth_alg = host_to_le16(auth_alg);
541 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
542 reply->u.auth.status_code = host_to_le16(resp);
543 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth);
544 if (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 2 &&
545 challenge) {
546 u8 *p = reply->u.auth.variable;
547 *p++ = WLAN_EID_CHALLENGE;
548 *p++ = WLAN_AUTH_CHALLENGE_LEN;
549 memcpy(p, challenge, WLAN_AUTH_CHALLENGE_LEN);
550 rlen += 2 + WLAN_AUTH_CHALLENGE_LEN;
551 } else
552 challenge = NULL;
554 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
555 "authentication reply: STA=" MACSTR " auth_alg=%d "
556 "auth_transaction=%d resp=%d%s\n",
557 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
558 resp, challenge ? " challenge" : "");
559 if (hostapd_send_mgmt_frame(hapd, reply, rlen, 0) < 0)
560 perror("send_auth_reply: send");
564 static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
565 size_t len)
567 u16 auth_alg, auth_transaction, status_code;
568 u16 resp = WLAN_STATUS_SUCCESS;
569 struct sta_info *sta = NULL;
570 int res;
571 u16 fc;
572 u8 *challenge = NULL;
573 u32 session_timeout, acct_interim_interval;
574 int vlan_id = 0;
576 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
577 printf("handle_auth - too short payload (len=%lu)\n",
578 (unsigned long) len);
579 return;
582 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
583 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
584 status_code = le_to_host16(mgmt->u.auth.status_code);
585 fc = le_to_host16(mgmt->frame_control);
587 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
588 2 + WLAN_AUTH_CHALLENGE_LEN &&
589 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
590 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
591 challenge = &mgmt->u.auth.variable[2];
593 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
594 "authentication: STA=" MACSTR " auth_alg=%d "
595 "auth_transaction=%d status_code=%d wep=%d%s\n",
596 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
597 status_code, !!(fc & WLAN_FC_ISWEP),
598 challenge ? " challenge" : "");
600 if (hapd->assoc_ap_state == AUTHENTICATE && auth_transaction == 2 &&
601 memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0 &&
602 memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
603 if (status_code != 0) {
604 printf("Authentication (as station) with AP "
605 MACSTR " failed (status_code=%d)\n",
606 MAC2STR(hapd->conf->assoc_ap_addr),
607 status_code);
608 return;
610 printf("Authenticated (as station) with AP " MACSTR "\n",
611 MAC2STR(hapd->conf->assoc_ap_addr));
612 ieee802_11_sta_associate(hapd, NULL);
613 return;
616 if (hapd->tkip_countermeasures) {
617 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
618 goto fail;
621 if (!(((hapd->conf->auth_algs & HOSTAPD_AUTH_OPEN) &&
622 auth_alg == WLAN_AUTH_OPEN) ||
623 ((hapd->conf->auth_algs & HOSTAPD_AUTH_SHARED_KEY) &&
624 auth_alg == WLAN_AUTH_SHARED_KEY))) {
625 printf("Unsupported authentication algorithm (%d)\n",
626 auth_alg);
627 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
628 goto fail;
631 if (!(auth_transaction == 1 ||
632 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
633 printf("Unknown authentication transaction number (%d)\n",
634 auth_transaction);
635 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
636 goto fail;
639 if (memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
640 printf("Station " MACSTR " not allowed to authenticate.\n",
641 MAC2STR(mgmt->sa));
642 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
643 goto fail;
646 res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
647 &session_timeout,
648 &acct_interim_interval, &vlan_id);
649 if (res == HOSTAPD_ACL_REJECT) {
650 printf("Station " MACSTR " not allowed to authenticate.\n",
651 MAC2STR(mgmt->sa));
652 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
653 goto fail;
655 if (res == HOSTAPD_ACL_PENDING) {
656 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Authentication frame "
657 "from " MACSTR " waiting for an external "
658 "authentication\n", MAC2STR(mgmt->sa));
659 /* Authentication code will re-send the authentication frame
660 * after it has received (and cached) information from the
661 * external source. */
662 return;
665 sta = ap_sta_add(hapd, mgmt->sa);
666 if (!sta) {
667 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
668 goto fail;
671 if (vlan_id > 0) {
672 if (hostapd_get_vlan_id_ifname(hapd->conf->vlan,
673 sta->vlan_id) == NULL) {
674 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
675 HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
676 "%d received from RADIUS server",
677 vlan_id);
678 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
679 goto fail;
681 sta->vlan_id = vlan_id;
682 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
683 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
686 sta->flags &= ~WLAN_STA_PREAUTH;
687 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
689 if (hapd->conf->radius->acct_interim_interval == 0 &&
690 acct_interim_interval)
691 sta->acct_interim_interval = acct_interim_interval;
692 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
693 ap_sta_session_timeout(hapd, sta, session_timeout);
694 else
695 ap_sta_no_session_timeout(hapd, sta);
697 switch (auth_alg) {
698 case WLAN_AUTH_OPEN:
699 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
700 HOSTAPD_LEVEL_DEBUG,
701 "authentication OK (open system)");
702 #ifdef IEEE80211_REQUIRE_AUTH_ACK
703 /* Station will be marked authenticated if it ACKs the
704 * authentication reply. */
705 #else
706 sta->flags |= WLAN_STA_AUTH;
707 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
708 sta->auth_alg = WLAN_AUTH_OPEN;
709 mlme_authenticate_indication(hapd, sta);
710 #endif
711 break;
712 case WLAN_AUTH_SHARED_KEY:
713 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
714 fc & WLAN_FC_ISWEP);
715 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
716 mlme_authenticate_indication(hapd, sta);
717 break;
720 fail:
721 send_auth_reply(hapd, mgmt, auth_alg, auth_transaction + 1, resp,
722 sta ? sta->challenge : NULL);
726 static void handle_assoc(struct hostapd_data *hapd,
727 struct ieee80211_mgmt *mgmt, size_t len, int reassoc)
729 u16 capab_info, listen_interval;
730 u16 resp = WLAN_STATUS_SUCCESS;
731 u8 *pos, *wpa_ie;
732 size_t wpa_ie_len;
733 int send_deauth = 0, send_len, left, i;
734 struct sta_info *sta;
735 struct ieee802_11_elems elems;
737 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
738 sizeof(mgmt->u.assoc_req))) {
739 printf("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
740 "\n", reassoc, (unsigned long) len);
741 return;
744 if (reassoc) {
745 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
746 listen_interval = le_to_host16(
747 mgmt->u.reassoc_req.listen_interval);
748 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
749 "reassociation request: STA=" MACSTR
750 " capab_info=0x%02x "
751 "listen_interval=%d current_ap=" MACSTR "\n",
752 MAC2STR(mgmt->sa), capab_info, listen_interval,
753 MAC2STR(mgmt->u.reassoc_req.current_ap));
754 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
755 pos = mgmt->u.reassoc_req.variable;
756 } else {
757 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
758 listen_interval = le_to_host16(
759 mgmt->u.assoc_req.listen_interval);
760 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
761 "association request: STA=" MACSTR
762 " capab_info=0x%02x listen_interval=%d\n",
763 MAC2STR(mgmt->sa), capab_info, listen_interval);
764 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
765 pos = mgmt->u.assoc_req.variable;
768 sta = ap_get_sta(hapd, mgmt->sa);
769 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
770 printf("STA " MACSTR " trying to associate before "
771 "authentication\n", MAC2STR(mgmt->sa));
772 if (sta) {
773 printf(" sta: addr=" MACSTR " aid=%d flags=0x%04x\n",
774 MAC2STR(sta->addr), sta->aid, sta->flags);
776 send_deauth = 1;
777 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
778 goto fail;
781 if (hapd->tkip_countermeasures) {
782 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
783 goto fail;
786 if (reassoc) {
787 memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap,
788 ETH_ALEN);
791 sta->capability = capab_info;
793 /* followed by SSID and Supported rates */
794 if (ieee802_11_parse_elems(hapd, pos, left, &elems, 1) == ParseFailed
795 || !elems.ssid) {
796 printf("STA " MACSTR " sent invalid association request\n",
797 MAC2STR(sta->addr));
798 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
799 goto fail;
802 if (elems.ssid_len != hapd->conf->ssid.ssid_len ||
803 memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 0) {
804 printf("Station " MACSTR " tried to associate with "
805 "unknown SSID '", MAC2STR(sta->addr));
806 ieee802_11_print_ssid(elems.ssid, elems.ssid_len);
807 printf("'\n");
808 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
809 goto fail;
812 sta->flags &= ~WLAN_STA_WME;
813 if (elems.wme && hapd->conf->wme_enabled) {
814 if (hostapd_eid_wme_valid(hapd, elems.wme, elems.wme_len))
815 hostapd_logger(hapd, sta->addr,
816 HOSTAPD_MODULE_WPA,
817 HOSTAPD_LEVEL_DEBUG,
818 "invalid WME element in association "
819 "request");
820 else
821 sta->flags |= WLAN_STA_WME;
824 if (!elems.supp_rates) {
825 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
826 HOSTAPD_LEVEL_DEBUG,
827 "No supported rates element in AssocReq");
828 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
829 goto fail;
832 if (elems.supp_rates_len > sizeof(sta->supported_rates)) {
833 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
834 HOSTAPD_LEVEL_DEBUG,
835 "Invalid supported rates element length %d",
836 elems.supp_rates_len);
837 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
838 goto fail;
841 memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
842 memcpy(sta->supported_rates, elems.supp_rates, elems.supp_rates_len);
843 sta->supported_rates_len = elems.supp_rates_len;
845 if (elems.ext_supp_rates) {
846 if (elems.supp_rates_len + elems.ext_supp_rates_len >
847 sizeof(sta->supported_rates)) {
848 hostapd_logger(hapd, mgmt->sa,
849 HOSTAPD_MODULE_IEEE80211,
850 HOSTAPD_LEVEL_DEBUG,
851 "Invalid supported rates element length"
852 " %d+%d", elems.supp_rates_len,
853 elems.ext_supp_rates_len);
854 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
855 goto fail;
858 memcpy(sta->supported_rates + elems.supp_rates_len,
859 elems.ext_supp_rates, elems.ext_supp_rates_len);
860 sta->supported_rates_len += elems.ext_supp_rates_len;
863 if ((hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA2) && elems.rsn_ie) {
864 wpa_ie = elems.rsn_ie;
865 wpa_ie_len = elems.rsn_ie_len;
866 } else if ((hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA) &&
867 elems.wpa_ie) {
868 wpa_ie = elems.wpa_ie;
869 wpa_ie_len = elems.wpa_ie_len;
870 } else {
871 wpa_ie = NULL;
872 wpa_ie_len = 0;
874 if (hapd->conf->wpa && wpa_ie == NULL) {
875 printf("STA " MACSTR ": No WPA/RSN IE in association "
876 "request\n", MAC2STR(sta->addr));
877 resp = WLAN_STATUS_INVALID_IE;
878 goto fail;
881 if (hapd->conf->wpa) {
882 int res;
883 wpa_ie -= 2;
884 wpa_ie_len += 2;
885 if (sta->wpa_sm == NULL)
886 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
887 sta->addr);
888 if (sta->wpa_sm == NULL) {
889 printf("Failed to initialize WPA state machine\n");
890 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
891 goto fail;
893 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
894 wpa_ie, wpa_ie_len);
895 if (res == WPA_INVALID_GROUP)
896 resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
897 else if (res == WPA_INVALID_PAIRWISE)
898 resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
899 else if (res == WPA_INVALID_AKMP)
900 resp = WLAN_STATUS_AKMP_NOT_VALID;
901 else if (res == WPA_ALLOC_FAIL)
902 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
903 #ifdef CONFIG_IEEE80211W
904 else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
905 resp = WLAN_STATUS_UNSPECIFIED_FAILURE; /* FIX */
906 else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
907 resp = WLAN_STATUS_UNSPECIFIED_FAILURE; /* FIX */
908 #endif /* CONFIG_IEEE80211W */
909 else if (res != WPA_IE_OK)
910 resp = WLAN_STATUS_INVALID_IE;
911 if (resp != WLAN_STATUS_SUCCESS)
912 goto fail;
915 if (hapd->iface->dfs_enable &&
916 hapd->iconf->ieee80211h == SPECT_STRICT_BINDING) {
917 if (hostapd_check_power_cap(hapd, elems.power_cap,
918 elems.power_cap_len)) {
919 resp = WLAN_STATUS_PWR_CAPABILITY_NOT_VALID;
920 hostapd_logger(hapd, sta->addr,
921 HOSTAPD_MODULE_IEEE80211,
922 HOSTAPD_LEVEL_DEBUG,
923 "Power capabilities of the station not "
924 "acceptable");
925 goto fail;
929 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
930 sta->flags |= WLAN_STA_NONERP;
931 for (i = 0; i < sta->supported_rates_len; i++) {
932 if ((sta->supported_rates[i] & 0x7f) > 22) {
933 sta->flags &= ~WLAN_STA_NONERP;
934 break;
937 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
938 sta->nonerp_set = 1;
939 hapd->iface->num_sta_non_erp++;
940 if (hapd->iface->num_sta_non_erp == 1)
941 ieee802_11_set_beacons(hapd->iface);
944 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
945 !sta->no_short_slot_time_set) {
946 sta->no_short_slot_time_set = 1;
947 hapd->iface->num_sta_no_short_slot_time++;
948 if (hapd->iface->current_mode->mode ==
949 HOSTAPD_MODE_IEEE80211G &&
950 hapd->iface->num_sta_no_short_slot_time == 1)
951 ieee802_11_set_beacons(hapd->iface);
954 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
955 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
956 else
957 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
959 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
960 !sta->no_short_preamble_set) {
961 sta->no_short_preamble_set = 1;
962 hapd->iface->num_sta_no_short_preamble++;
963 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
964 && hapd->iface->num_sta_no_short_preamble == 1)
965 ieee802_11_set_beacons(hapd->iface);
968 /* get a unique AID */
969 if (sta->aid > 0) {
970 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
971 " old AID %d\n", sta->aid);
972 } else {
973 for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++)
974 if (hapd->sta_aid[sta->aid - 1] == NULL)
975 break;
976 if (sta->aid > MAX_AID_TABLE_SIZE) {
977 sta->aid = 0;
978 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
979 printf(" no room for more AIDs\n");
980 goto fail;
981 } else {
982 hapd->sta_aid[sta->aid - 1] = sta;
983 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
984 " new AID %d\n", sta->aid);
988 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
989 HOSTAPD_LEVEL_DEBUG,
990 "association OK (aid %d)", sta->aid);
991 /* Station will be marked associated, after it acknowledges AssocResp
994 if (sta->last_assoc_req)
995 free(sta->last_assoc_req);
996 sta->last_assoc_req = (struct ieee80211_mgmt *) malloc(len);
997 if (sta->last_assoc_req)
998 memcpy(sta->last_assoc_req, mgmt, len);
1000 /* Make sure that the previously registered inactivity timer will not
1001 * remove the STA immediately. */
1002 sta->timeout_next = STA_NULLFUNC;
1004 fail:
1006 /* use the queued buffer for transmission because it is large enough
1007 * and not needed anymore */
1008 mgmt->frame_control =
1009 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1010 (send_deauth ? WLAN_FC_STYPE_DEAUTH :
1011 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
1012 WLAN_FC_STYPE_ASSOC_RESP)));
1013 memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
1014 memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
1015 /* Addr3 = BSSID - already set */
1017 send_len = IEEE80211_HDRLEN;
1018 if (send_deauth) {
1019 send_len += sizeof(mgmt->u.deauth);
1020 mgmt->u.deauth.reason_code = host_to_le16(resp);
1021 } else {
1022 u8 *p;
1023 send_len += sizeof(mgmt->u.assoc_resp);
1024 mgmt->u.assoc_resp.capab_info =
1025 host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
1026 mgmt->u.assoc_resp.status_code = host_to_le16(resp);
1027 mgmt->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0)
1028 | BIT(14) | BIT(15));
1029 /* Supported rates */
1030 p = hostapd_eid_supp_rates(hapd, mgmt->u.assoc_resp.variable);
1031 /* Extended supported rates */
1032 p = hostapd_eid_ext_supp_rates(hapd, p);
1033 if (sta->flags & WLAN_STA_WME)
1034 p = hostapd_eid_wme(hapd, p);
1035 send_len += p - mgmt->u.assoc_resp.variable;
1037 /* Request TX callback */
1038 mgmt->frame_control |= host_to_le16(BIT(1));
1041 if (hostapd_send_mgmt_frame(hapd, mgmt, send_len, 0) < 0)
1042 perror("handle_assoc: send");
1046 static void handle_assoc_resp(struct hostapd_data *hapd,
1047 struct ieee80211_mgmt *mgmt, size_t len)
1049 u16 status_code, aid;
1051 if (hapd->assoc_ap_state != ASSOCIATE) {
1052 printf("Unexpected association response received from " MACSTR
1053 "\n", MAC2STR(mgmt->sa));
1054 return;
1057 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp)) {
1058 printf("handle_assoc_resp - too short payload (len=%lu)\n",
1059 (unsigned long) len);
1060 return;
1063 if (memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0 ||
1064 memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0) {
1065 printf("Received association response from unexpected address "
1066 "(SA=" MACSTR " BSSID=" MACSTR "\n",
1067 MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1068 return;
1071 status_code = le_to_host16(mgmt->u.assoc_resp.status_code);
1072 aid = le_to_host16(mgmt->u.assoc_resp.aid);
1073 aid &= ~(BIT(14) | BIT(15));
1075 if (status_code != 0) {
1076 printf("Association (as station) with AP " MACSTR " failed "
1077 "(status_code=%d)\n",
1078 MAC2STR(hapd->conf->assoc_ap_addr), status_code);
1079 /* Try to authenticate again */
1080 hapd->assoc_ap_state = AUTHENTICATE;
1081 eloop_register_timeout(5, 0, ieee802_11_sta_authenticate,
1082 hapd, NULL);
1085 printf("Associated (as station) with AP " MACSTR " (aid=%d)\n",
1086 MAC2STR(hapd->conf->assoc_ap_addr), aid);
1087 hapd->assoc_ap_aid = aid;
1088 hapd->assoc_ap_state = ASSOCIATED;
1090 if (hostapd_set_assoc_ap(hapd, hapd->conf->assoc_ap_addr)) {
1091 printf("Could not set associated AP address to kernel "
1092 "driver.\n");
1097 static void handle_disassoc(struct hostapd_data *hapd,
1098 struct ieee80211_mgmt *mgmt, size_t len)
1100 struct sta_info *sta;
1102 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
1103 printf("handle_disassoc - too short payload (len=%lu)\n",
1104 (unsigned long) len);
1105 return;
1108 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1109 "disassocation: STA=" MACSTR " reason_code=%d\n",
1110 MAC2STR(mgmt->sa),
1111 le_to_host16(mgmt->u.disassoc.reason_code));
1113 if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
1114 memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
1115 printf("Assoc AP " MACSTR " sent disassociation "
1116 "(reason_code=%d) - try to authenticate\n",
1117 MAC2STR(hapd->conf->assoc_ap_addr),
1118 le_to_host16(mgmt->u.disassoc.reason_code));
1119 hapd->assoc_ap_state = AUTHENTICATE;
1120 ieee802_11_sta_authenticate(hapd, NULL);
1121 eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
1122 hapd, NULL);
1123 return;
1126 sta = ap_get_sta(hapd, mgmt->sa);
1127 if (sta == NULL) {
1128 printf("Station " MACSTR " trying to disassociate, but it "
1129 "is not associated.\n", MAC2STR(mgmt->sa));
1130 return;
1133 sta->flags &= ~WLAN_STA_ASSOC;
1134 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
1135 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1136 HOSTAPD_LEVEL_INFO, "disassociated");
1137 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1138 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1139 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
1140 * authenticated. */
1141 accounting_sta_stop(hapd, sta);
1142 ieee802_1x_free_station(sta);
1143 hostapd_sta_remove(hapd, sta->addr);
1145 if (sta->timeout_next == STA_NULLFUNC ||
1146 sta->timeout_next == STA_DISASSOC) {
1147 sta->timeout_next = STA_DEAUTH;
1148 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
1149 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
1150 hapd, sta);
1153 mlme_disassociate_indication(
1154 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
1158 static void handle_deauth(struct hostapd_data *hapd,
1159 struct ieee80211_mgmt *mgmt, size_t len)
1161 struct sta_info *sta;
1163 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
1164 printf("handle_deauth - too short payload (len=%lu)\n",
1165 (unsigned long) len);
1166 return;
1169 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1170 "deauthentication: STA=" MACSTR " reason_code=%d\n",
1171 MAC2STR(mgmt->sa),
1172 le_to_host16(mgmt->u.deauth.reason_code));
1174 if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
1175 memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
1176 printf("Assoc AP " MACSTR " sent deauthentication "
1177 "(reason_code=%d) - try to authenticate\n",
1178 MAC2STR(hapd->conf->assoc_ap_addr),
1179 le_to_host16(mgmt->u.deauth.reason_code));
1180 hapd->assoc_ap_state = AUTHENTICATE;
1181 eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
1182 hapd, NULL);
1183 return;
1186 sta = ap_get_sta(hapd, mgmt->sa);
1187 if (sta == NULL) {
1188 printf("Station " MACSTR " trying to deauthenticate, but it "
1189 "is not authenticated.\n", MAC2STR(mgmt->sa));
1190 return;
1193 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
1194 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
1195 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1196 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
1197 mlme_deauthenticate_indication(
1198 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
1199 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1200 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1201 ap_free_sta(hapd, sta);
1205 static void handle_beacon(struct hostapd_data *hapd,
1206 struct ieee80211_mgmt *mgmt, size_t len,
1207 struct hostapd_frame_info *fi)
1209 struct ieee802_11_elems elems;
1211 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
1212 printf("handle_beacon - too short payload (len=%lu)\n",
1213 (unsigned long) len);
1214 return;
1217 (void) ieee802_11_parse_elems(hapd, mgmt->u.beacon.variable,
1218 len - (IEEE80211_HDRLEN +
1219 sizeof(mgmt->u.beacon)), &elems,
1222 if (hapd->assoc_ap_state == WAIT_BEACON &&
1223 memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
1224 if (elems.ssid && elems.ssid_len <= 32) {
1225 memcpy(hapd->assoc_ap_ssid, elems.ssid,
1226 elems.ssid_len);
1227 hapd->assoc_ap_ssid[elems.ssid_len] = '\0';
1228 hapd->assoc_ap_ssid_len = elems.ssid_len;
1230 ieee802_11_sta_authenticate(hapd, NULL);
1233 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
1235 if (!HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_EXCESSIVE))
1236 return;
1238 printf("Beacon from " MACSTR, MAC2STR(mgmt->sa));
1239 if (elems.ssid) {
1240 printf(" SSID='");
1241 ieee802_11_print_ssid(elems.ssid, elems.ssid_len);
1242 printf("'");
1244 if (elems.ds_params && elems.ds_params_len == 1)
1245 printf(" CHAN=%d", elems.ds_params[0]);
1246 printf("\n");
1250 static void handle_action(struct hostapd_data *hapd,
1251 struct ieee80211_mgmt *mgmt, size_t len)
1253 if (len < IEEE80211_HDRLEN + 1) {
1254 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1255 HOSTAPD_LEVEL_DEBUG,
1256 "handle_action - too short payload (len=%lu)",
1257 (unsigned long) len);
1258 return;
1261 switch (mgmt->u.action.category) {
1262 case WME_ACTION_CATEGORY:
1263 hostapd_wme_action(hapd, mgmt, len);
1264 return;
1267 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1268 HOSTAPD_LEVEL_DEBUG,
1269 "handle_action - unknown action category %d",
1270 mgmt->u.action.category);
1271 if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
1272 !(mgmt->sa[0] & 0x01)) {
1274 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
1275 * Return the Action frame to the source without change
1276 * except that MSB of the Category set to 1.
1278 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
1279 "frame back to sender");
1280 os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
1281 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
1282 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
1283 mgmt->u.action.category |= 0x80;
1285 hostapd_send_mgmt_frame(hapd, mgmt, len, 0);
1291 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
1292 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
1293 * sent to)
1294 * @buf: management frame data (starting from IEEE 802.11 header)
1295 * @len: length of frame data in octets
1296 * @stype: management frame subtype from frame control field
1298 * Process all incoming IEEE 802.11 management frames. This will be called for
1299 * each frame received from the kernel driver through wlan#ap interface. In
1300 * addition, it can be called to re-inserted pending frames (e.g., when using
1301 * external RADIUS server as an MAC ACL).
1303 void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
1304 struct hostapd_frame_info *fi)
1306 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
1307 int broadcast;
1309 if (stype == WLAN_FC_STYPE_BEACON) {
1310 HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "mgmt::beacon\n");
1311 handle_beacon(hapd, mgmt, len, fi);
1312 return;
1315 if (fi && fi->passive_scan)
1316 return;
1318 broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
1319 mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
1320 mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
1322 if (!broadcast && memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0 &&
1323 (hapd->assoc_ap_state == DO_NOT_ASSOC ||
1324 memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0)) {
1325 printf("MGMT: BSSID=" MACSTR " not our address\n",
1326 MAC2STR(mgmt->bssid));
1327 return;
1331 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
1332 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, "mgmt::probe_req\n");
1333 handle_probe_req(hapd, mgmt, len);
1334 return;
1337 if (memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
1338 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1339 HOSTAPD_LEVEL_DEBUG,
1340 "MGMT: DA=" MACSTR " not our address",
1341 MAC2STR(mgmt->da));
1342 return;
1345 switch (stype) {
1346 case WLAN_FC_STYPE_AUTH:
1347 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::auth\n");
1348 handle_auth(hapd, mgmt, len);
1349 break;
1350 case WLAN_FC_STYPE_ASSOC_REQ:
1351 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::assoc_req\n");
1352 handle_assoc(hapd, mgmt, len, 0);
1353 break;
1354 case WLAN_FC_STYPE_ASSOC_RESP:
1355 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::assoc_resp\n");
1356 handle_assoc_resp(hapd, mgmt, len);
1357 break;
1358 case WLAN_FC_STYPE_REASSOC_REQ:
1359 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::reassoc_req\n");
1360 handle_assoc(hapd, mgmt, len, 1);
1361 break;
1362 case WLAN_FC_STYPE_DISASSOC:
1363 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::disassoc\n");
1364 handle_disassoc(hapd, mgmt, len);
1365 break;
1366 case WLAN_FC_STYPE_DEAUTH:
1367 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::deauth\n");
1368 handle_deauth(hapd, mgmt, len);
1369 break;
1370 case WLAN_FC_STYPE_ACTION:
1371 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::action\n");
1372 handle_action(hapd, mgmt, len);
1373 break;
1374 default:
1375 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1376 HOSTAPD_LEVEL_DEBUG,
1377 "unknown mgmt frame subtype %d", stype);
1378 break;
1383 static void handle_auth_cb(struct hostapd_data *hapd,
1384 struct ieee80211_mgmt *mgmt,
1385 size_t len, int ok)
1387 u16 auth_alg, auth_transaction, status_code;
1388 struct sta_info *sta;
1390 if (!ok) {
1391 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1392 HOSTAPD_LEVEL_NOTICE,
1393 "did not acknowledge authentication response");
1394 return;
1397 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
1398 printf("handle_auth_cb - too short payload (len=%lu)\n",
1399 (unsigned long) len);
1400 return;
1403 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1404 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1405 status_code = le_to_host16(mgmt->u.auth.status_code);
1407 sta = ap_get_sta(hapd, mgmt->da);
1408 if (!sta) {
1409 printf("handle_auth_cb: STA " MACSTR " not found\n",
1410 MAC2STR(mgmt->da));
1411 return;
1414 if (status_code == WLAN_STATUS_SUCCESS &&
1415 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
1416 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
1417 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1418 HOSTAPD_LEVEL_INFO, "authenticated");
1419 sta->flags |= WLAN_STA_AUTH;
1424 static void handle_assoc_cb(struct hostapd_data *hapd,
1425 struct ieee80211_mgmt *mgmt,
1426 size_t len, int reassoc, int ok)
1428 u16 status;
1429 struct sta_info *sta;
1430 int new_assoc = 1;
1432 if (!ok) {
1433 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1434 HOSTAPD_LEVEL_DEBUG,
1435 "did not acknowledge association response");
1436 return;
1439 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
1440 sizeof(mgmt->u.assoc_req))) {
1441 printf("handle_assoc_cb(reassoc=%d) - too short payload "
1442 "(len=%lu)\n", reassoc, (unsigned long) len);
1443 return;
1446 if (reassoc)
1447 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
1448 else
1449 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1451 sta = ap_get_sta(hapd, mgmt->da);
1452 if (!sta) {
1453 printf("handle_assoc_cb: STA " MACSTR " not found\n",
1454 MAC2STR(mgmt->da));
1455 return;
1458 if (status != WLAN_STATUS_SUCCESS)
1459 goto fail;
1461 /* Stop previous accounting session, if one is started, and allocate
1462 * new session id for the new session. */
1463 accounting_sta_stop(hapd, sta);
1464 accounting_sta_get_id(hapd, sta);
1466 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1467 HOSTAPD_LEVEL_INFO,
1468 "associated (aid %d, accounting session %08X-%08X)",
1469 sta->aid, sta->acct_session_id_hi,
1470 sta->acct_session_id_lo);
1472 if (sta->flags & WLAN_STA_ASSOC)
1473 new_assoc = 0;
1474 sta->flags |= WLAN_STA_ASSOC;
1476 if (reassoc)
1477 mlme_reassociate_indication(hapd, sta);
1478 else
1479 mlme_associate_indication(hapd, sta);
1481 if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
1482 sta->capability, sta->supported_rates,
1483 sta->supported_rates_len, 0)) {
1484 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1485 HOSTAPD_LEVEL_NOTICE,
1486 "Could not add STA to kernel driver");
1489 if (sta->eapol_sm == NULL) {
1491 * This STA does not use RADIUS server for EAP authentication,
1492 * so bind it to the selected VLAN interface now, since the
1493 * interface selection is not going to change anymore.
1495 ap_sta_bind_vlan(hapd, sta, 0);
1496 } else if (sta->vlan_id) {
1497 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
1498 ap_sta_bind_vlan(hapd, sta, 0);
1500 if (sta->flags & WLAN_STA_SHORT_PREAMBLE) {
1501 hostapd_sta_set_flags(hapd, sta->addr,
1502 WLAN_STA_SHORT_PREAMBLE, ~0);
1503 } else {
1504 hostapd_sta_set_flags(hapd, sta->addr,
1505 0, ~WLAN_STA_SHORT_PREAMBLE);
1508 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
1509 hostapd_new_assoc_sta(hapd, sta, !new_assoc);
1511 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
1513 fail:
1514 /* Copy of the association request is not needed anymore */
1515 if (sta->last_assoc_req) {
1516 free(sta->last_assoc_req);
1517 sta->last_assoc_req = NULL;
1522 void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
1523 u16 stype, int ok)
1525 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
1527 switch (stype) {
1528 case WLAN_FC_STYPE_AUTH:
1529 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::auth cb\n");
1530 handle_auth_cb(hapd, mgmt, len, ok);
1531 break;
1532 case WLAN_FC_STYPE_ASSOC_RESP:
1533 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1534 "mgmt::assoc_resp cb\n");
1535 handle_assoc_cb(hapd, mgmt, len, 0, ok);
1536 break;
1537 case WLAN_FC_STYPE_REASSOC_RESP:
1538 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1539 "mgmt::reassoc_resp cb\n");
1540 handle_assoc_cb(hapd, mgmt, len, 1, ok);
1541 break;
1542 case WLAN_FC_STYPE_PROBE_RESP:
1543 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::proberesp cb\n");
1544 break;
1545 default:
1546 printf("unknown mgmt cb frame subtype %d\n", stype);
1547 break;
1552 static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
1553 void *timeout_ctx)
1555 struct hostapd_data *hapd = eloop_ctx;
1556 hapd->tkip_countermeasures = 0;
1557 hostapd_set_countermeasures(hapd, 0);
1558 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1559 HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
1563 static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
1565 struct sta_info *sta;
1567 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1568 HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
1570 wpa_auth_countermeasures_start(hapd->wpa_auth);
1571 hapd->tkip_countermeasures = 1;
1572 hostapd_set_countermeasures(hapd, 1);
1573 wpa_gtk_rekey(hapd->wpa_auth);
1574 eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
1575 eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
1576 hapd, NULL);
1577 for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
1578 hostapd_sta_deauth(hapd, sta->addr,
1579 WLAN_REASON_MICHAEL_MIC_FAILURE);
1580 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
1581 WLAN_STA_AUTHORIZED);
1582 hostapd_sta_remove(hapd, sta->addr);
1587 void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr,
1588 int local)
1590 time_t now;
1592 if (addr && local) {
1593 struct sta_info *sta = ap_get_sta(hapd, addr);
1594 if (sta != NULL) {
1595 wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
1596 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
1597 HOSTAPD_LEVEL_INFO,
1598 "Michael MIC failure detected in "
1599 "received frame");
1600 mlme_michaelmicfailure_indication(hapd, addr);
1601 } else {
1602 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1603 "MLME-MICHAELMICFAILURE.indication "
1604 "for not associated STA (" MACSTR
1605 ") ignored\n", MAC2STR(addr));
1606 return;
1610 time(&now);
1611 if (now > hapd->michael_mic_failure + 60) {
1612 hapd->michael_mic_failures = 1;
1613 } else {
1614 hapd->michael_mic_failures++;
1615 if (hapd->michael_mic_failures > 1)
1616 ieee80211_tkip_countermeasures_start(hapd);
1618 hapd->michael_mic_failure = now;
1622 int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
1624 /* TODO */
1625 return 0;
1629 int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
1630 char *buf, size_t buflen)
1632 /* TODO */
1633 return 0;
1636 #endif /* CONFIG_NATIVE_WINDOWS */