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