~ubuntu-branches/ubuntu/precise/wpasupplicant/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/0005-pmkokc-Fix-proactive_key_caching-configuration-to-WPA-code.patch/wpa_supplicant/wpas_glue.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2013-06-12 15:57:50 UTC
  • Revision ID: package-import@ubuntu.com-20130612155750-go9lgylcef8n3f2f
Tags: 0.7.3-6ubuntu2.2
* Multiple patches to reduce the number of disconnections for WPA Enterprise
  roaming and Opportunistic Key Caching. (LP: #1187524)
* In debian/patches:
  0001-sme-fix-retry-after-auth-assoc-timeout-failure.patch,
  0002-sme-optimize-recovery-from-common-load-balancing-mechanisms.patch,
  0003-sme-blacklist-bss-on-first-failure-if-only-a-*.patch,
  0004-sme-extend-load-balancing-optimization-in-bss-blacklisting.patch,
  0005-sme-optimize-recovery-from-association-command-failures.patch,
  0006-sme-add-timers-for-authentication-and-association.patch,
  0007-sme-nl80211-set-cipher-suites.patch:
  Cherry-pick patches fixing SME (Session Management Entity) for the nl80211
  driver, which works as a basis for the OKC patches.
* In debian/patches:
  0001-pmkokc-Set-portValid-TRUE-on-association-for-driver-based-4.patch,
  0002-pmkokc-Clear-WPA-and-EAPOL-state-machine-config-pointer-on-.patch,
  0003-pmkokc-Clear-driver-PMKSA-cache-entry-on-PMKSA-cache-expira.patch,
  0004-pmkokc-Flush-PMKSA-cache-entries-and-invalidate-EAP-state-o.patch,
  0005-pmkokc-Fix-proactive_key_caching-configuration-to-WPA-code.patch,
  0006-pmkokc-RSN-Add-a-debug-message-when-considing-addition-of-O.patch,
  0007-pmkokc-Clear-OKC-based-PMKSA-caching-entries-if-PMK-is-chan.patch,
  0008-pmkokc-Move-wpa_sm_remove_pmkid-call-to-PMKSA-cache-entry-f.patch,
  0009-pmkokc-Use-PMKSA-cache-entries-with-only-a-single-network-c.patch,
  0010-pmkokc-PMKSA-Do-not-evict-active-cache-entry-when-adding-ne.patch,
  0011-pmkokc-PMKSA-Set-cur_pmksa-pointer-during-initial-associati.patch,
  0012-pmkokc-PMKSA-make-deauthentication-due-to-cache-entry-remov.patch,
  0013-pmkokc-PMKSA-update-current-cache-entry-due-to-association-.patch:
  Cherry-pick patches to properly do OKC (Opportunistic Key Caching) which
  helps maintaining connectivity on networks secured with WPA Enterprise,
  especially on nl80211-based drivers -- these patches require SME, and add
  or fix key caching and handling of the cache entries.
* debian/patches/force-enable-okc.patch: force Opportunistic Key Caching to
  be enabled.
* debian/patches/less-aggressive-roaming.patch: use less aggressive roaming
  settings to avoid switching to another AP unnecessarily, when the actual
  signal level difference is small.
* debian/patches/wpa_supplicant-dbus-null-error.patch: Don't send NULL to
  dbus_message_new_error().
* debian/patches/0001-nl80211-Fix-UNSPEC-signal-quality-reporting.patch: fix
  marking qual as invalid rather than signal level.
* debian/patches/wpa_supplicant-squelch-driver-disconnect-spam.patch: recover
  cleanly from streams of disconnect messages (like on iwl3945).
* debian/patches/wpa_supplicant-assoc-timeout.patch: increase association
  timeouts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * WPA Supplicant - Glue code to setup EAPOL and RSN modules
 
3
 * Copyright (c) 2003-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
#include "common.h"
 
18
#include "eapol_supp/eapol_supp_sm.h"
 
19
#include "rsn_supp/wpa.h"
 
20
#include "eloop.h"
 
21
#include "config.h"
 
22
#include "l2_packet/l2_packet.h"
 
23
#include "common/wpa_common.h"
 
24
#include "wpa_supplicant_i.h"
 
25
#include "driver_i.h"
 
26
#include "rsn_supp/pmksa_cache.h"
 
27
#include "mlme.h"
 
28
#include "sme.h"
 
29
#include "common/ieee802_11_defs.h"
 
30
#include "common/wpa_ctrl.h"
 
31
#include "wpas_glue.h"
 
32
#include "wps_supplicant.h"
 
33
#include "bss.h"
 
34
#include "scan.h"
 
35
 
 
36
 
 
37
#ifndef CONFIG_NO_CONFIG_BLOBS
 
38
#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
 
39
static void wpa_supplicant_set_config_blob(void *ctx,
 
40
                                           struct wpa_config_blob *blob)
 
41
{
 
42
        struct wpa_supplicant *wpa_s = ctx;
 
43
        wpa_config_set_blob(wpa_s->conf, blob);
 
44
        if (wpa_s->conf->update_config) {
 
45
                int ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
 
46
                if (ret) {
 
47
                        wpa_printf(MSG_DEBUG, "Failed to update config after "
 
48
                                   "blob set");
 
49
                }
 
50
        }
 
51
}
 
52
 
 
53
 
 
54
static const struct wpa_config_blob *
 
55
wpa_supplicant_get_config_blob(void *ctx, const char *name)
 
56
{
 
57
        struct wpa_supplicant *wpa_s = ctx;
 
58
        return wpa_config_get_blob(wpa_s->conf, name);
 
59
}
 
60
#endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */
 
61
#endif /* CONFIG_NO_CONFIG_BLOBS */
 
62
 
 
63
 
 
64
#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
 
65
static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
 
66
                            const void *data, u16 data_len,
 
67
                            size_t *msg_len, void **data_pos)
 
68
{
 
69
        struct ieee802_1x_hdr *hdr;
 
70
 
 
71
        *msg_len = sizeof(*hdr) + data_len;
 
72
        hdr = os_malloc(*msg_len);
 
73
        if (hdr == NULL)
 
74
                return NULL;
 
75
 
 
76
        hdr->version = wpa_s->conf->eapol_version;
 
77
        hdr->type = type;
 
78
        hdr->length = host_to_be16(data_len);
 
79
 
 
80
        if (data)
 
81
                os_memcpy(hdr + 1, data, data_len);
 
82
        else
 
83
                os_memset(hdr + 1, 0, data_len);
 
84
 
 
85
        if (data_pos)
 
86
                *data_pos = hdr + 1;
 
87
 
 
88
        return (u8 *) hdr;
 
89
}
 
90
 
 
91
 
 
92
/**
 
93
 * wpa_ether_send - Send Ethernet frame
 
94
 * @wpa_s: Pointer to wpa_supplicant data
 
95
 * @dest: Destination MAC address
 
96
 * @proto: Ethertype in host byte order
 
97
 * @buf: Frame payload starting from IEEE 802.1X header
 
98
 * @len: Frame payload length
 
99
 * Returns: >=0 on success, <0 on failure
 
100
 */
 
101
static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
 
102
                          u16 proto, const u8 *buf, size_t len)
 
103
{
 
104
        if (wpa_s->l2) {
 
105
                return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
 
106
        }
 
107
 
 
108
        return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
 
109
}
 
110
#endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
 
111
 
 
112
 
 
113
#ifdef IEEE8021X_EAPOL
 
114
 
 
115
/**
 
116
 * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
 
117
 * @ctx: Pointer to wpa_supplicant data (wpa_s)
 
118
 * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
 
119
 * @buf: EAPOL payload (after IEEE 802.1X header)
 
120
 * @len: EAPOL payload length
 
121
 * Returns: >=0 on success, <0 on failure
 
122
 *
 
123
 * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
 
124
 * to the current Authenticator.
 
125
 */
 
126
static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
 
127
                                     size_t len)
 
128
{
 
129
        struct wpa_supplicant *wpa_s = ctx;
 
130
        u8 *msg, *dst, bssid[ETH_ALEN];
 
131
        size_t msglen;
 
132
        int res;
 
133
 
 
134
        /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
 
135
         * extra copy here */
 
136
 
 
137
        if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
 
138
            wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
 
139
                /* Current SSID is not using IEEE 802.1X/EAP, so drop possible
 
140
                 * EAPOL frames (mainly, EAPOL-Start) from EAPOL state
 
141
                 * machines. */
 
142
                wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X "
 
143
                           "mode (type=%d len=%lu)", type,
 
144
                           (unsigned long) len);
 
145
                return -1;
 
146
        }
 
147
 
 
148
        if (pmksa_cache_get_current(wpa_s->wpa) &&
 
149
            type == IEEE802_1X_TYPE_EAPOL_START) {
 
150
                /* Trying to use PMKSA caching - do not send EAPOL-Start frames
 
151
                 * since they will trigger full EAPOL authentication. */
 
152
                wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send "
 
153
                           "EAPOL-Start");
 
154
                return -1;
 
155
        }
 
156
 
 
157
        if (is_zero_ether_addr(wpa_s->bssid)) {
 
158
                wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
 
159
                           "EAPOL frame");
 
160
                if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
 
161
                    !is_zero_ether_addr(bssid)) {
 
162
                        dst = bssid;
 
163
                        wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
 
164
                                   " from the driver as the EAPOL destination",
 
165
                                   MAC2STR(dst));
 
166
                } else {
 
167
                        dst = wpa_s->last_eapol_src;
 
168
                        wpa_printf(MSG_DEBUG, "Using the source address of the"
 
169
                                   " last received EAPOL frame " MACSTR " as "
 
170
                                   "the EAPOL destination",
 
171
                                   MAC2STR(dst));
 
172
                }
 
173
        } else {
 
174
                /* BSSID was already set (from (Re)Assoc event, so use it as
 
175
                 * the EAPOL destination. */
 
176
                dst = wpa_s->bssid;
 
177
        }
 
178
 
 
179
        msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
 
180
        if (msg == NULL)
 
181
                return -1;
 
182
 
 
183
        wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst));
 
184
        wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
 
185
        res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
 
186
        os_free(msg);
 
187
        return res;
 
188
}
 
189
 
 
190
 
 
191
/**
 
192
 * wpa_eapol_set_wep_key - set WEP key for the driver
 
193
 * @ctx: Pointer to wpa_supplicant data (wpa_s)
 
194
 * @unicast: 1 = individual unicast key, 0 = broadcast key
 
195
 * @keyidx: WEP key index (0..3)
 
196
 * @key: Pointer to key data
 
197
 * @keylen: Key length in bytes
 
198
 * Returns: 0 on success or < 0 on error.
 
199
 */
 
200
static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
 
201
                                 const u8 *key, size_t keylen)
 
202
{
 
203
        struct wpa_supplicant *wpa_s = ctx;
 
204
        if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 
205
                int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
 
206
                        WPA_CIPHER_WEP104;
 
207
                if (unicast)
 
208
                        wpa_s->pairwise_cipher = cipher;
 
209
                else
 
210
                        wpa_s->group_cipher = cipher;
 
211
        }
 
212
        return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
 
213
                               unicast ? wpa_s->bssid :
 
214
                               (u8 *) "\xff\xff\xff\xff\xff\xff",
 
215
                               keyidx, unicast, (u8 *) "", 0, key, keylen);
 
216
}
 
217
 
 
218
 
 
219
static void wpa_supplicant_aborted_cached(void *ctx)
 
220
{
 
221
        struct wpa_supplicant *wpa_s = ctx;
 
222
        wpa_sm_aborted_cached(wpa_s->wpa);
 
223
}
 
224
 
 
225
 
 
226
static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
 
227
                                    void *ctx)
 
228
{
 
229
        struct wpa_supplicant *wpa_s = ctx;
 
230
        int res, pmk_len;
 
231
        u8 pmk[PMK_LEN];
 
232
 
 
233
        wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
 
234
                   success ? "" : "un");
 
235
 
 
236
        if (wpas_wps_eapol_cb(wpa_s) > 0)
 
237
                return;
 
238
 
 
239
        if (!success) {
 
240
                /*
 
241
                 * Make sure we do not get stuck here waiting for long EAPOL
 
242
                 * timeout if the AP does not disconnect in case of
 
243
                 * authentication failure.
 
244
                 */
 
245
                wpa_supplicant_req_auth_timeout(wpa_s, 2, 0);
 
246
        }
 
247
 
 
248
        if (!success || !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
 
249
                return;
 
250
 
 
251
        if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
 
252
                return;
 
253
 
 
254
        wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way "
 
255
                   "handshake");
 
256
 
 
257
        pmk_len = PMK_LEN;
 
258
        res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
 
259
        if (res) {
 
260
                /*
 
261
                 * EAP-LEAP is an exception from other EAP methods: it
 
262
                 * uses only 16-byte PMK.
 
263
                 */
 
264
                res = eapol_sm_get_key(eapol, pmk, 16);
 
265
                pmk_len = 16;
 
266
        }
 
267
 
 
268
        if (res) {
 
269
                wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state "
 
270
                           "machines");
 
271
                return;
 
272
        }
 
273
 
 
274
        if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
 
275
                            pmk_len)) {
 
276
                wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
 
277
        }
 
278
 
 
279
        wpa_supplicant_cancel_scan(wpa_s);
 
280
        wpa_supplicant_cancel_auth_timeout(wpa_s);
 
281
        wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 
282
 
 
283
}
 
284
 
 
285
 
 
286
static void wpa_supplicant_notify_eapol_done(void *ctx)
 
287
{
 
288
        struct wpa_supplicant *wpa_s = ctx;
 
289
        wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
 
290
        if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
 
291
                wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
 
292
        } else {
 
293
                wpa_supplicant_cancel_auth_timeout(wpa_s);
 
294
                wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 
295
        }
 
296
}
 
297
 
 
298
#endif /* IEEE8021X_EAPOL */
 
299
 
 
300
 
 
301
#ifndef CONFIG_NO_WPA
 
302
 
 
303
static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
 
304
{
 
305
        int ret = 0;
 
306
        struct wpa_bss *curr = NULL, *bss;
 
307
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
308
        const u8 *ie;
 
309
 
 
310
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 
311
                if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
 
312
                        continue;
 
313
                if (ssid == NULL ||
 
314
                    ((bss->ssid_len == ssid->ssid_len &&
 
315
                      os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) ||
 
316
                     ssid->ssid_len == 0)) {
 
317
                        curr = bss;
 
318
                        break;
 
319
                }
 
320
        }
 
321
 
 
322
        if (curr) {
 
323
                ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
 
324
                if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
 
325
                        ret = -1;
 
326
 
 
327
                ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
 
328
                if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
 
329
                        ret = -1;
 
330
        } else {
 
331
                ret = -1;
 
332
        }
 
333
 
 
334
        return ret;
 
335
}
 
336
 
 
337
 
 
338
static int wpa_supplicant_get_beacon_ie(void *ctx)
 
339
{
 
340
        struct wpa_supplicant *wpa_s = ctx;
 
341
        if (wpa_get_beacon_ie(wpa_s) == 0) {
 
342
                return 0;
 
343
        }
 
344
 
 
345
        /* No WPA/RSN IE found in the cached scan results. Try to get updated
 
346
         * scan results from the driver. */
 
347
        if (wpa_supplicant_update_scan_results(wpa_s) < 0)
 
348
                return -1;
 
349
 
 
350
        return wpa_get_beacon_ie(wpa_s);
 
351
}
 
352
 
 
353
 
 
354
static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
 
355
                             const void *data, u16 data_len,
 
356
                             size_t *msg_len, void **data_pos)
 
357
{
 
358
        return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos);
 
359
}
 
360
 
 
361
 
 
362
static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
 
363
                           const u8 *buf, size_t len)
 
364
{
 
365
        return wpa_ether_send(wpa_s, dest, proto, buf, len);
 
366
}
 
367
 
 
368
 
 
369
static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
 
370
{
 
371
        wpa_supplicant_cancel_auth_timeout(wpa_s);
 
372
}
 
373
 
 
374
 
 
375
static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state)
 
376
{
 
377
        wpa_supplicant_set_state(wpa_s, state);
 
378
}
 
379
 
 
380
 
 
381
/**
 
382
 * wpa_supplicant_get_state - Get the connection state
 
383
 * @wpa_s: Pointer to wpa_supplicant data
 
384
 * Returns: The current connection state (WPA_*)
 
385
 */
 
386
static enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
 
387
{
 
388
        return wpa_s->wpa_state;
 
389
}
 
390
 
 
391
 
 
392
static enum wpa_states _wpa_supplicant_get_state(void *wpa_s)
 
393
{
 
394
        return wpa_supplicant_get_state(wpa_s);
 
395
}
 
396
 
 
397
 
 
398
static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
 
399
{
 
400
        wpa_supplicant_disassociate(wpa_s, reason_code);
 
401
        /* Schedule a scan to make sure we continue looking for networks */
 
402
        wpa_supplicant_req_scan(wpa_s, 5, 0);
 
403
}
 
404
 
 
405
 
 
406
static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
 
407
{
 
408
        wpa_supplicant_deauthenticate(wpa_s, reason_code);
 
409
        /* Schedule a scan to make sure we continue looking for networks */
 
410
        wpa_supplicant_req_scan(wpa_s, 5, 0);
 
411
}
 
412
 
 
413
 
 
414
static void * wpa_supplicant_get_network_ctx(void *wpa_s)
 
415
{
 
416
        return wpa_supplicant_get_ssid(wpa_s);
 
417
}
 
418
 
 
419
 
 
420
static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
 
421
{
 
422
        struct wpa_supplicant *wpa_s = ctx;
 
423
        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) {
 
424
                os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
 
425
                return 0;
 
426
        }
 
427
        return wpa_drv_get_bssid(wpa_s, bssid);
 
428
}
 
429
 
 
430
 
 
431
static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
 
432
                                  const u8 *addr, int key_idx, int set_tx,
 
433
                                  const u8 *seq, size_t seq_len,
 
434
                                  const u8 *key, size_t key_len)
 
435
{
 
436
        struct wpa_supplicant *wpa_s = _wpa_s;
 
437
        if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
 
438
                /* Clear the MIC error counter when setting a new PTK. */
 
439
                wpa_s->mic_errors_seen = 0;
 
440
        }
 
441
        return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
 
442
                               key, key_len);
 
443
}
 
444
 
 
445
 
 
446
static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
 
447
                                             int protection_type,
 
448
                                             int key_type)
 
449
{
 
450
        return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type,
 
451
                                          key_type);
 
452
}
 
453
 
 
454
 
 
455
static int wpa_supplicant_add_pmkid(void *wpa_s,
 
456
                                    const u8 *bssid, const u8 *pmkid)
 
457
{
 
458
        return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
 
459
}
 
460
 
 
461
 
 
462
static int wpa_supplicant_remove_pmkid(void *wpa_s,
 
463
                                       const u8 *bssid, const u8 *pmkid)
 
464
{
 
465
        return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
 
466
}
 
467
 
 
468
 
 
469
#ifdef CONFIG_IEEE80211R
 
470
static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md,
 
471
                                        const u8 *ies, size_t ies_len)
 
472
{
 
473
        struct wpa_supplicant *wpa_s = ctx;
 
474
        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
 
475
                return ieee80211_sta_update_ft_ies(wpa_s, md, ies, ies_len);
 
476
        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
 
477
                return sme_update_ft_ies(wpa_s, md, ies, ies_len);
 
478
        return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len);
 
479
}
 
480
 
 
481
 
 
482
static int wpa_supplicant_send_ft_action(void *ctx, u8 action,
 
483
                                         const u8 *target_ap,
 
484
                                         const u8 *ies, size_t ies_len)
 
485
{
 
486
        struct wpa_supplicant *wpa_s = ctx;
 
487
        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
 
488
                return ieee80211_sta_send_ft_action(wpa_s, action, target_ap,
 
489
                                                    ies, ies_len);
 
490
        return wpa_drv_send_ft_action(wpa_s, action, target_ap, ies, ies_len);
 
491
}
 
492
 
 
493
 
 
494
static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap)
 
495
{
 
496
        struct wpa_supplicant *wpa_s = ctx;
 
497
        struct wpa_driver_auth_params params;
 
498
        struct wpa_bss *bss;
 
499
 
 
500
        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
 
501
                return -1;
 
502
 
 
503
        bss = wpa_bss_get_bssid(wpa_s, target_ap);
 
504
        if (bss == NULL)
 
505
                return -1;
 
506
 
 
507
        os_memset(&params, 0, sizeof(params));
 
508
        params.bssid = target_ap;
 
509
        params.freq = bss->freq;
 
510
        params.ssid = bss->ssid;
 
511
        params.ssid_len = bss->ssid_len;
 
512
        params.auth_alg = WPA_AUTH_ALG_FT;
 
513
        params.local_state_change = 1;
 
514
        return wpa_drv_authenticate(wpa_s, &params);
 
515
}
 
516
#endif /* CONFIG_IEEE80211R */
 
517
 
 
518
#endif /* CONFIG_NO_WPA */
 
519
 
 
520
 
 
521
#ifdef IEEE8021X_EAPOL
 
522
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
 
523
static void wpa_supplicant_eap_param_needed(void *ctx, const char *field,
 
524
                                            const char *txt)
 
525
{
 
526
        struct wpa_supplicant *wpa_s = ctx;
 
527
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
528
        char *buf;
 
529
        size_t buflen;
 
530
        int len;
 
531
 
 
532
        if (ssid == NULL)
 
533
                return;
 
534
 
 
535
        buflen = 100 + os_strlen(txt) + ssid->ssid_len;
 
536
        buf = os_malloc(buflen);
 
537
        if (buf == NULL)
 
538
                return;
 
539
        len = os_snprintf(buf, buflen,
 
540
                          WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
 
541
                          field, ssid->id, txt);
 
542
        if (len < 0 || (size_t) len >= buflen) {
 
543
                os_free(buf);
 
544
                return;
 
545
        }
 
546
        if (ssid->ssid && buflen > len + ssid->ssid_len) {
 
547
                os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
 
548
                len += ssid->ssid_len;
 
549
                buf[len] = '\0';
 
550
        }
 
551
        buf[buflen - 1] = '\0';
 
552
        wpa_msg(wpa_s, MSG_INFO, "%s", buf);
 
553
        os_free(buf);
 
554
}
 
555
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
556
#define wpa_supplicant_eap_param_needed NULL
 
557
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
558
 
 
559
 
 
560
static void wpa_supplicant_port_cb(void *ctx, int authorized)
 
561
{
 
562
        struct wpa_supplicant *wpa_s = ctx;
 
563
#ifdef CONFIG_AP
 
564
        if (wpa_s->ap_iface) {
 
565
                wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant "
 
566
                           "port status: %s",
 
567
                           authorized ? "Authorized" : "Unauthorized");
 
568
                return;
 
569
        }
 
570
#endif /* CONFIG_AP */
 
571
        wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s",
 
572
                   authorized ? "Authorized" : "Unauthorized");
 
573
        wpa_drv_set_supp_port(wpa_s, authorized);
 
574
}
 
575
#endif /* IEEE8021X_EAPOL */
 
576
 
 
577
 
 
578
int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
 
579
{
 
580
#ifdef IEEE8021X_EAPOL
 
581
        struct eapol_ctx *ctx;
 
582
        ctx = os_zalloc(sizeof(*ctx));
 
583
        if (ctx == NULL) {
 
584
                wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
 
585
                return -1;
 
586
        }
 
587
 
 
588
        ctx->ctx = wpa_s;
 
589
        ctx->msg_ctx = wpa_s;
 
590
        ctx->eapol_send_ctx = wpa_s;
 
591
        ctx->preauth = 0;
 
592
        ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
 
593
        ctx->eapol_send = wpa_supplicant_eapol_send;
 
594
        ctx->set_wep_key = wpa_eapol_set_wep_key;
 
595
        ctx->set_config_blob = wpa_supplicant_set_config_blob;
 
596
        ctx->get_config_blob = wpa_supplicant_get_config_blob;
 
597
        ctx->aborted_cached = wpa_supplicant_aborted_cached;
 
598
        ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
 
599
        ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
 
600
        ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
 
601
        ctx->wps = wpa_s->wps;
 
602
        ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
 
603
        ctx->port_cb = wpa_supplicant_port_cb;
 
604
        ctx->cb = wpa_supplicant_eapol_cb;
 
605
        ctx->cb_ctx = wpa_s;
 
606
        wpa_s->eapol = eapol_sm_init(ctx);
 
607
        if (wpa_s->eapol == NULL) {
 
608
                os_free(ctx);
 
609
                wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
 
610
                           "machines.");
 
611
                return -1;
 
612
        }
 
613
#endif /* IEEE8021X_EAPOL */
 
614
 
 
615
        return 0;
 
616
}
 
617
 
 
618
 
 
619
int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
 
620
{
 
621
#ifndef CONFIG_NO_WPA
 
622
        struct wpa_sm_ctx *ctx;
 
623
        ctx = os_zalloc(sizeof(*ctx));
 
624
        if (ctx == NULL) {
 
625
                wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
 
626
                return -1;
 
627
        }
 
628
 
 
629
        ctx->ctx = wpa_s;
 
630
        ctx->msg_ctx = wpa_s;
 
631
        ctx->set_state = _wpa_supplicant_set_state;
 
632
        ctx->get_state = _wpa_supplicant_get_state;
 
633
        ctx->deauthenticate = _wpa_supplicant_deauthenticate;
 
634
        ctx->disassociate = _wpa_supplicant_disassociate;
 
635
        ctx->set_key = wpa_supplicant_set_key;
 
636
        ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
 
637
        ctx->get_bssid = wpa_supplicant_get_bssid;
 
638
        ctx->ether_send = _wpa_ether_send;
 
639
        ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
 
640
        ctx->alloc_eapol = _wpa_alloc_eapol;
 
641
        ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
 
642
        ctx->add_pmkid = wpa_supplicant_add_pmkid;
 
643
        ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
 
644
#ifndef CONFIG_NO_CONFIG_BLOBS
 
645
        ctx->set_config_blob = wpa_supplicant_set_config_blob;
 
646
        ctx->get_config_blob = wpa_supplicant_get_config_blob;
 
647
#endif /* CONFIG_NO_CONFIG_BLOBS */
 
648
        ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
 
649
#ifdef CONFIG_IEEE80211R
 
650
        ctx->update_ft_ies = wpa_supplicant_update_ft_ies;
 
651
        ctx->send_ft_action = wpa_supplicant_send_ft_action;
 
652
        ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
 
653
#endif /* CONFIG_IEEE80211R */
 
654
 
 
655
        wpa_s->wpa = wpa_sm_init(ctx);
 
656
        if (wpa_s->wpa == NULL) {
 
657
                wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
 
658
                           "machine");
 
659
                return -1;
 
660
        }
 
661
#endif /* CONFIG_NO_WPA */
 
662
 
 
663
        return 0;
 
664
}
 
665
 
 
666
 
 
667
void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
 
668
                                        struct wpa_ssid *ssid)
 
669
{
 
670
        struct rsn_supp_config conf;
 
671
        if (ssid) {
 
672
                os_memset(&conf, 0, sizeof(conf));
 
673
                conf.network_ctx = ssid;
 
674
                conf.peerkey_enabled = ssid->peerkey;
 
675
                conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
 
676
#ifdef IEEE8021X_EAPOL
 
677
                conf.eap_workaround = ssid->eap_workaround;
 
678
                conf.eap_conf_ctx = &ssid->eap;
 
679
#endif /* IEEE8021X_EAPOL */
 
680
                conf.ssid = ssid->ssid;
 
681
                conf.ssid_len = ssid->ssid_len;
 
682
                conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
 
683
        }
 
684
        wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
 
685
}