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