Added WLAN_STA_MFP flag for driver wrappers so that they can configure the
[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 #ifdef CONFIG_IEEE80211W
1000                 if (wpa_auth_uses_mfp(sta->wpa_sm))
1001                         sta->flags |= WLAN_STA_MFP;
1002                 else
1003                         sta->flags &= ~WLAN_STA_MFP;
1004 #endif /* CONFIG_IEEE80211W */
1005
1006 #ifdef CONFIG_IEEE80211R
1007                 if (sta->auth_alg == WLAN_AUTH_FT) {
1008                         if (!reassoc) {
1009                                 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
1010                                            "to use association (not "
1011                                            "re-association) with FT auth_alg",
1012                                            MAC2STR(sta->addr));
1013                                 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1014                                 goto fail;
1015                         }
1016
1017                         resp = wpa_ft_validate_reassoc(sta->wpa_sm, pos, left);
1018                         if (resp != WLAN_STATUS_SUCCESS)
1019                                 goto fail;
1020                 }
1021 #endif /* CONFIG_IEEE80211R */
1022         }
1023
1024         if (hapd->iface->dfs_enable &&
1025             hapd->iconf->ieee80211h == SPECT_STRICT_BINDING) {
1026                 if (hostapd_check_power_cap(hapd, elems.power_cap,
1027                                             elems.power_cap_len)) {
1028                         resp = WLAN_STATUS_PWR_CAPABILITY_NOT_VALID;
1029                         hostapd_logger(hapd, sta->addr,
1030                                        HOSTAPD_MODULE_IEEE80211,
1031                                        HOSTAPD_LEVEL_DEBUG,
1032                                        "Power capabilities of the station not "
1033                                        "acceptable");
1034                         goto fail;
1035                 }
1036         }
1037
1038         if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
1039                 sta->flags |= WLAN_STA_NONERP;
1040         for (i = 0; i < sta->supported_rates_len; i++) {
1041                 if ((sta->supported_rates[i] & 0x7f) > 22) {
1042                         sta->flags &= ~WLAN_STA_NONERP;
1043                         break;
1044                 }
1045         }
1046         if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
1047                 sta->nonerp_set = 1;
1048                 hapd->iface->num_sta_non_erp++;
1049                 if (hapd->iface->num_sta_non_erp == 1)
1050                         ieee802_11_set_beacons(hapd->iface);
1051         }
1052
1053         if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
1054             !sta->no_short_slot_time_set) {
1055                 sta->no_short_slot_time_set = 1;
1056                 hapd->iface->num_sta_no_short_slot_time++;
1057                 if (hapd->iface->current_mode->mode ==
1058                     HOSTAPD_MODE_IEEE80211G &&
1059                     hapd->iface->num_sta_no_short_slot_time == 1)
1060                         ieee802_11_set_beacons(hapd->iface);
1061         }
1062
1063         if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1064                 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
1065         else
1066                 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1067
1068         if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
1069             !sta->no_short_preamble_set) {
1070                 sta->no_short_preamble_set = 1;
1071                 hapd->iface->num_sta_no_short_preamble++;
1072                 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
1073                     && hapd->iface->num_sta_no_short_preamble == 1)
1074                         ieee802_11_set_beacons(hapd->iface);
1075         }
1076
1077         /* get a unique AID */
1078         if (sta->aid > 0) {
1079                 wpa_printf(MSG_DEBUG, "  old AID %d", sta->aid);
1080         } else {
1081                 for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++)
1082                         if (hapd->sta_aid[sta->aid - 1] == NULL)
1083                                 break;
1084                 if (sta->aid > MAX_AID_TABLE_SIZE) {
1085                         sta->aid = 0;
1086                         resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1087                         wpa_printf(MSG_ERROR, "  no room for more AIDs");
1088                         goto fail;
1089                 } else {
1090                         hapd->sta_aid[sta->aid - 1] = sta;
1091                         wpa_printf(MSG_DEBUG, "  new AID %d", sta->aid);
1092                 }
1093         }
1094
1095         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1096                        HOSTAPD_LEVEL_DEBUG,
1097                        "association OK (aid %d)", sta->aid);
1098         /* Station will be marked associated, after it acknowledges AssocResp
1099          */
1100
1101         if (sta->last_assoc_req)
1102                 os_free(sta->last_assoc_req);
1103         sta->last_assoc_req = os_malloc(len);
1104         if (sta->last_assoc_req)
1105                 os_memcpy(sta->last_assoc_req, mgmt, len);
1106
1107         /* Make sure that the previously registered inactivity timer will not
1108          * remove the STA immediately. */
1109         sta->timeout_next = STA_NULLFUNC;
1110
1111  fail:
1112         os_memset(buf, 0, sizeof(buf));
1113         reply = (struct ieee80211_mgmt *) buf;
1114         reply->frame_control =
1115                 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1116                              (send_deauth ? WLAN_FC_STYPE_DEAUTH :
1117                               (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
1118                                WLAN_FC_STYPE_ASSOC_RESP)));
1119         os_memcpy(reply->da, mgmt->sa, ETH_ALEN);
1120         os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
1121         os_memcpy(reply->bssid, mgmt->bssid, ETH_ALEN);
1122
1123         send_len = IEEE80211_HDRLEN;
1124         if (send_deauth) {
1125                 send_len += sizeof(reply->u.deauth);
1126                 reply->u.deauth.reason_code = host_to_le16(resp);
1127         } else {
1128                 u8 *p;
1129                 send_len += sizeof(reply->u.assoc_resp);
1130                 reply->u.assoc_resp.capab_info =
1131                         host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
1132                 reply->u.assoc_resp.status_code = host_to_le16(resp);
1133                 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0)
1134                                                        | BIT(14) | BIT(15));
1135                 /* Supported rates */
1136                 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
1137                 /* Extended supported rates */
1138                 p = hostapd_eid_ext_supp_rates(hapd, p);
1139                 if (sta->flags & WLAN_STA_WME)
1140                         p = hostapd_eid_wme(hapd, p);
1141
1142 #ifdef CONFIG_IEEE80211R
1143                 if (resp == WLAN_STATUS_SUCCESS) {
1144                         /* IEEE 802.11r: Mobility Domain Information, Fast BSS
1145                          * Transition Information, RSN */
1146                         p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
1147                                                         buf + sizeof(buf) - p,
1148                                                         sta->auth_alg);
1149                 }
1150 #endif /* CONFIG_IEEE80211R */
1151
1152                 send_len += p - reply->u.assoc_resp.variable;
1153
1154                 /* Request TX callback */
1155                 reply->frame_control |= host_to_le16(BIT(1));
1156         }
1157
1158         if (hostapd_send_mgmt_frame(hapd, reply, send_len, 0) < 0)
1159                 perror("handle_assoc: send");
1160 }
1161
1162
1163 static void handle_assoc_resp(struct hostapd_data *hapd,
1164                               struct ieee80211_mgmt *mgmt, size_t len)
1165 {
1166         u16 status_code, aid;
1167
1168         if (hapd->assoc_ap_state != ASSOCIATE) {
1169                 printf("Unexpected association response received from " MACSTR
1170                        "\n", MAC2STR(mgmt->sa));
1171                 return;
1172         }
1173
1174         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp)) {
1175                 printf("handle_assoc_resp - too short payload (len=%lu)\n",
1176                        (unsigned long) len);
1177                 return;
1178         }
1179
1180         if (os_memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0 ||
1181             os_memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0) {
1182                 printf("Received association response from unexpected address "
1183                        "(SA=" MACSTR " BSSID=" MACSTR "\n",
1184                        MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1185                 return;
1186         }
1187
1188         status_code = le_to_host16(mgmt->u.assoc_resp.status_code);
1189         aid = le_to_host16(mgmt->u.assoc_resp.aid);
1190         aid &= ~(BIT(14) | BIT(15));
1191
1192         if (status_code != 0) {
1193                 printf("Association (as station) with AP " MACSTR " failed "
1194                        "(status_code=%d)\n",
1195                        MAC2STR(hapd->conf->assoc_ap_addr), status_code);
1196                 /* Try to authenticate again */
1197                 hapd->assoc_ap_state = AUTHENTICATE;
1198                 eloop_register_timeout(5, 0, ieee802_11_sta_authenticate,
1199                                        hapd, NULL);
1200         }
1201
1202         printf("Associated (as station) with AP " MACSTR " (aid=%d)\n",
1203                MAC2STR(hapd->conf->assoc_ap_addr), aid);
1204         hapd->assoc_ap_aid = aid;
1205         hapd->assoc_ap_state = ASSOCIATED;
1206
1207         if (hostapd_set_assoc_ap(hapd, hapd->conf->assoc_ap_addr)) {
1208                 printf("Could not set associated AP address to kernel "
1209                        "driver.\n");
1210         }
1211 }
1212
1213
1214 static void handle_disassoc(struct hostapd_data *hapd,
1215                             struct ieee80211_mgmt *mgmt, size_t len)
1216 {
1217         struct sta_info *sta;
1218
1219         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
1220                 printf("handle_disassoc - too short payload (len=%lu)\n",
1221                        (unsigned long) len);
1222                 return;
1223         }
1224
1225         wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
1226                    MAC2STR(mgmt->sa),
1227                    le_to_host16(mgmt->u.disassoc.reason_code));
1228
1229         if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
1230             os_memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
1231                 printf("Assoc AP " MACSTR " sent disassociation "
1232                        "(reason_code=%d) - try to authenticate\n",
1233                        MAC2STR(hapd->conf->assoc_ap_addr),
1234                        le_to_host16(mgmt->u.disassoc.reason_code));
1235                 hapd->assoc_ap_state = AUTHENTICATE;
1236                 ieee802_11_sta_authenticate(hapd, NULL);
1237                 eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
1238                                        hapd, NULL);
1239                 return;
1240         }
1241
1242         sta = ap_get_sta(hapd, mgmt->sa);
1243         if (sta == NULL) {
1244                 printf("Station " MACSTR " trying to disassociate, but it "
1245                        "is not associated.\n", MAC2STR(mgmt->sa));
1246                 return;
1247         }
1248
1249         sta->flags &= ~WLAN_STA_ASSOC;
1250         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
1251         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1252                        HOSTAPD_LEVEL_INFO, "disassociated");
1253         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1254         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1255         /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
1256          * authenticated. */
1257         accounting_sta_stop(hapd, sta);
1258         ieee802_1x_free_station(sta);
1259         hostapd_sta_remove(hapd, sta->addr);
1260
1261         if (sta->timeout_next == STA_NULLFUNC ||
1262             sta->timeout_next == STA_DISASSOC) {
1263                 sta->timeout_next = STA_DEAUTH;
1264                 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
1265                 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
1266                                        hapd, sta);
1267         }
1268
1269         mlme_disassociate_indication(
1270                 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
1271 }
1272
1273
1274 static void handle_deauth(struct hostapd_data *hapd,
1275                           struct ieee80211_mgmt *mgmt, size_t len)
1276 {
1277         struct sta_info *sta;
1278
1279         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
1280                 printf("handle_deauth - too short payload (len=%lu)\n",
1281                        (unsigned long) len);
1282                 return;
1283         }
1284
1285         wpa_printf(MSG_DEBUG, "deauthentication: STA=" MACSTR
1286                    " reason_code=%d",
1287                    MAC2STR(mgmt->sa),
1288                    le_to_host16(mgmt->u.deauth.reason_code));
1289
1290         if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
1291             os_memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
1292                 printf("Assoc AP " MACSTR " sent deauthentication "
1293                        "(reason_code=%d) - try to authenticate\n",
1294                        MAC2STR(hapd->conf->assoc_ap_addr),
1295                        le_to_host16(mgmt->u.deauth.reason_code));
1296                 hapd->assoc_ap_state = AUTHENTICATE;
1297                 eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
1298                                        hapd, NULL);
1299                 return;
1300         }
1301
1302         sta = ap_get_sta(hapd, mgmt->sa);
1303         if (sta == NULL) {
1304                 printf("Station " MACSTR " trying to deauthenticate, but it "
1305                        "is not authenticated.\n", MAC2STR(mgmt->sa));
1306                 return;
1307         }
1308
1309         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
1310         wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
1311         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1312                        HOSTAPD_LEVEL_DEBUG, "deauthenticated");
1313         mlme_deauthenticate_indication(
1314                 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
1315         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
1316         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
1317         ap_free_sta(hapd, sta);
1318 }
1319
1320
1321 static void handle_beacon(struct hostapd_data *hapd,
1322                           struct ieee80211_mgmt *mgmt, size_t len,
1323                           struct hostapd_frame_info *fi)
1324 {
1325         struct ieee802_11_elems elems;
1326
1327         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
1328                 printf("handle_beacon - too short payload (len=%lu)\n",
1329                        (unsigned long) len);
1330                 return;
1331         }
1332
1333         (void) ieee802_11_parse_elems(hapd, mgmt->u.beacon.variable,
1334                                       len - (IEEE80211_HDRLEN +
1335                                              sizeof(mgmt->u.beacon)), &elems,
1336                                       0);
1337
1338         if (hapd->assoc_ap_state == WAIT_BEACON &&
1339             os_memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
1340                 if (elems.ssid && elems.ssid_len <= 32) {
1341                         os_memcpy(hapd->assoc_ap_ssid, elems.ssid,
1342                                   elems.ssid_len);
1343                         hapd->assoc_ap_ssid[elems.ssid_len] = '\0';
1344                         hapd->assoc_ap_ssid_len = elems.ssid_len;
1345                 }
1346                 ieee802_11_sta_authenticate(hapd, NULL);
1347         }
1348
1349         ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
1350 }
1351
1352
1353 static void handle_action(struct hostapd_data *hapd,
1354                           struct ieee80211_mgmt *mgmt, size_t len)
1355 {
1356         if (len < IEEE80211_HDRLEN + 1) {
1357                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1358                                HOSTAPD_LEVEL_DEBUG,
1359                                "handle_action - too short payload (len=%lu)",
1360                                (unsigned long) len);
1361                 return;
1362         }
1363
1364         switch (mgmt->u.action.category) {
1365 #ifdef CONFIG_IEEE80211R
1366         case WLAN_ACTION_FT:
1367         {
1368                 struct sta_info *sta;
1369
1370                 sta = ap_get_sta(hapd, mgmt->sa);
1371                 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
1372                         wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action "
1373                                    "frame from unassociated STA " MACSTR,
1374                                    MAC2STR(mgmt->sa));
1375                         return;
1376                 }
1377
1378                 if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
1379                                      len - IEEE80211_HDRLEN))
1380                         break;
1381
1382                 return;
1383         }
1384 #endif /* CONFIG_IEEE80211R */
1385         case WME_ACTION_CATEGORY:
1386                 hostapd_wme_action(hapd, mgmt, len);
1387                 return;
1388         }
1389
1390         hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1391                        HOSTAPD_LEVEL_DEBUG,
1392                        "handle_action - unknown action category %d or invalid "
1393                        "frame",
1394                        mgmt->u.action.category);
1395         if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
1396             !(mgmt->sa[0] & 0x01)) {
1397                 /*
1398                  * IEEE 802.11-REVma/D9.0 - 7.3.1.11
1399                  * Return the Action frame to the source without change
1400                  * except that MSB of the Category set to 1.
1401                  */
1402                 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
1403                            "frame back to sender");
1404                 os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
1405                 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
1406                 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
1407                 mgmt->u.action.category |= 0x80;
1408
1409                 hostapd_send_mgmt_frame(hapd, mgmt, len, 0);
1410         }
1411 }
1412
1413
1414 /**
1415  * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
1416  * @hapd: hostapd BSS data structure (the BSS to which the management frame was
1417  * sent to)
1418  * @buf: management frame data (starting from IEEE 802.11 header)
1419  * @len: length of frame data in octets
1420  * @stype: management frame subtype from frame control field
1421  *
1422  * Process all incoming IEEE 802.11 management frames. This will be called for
1423  * each frame received from the kernel driver through wlan#ap interface. In
1424  * addition, it can be called to re-inserted pending frames (e.g., when using
1425  * external RADIUS server as an MAC ACL).
1426  */
1427 void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
1428                      struct hostapd_frame_info *fi)
1429 {
1430         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
1431         int broadcast;
1432
1433         if (stype == WLAN_FC_STYPE_BEACON) {
1434                 handle_beacon(hapd, mgmt, len, fi);
1435                 return;
1436         }
1437
1438         if (fi && fi->passive_scan)
1439                 return;
1440
1441         broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
1442                 mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
1443                 mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
1444
1445         if (!broadcast &&
1446             os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0 &&
1447             (hapd->assoc_ap_state == DO_NOT_ASSOC ||
1448              os_memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0))
1449         {
1450                 printf("MGMT: BSSID=" MACSTR " not our address\n",
1451                        MAC2STR(mgmt->bssid));
1452                 return;
1453         }
1454
1455
1456         if (stype == WLAN_FC_STYPE_PROBE_REQ) {
1457                 handle_probe_req(hapd, mgmt, len);
1458                 return;
1459         }
1460
1461         if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
1462                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1463                                HOSTAPD_LEVEL_DEBUG,
1464                                "MGMT: DA=" MACSTR " not our address",
1465                                MAC2STR(mgmt->da));
1466                 return;
1467         }
1468
1469         switch (stype) {
1470         case WLAN_FC_STYPE_AUTH:
1471                 wpa_printf(MSG_DEBUG, "mgmt::auth");
1472                 handle_auth(hapd, mgmt, len);
1473                 break;
1474         case WLAN_FC_STYPE_ASSOC_REQ:
1475                 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
1476                 handle_assoc(hapd, mgmt, len, 0);
1477                 break;
1478         case WLAN_FC_STYPE_ASSOC_RESP:
1479                 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp");
1480                 handle_assoc_resp(hapd, mgmt, len);
1481                 break;
1482         case WLAN_FC_STYPE_REASSOC_REQ:
1483                 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
1484                 handle_assoc(hapd, mgmt, len, 1);
1485                 break;
1486         case WLAN_FC_STYPE_DISASSOC:
1487                 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
1488                 handle_disassoc(hapd, mgmt, len);
1489                 break;
1490         case WLAN_FC_STYPE_DEAUTH:
1491                 wpa_printf(MSG_DEBUG, "mgmt::deauth");
1492                 handle_deauth(hapd, mgmt, len);
1493                 break;
1494         case WLAN_FC_STYPE_ACTION:
1495                 wpa_printf(MSG_DEBUG, "mgmt::action");
1496                 handle_action(hapd, mgmt, len);
1497                 break;
1498         default:
1499                 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
1500                                HOSTAPD_LEVEL_DEBUG,
1501                                "unknown mgmt frame subtype %d", stype);
1502                 break;
1503         }
1504 }
1505
1506
1507 static void handle_auth_cb(struct hostapd_data *hapd,
1508                            struct ieee80211_mgmt *mgmt,
1509                            size_t len, int ok)
1510 {
1511         u16 auth_alg, auth_transaction, status_code;
1512         struct sta_info *sta;
1513
1514         if (!ok) {
1515                 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1516                                HOSTAPD_LEVEL_NOTICE,
1517                                "did not acknowledge authentication response");
1518                 return;
1519         }
1520
1521         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
1522                 printf("handle_auth_cb - too short payload (len=%lu)\n",
1523                        (unsigned long) len);
1524                 return;
1525         }
1526
1527         auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1528         auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1529         status_code = le_to_host16(mgmt->u.auth.status_code);
1530
1531         sta = ap_get_sta(hapd, mgmt->da);
1532         if (!sta) {
1533                 printf("handle_auth_cb: STA " MACSTR " not found\n",
1534                        MAC2STR(mgmt->da));
1535                 return;
1536         }
1537
1538         if (status_code == WLAN_STATUS_SUCCESS &&
1539             ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
1540              (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
1541                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1542                                HOSTAPD_LEVEL_INFO, "authenticated");
1543                 sta->flags |= WLAN_STA_AUTH;
1544         }
1545 }
1546
1547
1548 static void handle_assoc_cb(struct hostapd_data *hapd,
1549                             struct ieee80211_mgmt *mgmt,
1550                             size_t len, int reassoc, int ok)
1551 {
1552         u16 status;
1553         struct sta_info *sta;
1554         int new_assoc = 1;
1555
1556         if (!ok) {
1557                 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
1558                                HOSTAPD_LEVEL_DEBUG,
1559                                "did not acknowledge association response");
1560                 return;
1561         }
1562
1563         if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
1564                                       sizeof(mgmt->u.assoc_resp))) {
1565                 printf("handle_assoc_cb(reassoc=%d) - too short payload "
1566                        "(len=%lu)\n", reassoc, (unsigned long) len);
1567                 return;
1568         }
1569
1570         if (reassoc)
1571                 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
1572         else
1573                 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1574
1575         sta = ap_get_sta(hapd, mgmt->da);
1576         if (!sta) {
1577                 printf("handle_assoc_cb: STA " MACSTR " not found\n",
1578                        MAC2STR(mgmt->da));
1579                 return;
1580         }
1581
1582         if (status != WLAN_STATUS_SUCCESS)
1583                 goto fail;
1584
1585         /* Stop previous accounting session, if one is started, and allocate
1586          * new session id for the new session. */
1587         accounting_sta_stop(hapd, sta);
1588         accounting_sta_get_id(hapd, sta);
1589
1590         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1591                        HOSTAPD_LEVEL_INFO,
1592                        "associated (aid %d, accounting session %08X-%08X)",
1593                        sta->aid, sta->acct_session_id_hi,
1594                        sta->acct_session_id_lo);
1595
1596         if (sta->flags & WLAN_STA_ASSOC)
1597                 new_assoc = 0;
1598         sta->flags |= WLAN_STA_ASSOC;
1599
1600         if (reassoc)
1601                 mlme_reassociate_indication(hapd, sta);
1602         else
1603                 mlme_associate_indication(hapd, sta);
1604
1605         if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
1606                             sta->capability, sta->supported_rates,
1607                             sta->supported_rates_len, 0, sta->listen_interval))
1608         {
1609                 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1610                                HOSTAPD_LEVEL_NOTICE,
1611                                "Could not add STA to kernel driver");
1612         }
1613
1614         if (sta->eapol_sm == NULL) {
1615                 /*
1616                  * This STA does not use RADIUS server for EAP authentication,
1617                  * so bind it to the selected VLAN interface now, since the
1618                  * interface selection is not going to change anymore.
1619                  */
1620                 ap_sta_bind_vlan(hapd, sta, 0);
1621         } else if (sta->vlan_id) {
1622                 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
1623                 ap_sta_bind_vlan(hapd, sta, 0);
1624         }
1625         if (sta->flags & WLAN_STA_SHORT_PREAMBLE) {
1626                 hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
1627                                       WLAN_STA_SHORT_PREAMBLE, ~0);
1628         } else {
1629                 hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
1630                                       0, ~WLAN_STA_SHORT_PREAMBLE);
1631         }
1632
1633         if (sta->auth_alg == WLAN_AUTH_FT)
1634                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
1635         else
1636                 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
1637         hostapd_new_assoc_sta(hapd, sta, !new_assoc);
1638
1639         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
1640
1641  fail:
1642         /* Copy of the association request is not needed anymore */
1643         if (sta->last_assoc_req) {
1644                 os_free(sta->last_assoc_req);
1645                 sta->last_assoc_req = NULL;
1646         }
1647 }
1648
1649
1650 void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
1651                         u16 stype, int ok)
1652 {
1653         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
1654
1655         switch (stype) {
1656         case WLAN_FC_STYPE_AUTH:
1657                 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
1658                 handle_auth_cb(hapd, mgmt, len, ok);
1659                 break;
1660         case WLAN_FC_STYPE_ASSOC_RESP:
1661                 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
1662                 handle_assoc_cb(hapd, mgmt, len, 0, ok);
1663                 break;
1664         case WLAN_FC_STYPE_REASSOC_RESP:
1665                 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
1666                 handle_assoc_cb(hapd, mgmt, len, 1, ok);
1667                 break;
1668         case WLAN_FC_STYPE_PROBE_RESP:
1669                 wpa_printf(MSG_DEBUG, "mgmt::proberesp cb");
1670                 break;
1671         case WLAN_FC_STYPE_DEAUTH:
1672                 /* ignore */
1673                 break;
1674         default:
1675                 printf("unknown mgmt cb frame subtype %d\n", stype);
1676                 break;
1677         }
1678 }
1679
1680
1681 static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
1682                                                 void *timeout_ctx)
1683 {
1684         struct hostapd_data *hapd = eloop_ctx;
1685         hapd->tkip_countermeasures = 0;
1686         hostapd_set_countermeasures(hapd, 0);
1687         hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1688                        HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
1689 }
1690
1691
1692 static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
1693 {
1694         struct sta_info *sta;
1695
1696         hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
1697                        HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
1698
1699         wpa_auth_countermeasures_start(hapd->wpa_auth);
1700         hapd->tkip_countermeasures = 1;
1701         hostapd_set_countermeasures(hapd, 1);
1702         wpa_gtk_rekey(hapd->wpa_auth);
1703         eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
1704         eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
1705                                hapd, NULL);
1706         for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
1707                 hostapd_sta_deauth(hapd, sta->addr,
1708                                    WLAN_REASON_MICHAEL_MIC_FAILURE);
1709                 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
1710                                 WLAN_STA_AUTHORIZED);
1711                 hostapd_sta_remove(hapd, sta->addr);
1712         }
1713 }
1714
1715
1716 void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr,
1717                                    int local)
1718 {
1719         time_t now;
1720
1721         if (addr && local) {
1722                 struct sta_info *sta = ap_get_sta(hapd, addr);
1723                 if (sta != NULL) {
1724                         wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
1725                         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
1726                                        HOSTAPD_LEVEL_INFO,
1727                                        "Michael MIC failure detected in "
1728                                        "received frame");
1729                         mlme_michaelmicfailure_indication(hapd, addr);
1730                 } else {
1731                         wpa_printf(MSG_DEBUG,
1732                                    "MLME-MICHAELMICFAILURE.indication "
1733                                    "for not associated STA (" MACSTR
1734                                    ") ignored", MAC2STR(addr));
1735                         return;
1736                 }
1737         }
1738
1739         time(&now);
1740         if (now > hapd->michael_mic_failure + 60) {
1741                 hapd->michael_mic_failures = 1;
1742         } else {
1743                 hapd->michael_mic_failures++;
1744                 if (hapd->michael_mic_failures > 1)
1745                         ieee80211_tkip_countermeasures_start(hapd);
1746         }
1747         hapd->michael_mic_failure = now;
1748 }
1749
1750
1751 int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
1752 {
1753         /* TODO */
1754         return 0;
1755 }
1756
1757
1758 int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
1759                            char *buf, size_t buflen)
1760 {
1761         /* TODO */
1762         return 0;
1763 }
1764
1765 #endif /* CONFIG_NATIVE_WINDOWS */