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

« back to all changes in this revision

Viewing changes to .pc/0002-pmkokc-Clear-WPA-and-EAPOL-state-machine-config-pointer-on-.patch/wpa_supplicant/ctrl_iface.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 / Control interface (shared code for all backends)
 
3
 * Copyright (c) 2004-2010, 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 "utils/includes.h"
 
16
 
 
17
#include "utils/common.h"
 
18
#include "utils/eloop.h"
 
19
#include "common/ieee802_11_defs.h"
 
20
#include "common/wpa_ctrl.h"
 
21
#include "eap_peer/eap.h"
 
22
#include "eapol_supp/eapol_supp_sm.h"
 
23
#include "rsn_supp/wpa.h"
 
24
#include "rsn_supp/preauth.h"
 
25
#include "rsn_supp/pmksa_cache.h"
 
26
#include "l2_packet/l2_packet.h"
 
27
#include "wps/wps.h"
 
28
#include "config.h"
 
29
#include "wpa_supplicant_i.h"
 
30
#include "driver_i.h"
 
31
#include "wps_supplicant.h"
 
32
#include "ibss_rsn.h"
 
33
#include "ap.h"
 
34
#include "notify.h"
 
35
#include "bss.h"
 
36
#include "scan.h"
 
37
#include "ctrl_iface.h"
 
38
 
 
39
extern struct wpa_driver_ops *wpa_drivers[];
 
40
 
 
41
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
 
42
                                            char *buf, int len);
 
43
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 
44
                                                  char *buf, int len);
 
45
 
 
46
 
 
47
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 
48
                                         char *cmd)
 
49
{
 
50
        char *value;
 
51
        int ret = 0;
 
52
 
 
53
        value = os_strchr(cmd, ' ');
 
54
        if (value == NULL)
 
55
                return -1;
 
56
        *value++ = '\0';
 
57
 
 
58
        wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
 
59
        if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
 
60
                eapol_sm_configure(wpa_s->eapol,
 
61
                                   atoi(value), -1, -1, -1);
 
62
        } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
 
63
                eapol_sm_configure(wpa_s->eapol,
 
64
                                   -1, atoi(value), -1, -1);
 
65
        } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
 
66
                eapol_sm_configure(wpa_s->eapol,
 
67
                                   -1, -1, atoi(value), -1);
 
68
        } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
 
69
                eapol_sm_configure(wpa_s->eapol,
 
70
                                   -1, -1, -1, atoi(value));
 
71
        } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
 
72
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
 
73
                                     atoi(value)))
 
74
                        ret = -1;
 
75
        } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
 
76
                   0) {
 
77
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
 
78
                                     atoi(value)))
 
79
                        ret = -1;
 
80
        } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
 
81
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
 
82
                        ret = -1;
 
83
        } else
 
84
                ret = -1;
 
85
 
 
86
        return ret;
 
87
}
 
88
 
 
89
 
 
90
#ifdef IEEE8021X_EAPOL
 
91
static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
 
92
                                             char *addr)
 
93
{
 
94
        u8 bssid[ETH_ALEN];
 
95
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
96
 
 
97
        if (hwaddr_aton(addr, bssid)) {
 
98
                wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
 
99
                           "'%s'", addr);
 
100
                return -1;
 
101
        }
 
102
 
 
103
        wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
 
104
        rsn_preauth_deinit(wpa_s->wpa);
 
105
        if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
 
106
                return -1;
 
107
 
 
108
        return 0;
 
109
}
 
110
#endif /* IEEE8021X_EAPOL */
 
111
 
 
112
 
 
113
#ifdef CONFIG_PEERKEY
 
114
/* MLME-STKSTART.request(peer) */
 
115
static int wpa_supplicant_ctrl_iface_stkstart(
 
116
        struct wpa_supplicant *wpa_s, char *addr)
 
117
{
 
118
        u8 peer[ETH_ALEN];
 
119
 
 
120
        if (hwaddr_aton(addr, peer)) {
 
121
                wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
 
122
                           "address '%s'", addr);
 
123
                return -1;
 
124
        }
 
125
 
 
126
        wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
 
127
                   MAC2STR(peer));
 
128
 
 
129
        return wpa_sm_stkstart(wpa_s->wpa, peer);
 
130
}
 
131
#endif /* CONFIG_PEERKEY */
 
132
 
 
133
 
 
134
#ifdef CONFIG_IEEE80211R
 
135
static int wpa_supplicant_ctrl_iface_ft_ds(
 
136
        struct wpa_supplicant *wpa_s, char *addr)
 
137
{
 
138
        u8 target_ap[ETH_ALEN];
 
139
        struct wpa_bss *bss;
 
140
        const u8 *mdie;
 
141
 
 
142
        if (hwaddr_aton(addr, target_ap)) {
 
143
                wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
 
144
                           "address '%s'", addr);
 
145
                return -1;
 
146
        }
 
147
 
 
148
        wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
 
149
 
 
150
        bss = wpa_bss_get_bssid(wpa_s, target_ap);
 
151
        if (bss)
 
152
                mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
 
153
        else
 
154
                mdie = NULL;
 
155
 
 
156
        return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
 
157
}
 
158
#endif /* CONFIG_IEEE80211R */
 
159
 
 
160
 
 
161
#ifdef CONFIG_WPS
 
162
static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
 
163
                                             char *cmd)
 
164
{
 
165
        u8 bssid[ETH_ALEN], *_bssid = bssid;
 
166
 
 
167
        if (cmd == NULL || os_strcmp(cmd, "any") == 0)
 
168
                _bssid = NULL;
 
169
        else if (hwaddr_aton(cmd, bssid)) {
 
170
                wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
 
171
                           cmd);
 
172
                return -1;
 
173
        }
 
174
 
 
175
#ifdef CONFIG_AP
 
176
        if (wpa_s->ap_iface)
 
177
                return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
 
178
#endif /* CONFIG_AP */
 
179
 
 
180
        return wpas_wps_start_pbc(wpa_s, _bssid);
 
181
}
 
182
 
 
183
 
 
184
static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
 
185
                                             char *cmd, char *buf,
 
186
                                             size_t buflen)
 
187
{
 
188
        u8 bssid[ETH_ALEN], *_bssid = bssid;
 
189
        char *pin;
 
190
        int ret;
 
191
 
 
192
        pin = os_strchr(cmd, ' ');
 
193
        if (pin)
 
194
                *pin++ = '\0';
 
195
 
 
196
        if (os_strcmp(cmd, "any") == 0)
 
197
                _bssid = NULL;
 
198
        else if (hwaddr_aton(cmd, bssid)) {
 
199
                wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
 
200
                           cmd);
 
201
                return -1;
 
202
        }
 
203
 
 
204
#ifdef CONFIG_AP
 
205
        if (wpa_s->ap_iface)
 
206
                return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
 
207
                                                 buf, buflen);
 
208
#endif /* CONFIG_AP */
 
209
 
 
210
        if (pin) {
 
211
                ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
 
212
                if (ret < 0)
 
213
                        return -1;
 
214
                ret = os_snprintf(buf, buflen, "%s", pin);
 
215
                if (ret < 0 || (size_t) ret >= buflen)
 
216
                        return -1;
 
217
                return ret;
 
218
        }
 
219
 
 
220
        ret = wpas_wps_start_pin(wpa_s, _bssid, NULL);
 
221
        if (ret < 0)
 
222
                return -1;
 
223
 
 
224
        /* Return the generated PIN */
 
225
        ret = os_snprintf(buf, buflen, "%08d", ret);
 
226
        if (ret < 0 || (size_t) ret >= buflen)
 
227
                return -1;
 
228
        return ret;
 
229
}
 
230
 
 
231
 
 
232
#ifdef CONFIG_WPS_OOB
 
233
static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
 
234
                                             char *cmd)
 
235
{
 
236
        char *path, *method, *name;
 
237
 
 
238
        path = os_strchr(cmd, ' ');
 
239
        if (path == NULL)
 
240
                return -1;
 
241
        *path++ = '\0';
 
242
 
 
243
        method = os_strchr(path, ' ');
 
244
        if (method == NULL)
 
245
                return -1;
 
246
        *method++ = '\0';
 
247
 
 
248
        name = os_strchr(method, ' ');
 
249
        if (name != NULL)
 
250
                *name++ = '\0';
 
251
 
 
252
        return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
 
253
}
 
254
#endif /* CONFIG_WPS_OOB */
 
255
 
 
256
 
 
257
static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
 
258
                                             char *cmd)
 
259
{
 
260
        u8 bssid[ETH_ALEN], *_bssid = bssid;
 
261
        char *pin;
 
262
        char *new_ssid;
 
263
        char *new_auth;
 
264
        char *new_encr;
 
265
        char *new_key;
 
266
        struct wps_new_ap_settings ap;
 
267
 
 
268
        pin = os_strchr(cmd, ' ');
 
269
        if (pin == NULL)
 
270
                return -1;
 
271
        *pin++ = '\0';
 
272
 
 
273
        if (os_strcmp(cmd, "any") == 0)
 
274
                _bssid = NULL;
 
275
        else if (hwaddr_aton(cmd, bssid)) {
 
276
                wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
 
277
                           cmd);
 
278
                return -1;
 
279
        }
 
280
 
 
281
        new_ssid = os_strchr(pin, ' ');
 
282
        if (new_ssid == NULL)
 
283
                return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL);
 
284
        *new_ssid++ = '\0';
 
285
 
 
286
        new_auth = os_strchr(new_ssid, ' ');
 
287
        if (new_auth == NULL)
 
288
                return -1;
 
289
        *new_auth++ = '\0';
 
290
 
 
291
        new_encr = os_strchr(new_auth, ' ');
 
292
        if (new_encr == NULL)
 
293
                return -1;
 
294
        *new_encr++ = '\0';
 
295
 
 
296
        new_key = os_strchr(new_encr, ' ');
 
297
        if (new_key == NULL)
 
298
                return -1;
 
299
        *new_key++ = '\0';
 
300
 
 
301
        os_memset(&ap, 0, sizeof(ap));
 
302
        ap.ssid_hex = new_ssid;
 
303
        ap.auth = new_auth;
 
304
        ap.encr = new_encr;
 
305
        ap.key_hex = new_key;
 
306
        return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap);
 
307
}
 
308
 
 
309
 
 
310
#ifdef CONFIG_WPS_ER
 
311
static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
 
312
                                                char *cmd)
 
313
{
 
314
        char *uuid = cmd, *pin;
 
315
        pin = os_strchr(uuid, ' ');
 
316
        if (pin == NULL)
 
317
                return -1;
 
318
        *pin++ = '\0';
 
319
        return wpas_wps_er_add_pin(wpa_s, uuid, pin);
 
320
}
 
321
 
 
322
 
 
323
static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
 
324
                                                  char *cmd)
 
325
{
 
326
        char *uuid = cmd, *pin;
 
327
        pin = os_strchr(uuid, ' ');
 
328
        if (pin == NULL)
 
329
                return -1;
 
330
        *pin++ = '\0';
 
331
        return wpas_wps_er_learn(wpa_s, uuid, pin);
 
332
}
 
333
#endif /* CONFIG_WPS_ER */
 
334
 
 
335
#endif /* CONFIG_WPS */
 
336
 
 
337
 
 
338
#ifdef CONFIG_IBSS_RSN
 
339
static int wpa_supplicant_ctrl_iface_ibss_rsn(
 
340
        struct wpa_supplicant *wpa_s, char *addr)
 
341
{
 
342
        u8 peer[ETH_ALEN];
 
343
 
 
344
        if (hwaddr_aton(addr, peer)) {
 
345
                wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
 
346
                           "address '%s'", addr);
 
347
                return -1;
 
348
        }
 
349
 
 
350
        wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
 
351
                   MAC2STR(peer));
 
352
 
 
353
        return ibss_rsn_start(wpa_s->ibss_rsn, peer);
 
354
}
 
355
#endif /* CONFIG_IBSS_RSN */
 
356
 
 
357
 
 
358
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
 
359
                                              char *rsp)
 
360
{
 
361
#ifdef IEEE8021X_EAPOL
 
362
        char *pos, *id_pos;
 
363
        int id;
 
364
        struct wpa_ssid *ssid;
 
365
        struct eap_peer_config *eap;
 
366
 
 
367
        pos = os_strchr(rsp, '-');
 
368
        if (pos == NULL)
 
369
                return -1;
 
370
        *pos++ = '\0';
 
371
        id_pos = pos;
 
372
        pos = os_strchr(pos, ':');
 
373
        if (pos == NULL)
 
374
                return -1;
 
375
        *pos++ = '\0';
 
376
        id = atoi(id_pos);
 
377
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
 
378
        wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
 
379
                              (u8 *) pos, os_strlen(pos));
 
380
 
 
381
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
382
        if (ssid == NULL) {
 
383
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
 
384
                           "to update", id);
 
385
                return -1;
 
386
        }
 
387
        eap = &ssid->eap;
 
388
 
 
389
        if (os_strcmp(rsp, "IDENTITY") == 0) {
 
390
                os_free(eap->identity);
 
391
                eap->identity = (u8 *) os_strdup(pos);
 
392
                eap->identity_len = os_strlen(pos);
 
393
                eap->pending_req_identity = 0;
 
394
                if (ssid == wpa_s->current_ssid)
 
395
                        wpa_s->reassociate = 1;
 
396
        } else if (os_strcmp(rsp, "PASSWORD") == 0) {
 
397
                os_free(eap->password);
 
398
                eap->password = (u8 *) os_strdup(pos);
 
399
                eap->password_len = os_strlen(pos);
 
400
                eap->pending_req_password = 0;
 
401
                if (ssid == wpa_s->current_ssid)
 
402
                        wpa_s->reassociate = 1;
 
403
        } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
 
404
                os_free(eap->new_password);
 
405
                eap->new_password = (u8 *) os_strdup(pos);
 
406
                eap->new_password_len = os_strlen(pos);
 
407
                eap->pending_req_new_password = 0;
 
408
                if (ssid == wpa_s->current_ssid)
 
409
                        wpa_s->reassociate = 1;
 
410
        } else if (os_strcmp(rsp, "PIN") == 0) {
 
411
                os_free(eap->pin);
 
412
                eap->pin = os_strdup(pos);
 
413
                eap->pending_req_pin = 0;
 
414
                if (ssid == wpa_s->current_ssid)
 
415
                        wpa_s->reassociate = 1;
 
416
        } else if (os_strcmp(rsp, "OTP") == 0) {
 
417
                os_free(eap->otp);
 
418
                eap->otp = (u8 *) os_strdup(pos);
 
419
                eap->otp_len = os_strlen(pos);
 
420
                os_free(eap->pending_req_otp);
 
421
                eap->pending_req_otp = NULL;
 
422
                eap->pending_req_otp_len = 0;
 
423
        } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
 
424
                os_free(eap->private_key_passwd);
 
425
                eap->private_key_passwd = (u8 *) os_strdup(pos);
 
426
                eap->pending_req_passphrase = 0;
 
427
                if (ssid == wpa_s->current_ssid)
 
428
                        wpa_s->reassociate = 1;
 
429
        } else {
 
430
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
 
431
                return -1;
 
432
        }
 
433
 
 
434
        return 0;
 
435
#else /* IEEE8021X_EAPOL */
 
436
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
 
437
        return -1;
 
438
#endif /* IEEE8021X_EAPOL */
 
439
}
 
440
 
 
441
 
 
442
static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
 
443
                                            const char *params,
 
444
                                            char *buf, size_t buflen)
 
445
{
 
446
        char *pos, *end, tmp[30];
 
447
        int res, verbose, ret;
 
448
 
 
449
        verbose = os_strcmp(params, "-VERBOSE") == 0;
 
450
        pos = buf;
 
451
        end = buf + buflen;
 
452
        if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
 
453
                struct wpa_ssid *ssid = wpa_s->current_ssid;
 
454
                ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
 
455
                                  MAC2STR(wpa_s->bssid));
 
456
                if (ret < 0 || ret >= end - pos)
 
457
                        return pos - buf;
 
458
                pos += ret;
 
459
                if (ssid) {
 
460
                        u8 *_ssid = ssid->ssid;
 
461
                        size_t ssid_len = ssid->ssid_len;
 
462
                        u8 ssid_buf[MAX_SSID_LEN];
 
463
                        if (ssid_len == 0) {
 
464
                                int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
 
465
                                if (_res < 0)
 
466
                                        ssid_len = 0;
 
467
                                else
 
468
                                        ssid_len = _res;
 
469
                                _ssid = ssid_buf;
 
470
                        }
 
471
                        ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
 
472
                                          wpa_ssid_txt(_ssid, ssid_len),
 
473
                                          ssid->id);
 
474
                        if (ret < 0 || ret >= end - pos)
 
475
                                return pos - buf;
 
476
                        pos += ret;
 
477
 
 
478
                        if (ssid->id_str) {
 
479
                                ret = os_snprintf(pos, end - pos,
 
480
                                                  "id_str=%s\n",
 
481
                                                  ssid->id_str);
 
482
                                if (ret < 0 || ret >= end - pos)
 
483
                                        return pos - buf;
 
484
                                pos += ret;
 
485
                        }
 
486
 
 
487
                        switch (ssid->mode) {
 
488
                        case WPAS_MODE_INFRA:
 
489
                                ret = os_snprintf(pos, end - pos,
 
490
                                                  "mode=station\n");
 
491
                                break;
 
492
                        case WPAS_MODE_IBSS:
 
493
                                ret = os_snprintf(pos, end - pos,
 
494
                                                  "mode=IBSS\n");
 
495
                                break;
 
496
                        case WPAS_MODE_AP:
 
497
                                ret = os_snprintf(pos, end - pos,
 
498
                                                  "mode=AP\n");
 
499
                                break;
 
500
                        default:
 
501
                                ret = 0;
 
502
                                break;
 
503
                        }
 
504
                        if (ret < 0 || ret >= end - pos)
 
505
                                return pos - buf;
 
506
                        pos += ret;
 
507
                }
 
508
 
 
509
#ifdef CONFIG_AP
 
510
                if (wpa_s->ap_iface) {
 
511
                        pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
 
512
                                                            end - pos,
 
513
                                                            verbose);
 
514
                } else
 
515
#endif /* CONFIG_AP */
 
516
                pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
 
517
        }
 
518
        ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
 
519
                          wpa_supplicant_state_txt(wpa_s->wpa_state));
 
520
        if (ret < 0 || ret >= end - pos)
 
521
                return pos - buf;
 
522
        pos += ret;
 
523
 
 
524
        if (wpa_s->l2 &&
 
525
            l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
 
526
                ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
 
527
                if (ret < 0 || ret >= end - pos)
 
528
                        return pos - buf;
 
529
                pos += ret;
 
530
        }
 
531
 
 
532
        if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
 
533
            wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 
534
                res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
 
535
                                          verbose);
 
536
                if (res >= 0)
 
537
                        pos += res;
 
538
        }
 
539
 
 
540
        res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
 
541
        if (res >= 0)
 
542
                pos += res;
 
543
 
 
544
        return pos - buf;
 
545
}
 
546
 
 
547
 
 
548
static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
 
549
                                           char *cmd)
 
550
{
 
551
        char *pos;
 
552
        int id;
 
553
        struct wpa_ssid *ssid;
 
554
        u8 bssid[ETH_ALEN];
 
555
 
 
556
        /* cmd: "<network id> <BSSID>" */
 
557
        pos = os_strchr(cmd, ' ');
 
558
        if (pos == NULL)
 
559
                return -1;
 
560
        *pos++ = '\0';
 
561
        id = atoi(cmd);
 
562
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
 
563
        if (hwaddr_aton(pos, bssid)) {
 
564
                wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
 
565
                return -1;
 
566
        }
 
567
 
 
568
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
569
        if (ssid == NULL) {
 
570
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
 
571
                           "to update", id);
 
572
                return -1;
 
573
        }
 
574
 
 
575
        os_memcpy(ssid->bssid, bssid, ETH_ALEN);
 
576
        ssid->bssid_set = !is_zero_ether_addr(bssid);
 
577
 
 
578
        return 0;
 
579
}
 
580
 
 
581
 
 
582
static int wpa_supplicant_ctrl_iface_list_networks(
 
583
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
584
{
 
585
        char *pos, *end;
 
586
        struct wpa_ssid *ssid;
 
587
        int ret;
 
588
 
 
589
        pos = buf;
 
590
        end = buf + buflen;
 
591
        ret = os_snprintf(pos, end - pos,
 
592
                          "network id / ssid / bssid / flags\n");
 
593
        if (ret < 0 || ret >= end - pos)
 
594
                return pos - buf;
 
595
        pos += ret;
 
596
 
 
597
        ssid = wpa_s->conf->ssid;
 
598
        while (ssid) {
 
599
                ret = os_snprintf(pos, end - pos, "%d\t%s",
 
600
                                  ssid->id,
 
601
                                  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
 
602
                if (ret < 0 || ret >= end - pos)
 
603
                        return pos - buf;
 
604
                pos += ret;
 
605
                if (ssid->bssid_set) {
 
606
                        ret = os_snprintf(pos, end - pos, "\t" MACSTR,
 
607
                                          MAC2STR(ssid->bssid));
 
608
                } else {
 
609
                        ret = os_snprintf(pos, end - pos, "\tany");
 
610
                }
 
611
                if (ret < 0 || ret >= end - pos)
 
612
                        return pos - buf;
 
613
                pos += ret;
 
614
                ret = os_snprintf(pos, end - pos, "\t%s%s",
 
615
                                  ssid == wpa_s->current_ssid ?
 
616
                                  "[CURRENT]" : "",
 
617
                                  ssid->disabled ? "[DISABLED]" : "");
 
618
                if (ret < 0 || ret >= end - pos)
 
619
                        return pos - buf;
 
620
                pos += ret;
 
621
                ret = os_snprintf(pos, end - pos, "\n");
 
622
                if (ret < 0 || ret >= end - pos)
 
623
                        return pos - buf;
 
624
                pos += ret;
 
625
 
 
626
                ssid = ssid->next;
 
627
        }
 
628
 
 
629
        return pos - buf;
 
630
}
 
631
 
 
632
 
 
633
static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
 
634
{
 
635
        int first = 1, ret;
 
636
        ret = os_snprintf(pos, end - pos, "-");
 
637
        if (ret < 0 || ret >= end - pos)
 
638
                return pos;
 
639
        pos += ret;
 
640
        if (cipher & WPA_CIPHER_NONE) {
 
641
                ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
 
642
                if (ret < 0 || ret >= end - pos)
 
643
                        return pos;
 
644
                pos += ret;
 
645
                first = 0;
 
646
        }
 
647
        if (cipher & WPA_CIPHER_WEP40) {
 
648
                ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
 
649
                if (ret < 0 || ret >= end - pos)
 
650
                        return pos;
 
651
                pos += ret;
 
652
                first = 0;
 
653
        }
 
654
        if (cipher & WPA_CIPHER_WEP104) {
 
655
                ret = os_snprintf(pos, end - pos, "%sWEP104",
 
656
                                  first ? "" : "+");
 
657
                if (ret < 0 || ret >= end - pos)
 
658
                        return pos;
 
659
                pos += ret;
 
660
                first = 0;
 
661
        }
 
662
        if (cipher & WPA_CIPHER_TKIP) {
 
663
                ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
 
664
                if (ret < 0 || ret >= end - pos)
 
665
                        return pos;
 
666
                pos += ret;
 
667
                first = 0;
 
668
        }
 
669
        if (cipher & WPA_CIPHER_CCMP) {
 
670
                ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
 
671
                if (ret < 0 || ret >= end - pos)
 
672
                        return pos;
 
673
                pos += ret;
 
674
                first = 0;
 
675
        }
 
676
        return pos;
 
677
}
 
678
 
 
679
 
 
680
static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
 
681
                                    const u8 *ie, size_t ie_len)
 
682
{
 
683
        struct wpa_ie_data data;
 
684
        int first, ret;
 
685
 
 
686
        ret = os_snprintf(pos, end - pos, "[%s-", proto);
 
687
        if (ret < 0 || ret >= end - pos)
 
688
                return pos;
 
689
        pos += ret;
 
690
 
 
691
        if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
 
692
                ret = os_snprintf(pos, end - pos, "?]");
 
693
                if (ret < 0 || ret >= end - pos)
 
694
                        return pos;
 
695
                pos += ret;
 
696
                return pos;
 
697
        }
 
698
 
 
699
        first = 1;
 
700
        if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
 
701
                ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
 
702
                if (ret < 0 || ret >= end - pos)
 
703
                        return pos;
 
704
                pos += ret;
 
705
                first = 0;
 
706
        }
 
707
        if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
 
708
                ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
 
709
                if (ret < 0 || ret >= end - pos)
 
710
                        return pos;
 
711
                pos += ret;
 
712
                first = 0;
 
713
        }
 
714
        if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
 
715
                ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
 
716
                if (ret < 0 || ret >= end - pos)
 
717
                        return pos;
 
718
                pos += ret;
 
719
                first = 0;
 
720
        }
 
721
#ifdef CONFIG_IEEE80211R
 
722
        if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
 
723
                ret = os_snprintf(pos, end - pos, "%sFT/EAP",
 
724
                                  first ? "" : "+");
 
725
                if (ret < 0 || ret >= end - pos)
 
726
                        return pos;
 
727
                pos += ret;
 
728
                first = 0;
 
729
        }
 
730
        if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
 
731
                ret = os_snprintf(pos, end - pos, "%sFT/PSK",
 
732
                                  first ? "" : "+");
 
733
                if (ret < 0 || ret >= end - pos)
 
734
                        return pos;
 
735
                pos += ret;
 
736
                first = 0;
 
737
        }
 
738
#endif /* CONFIG_IEEE80211R */
 
739
#ifdef CONFIG_IEEE80211W
 
740
        if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
 
741
                ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
 
742
                                  first ? "" : "+");
 
743
                if (ret < 0 || ret >= end - pos)
 
744
                        return pos;
 
745
                pos += ret;
 
746
                first = 0;
 
747
        }
 
748
        if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
 
749
                ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
 
750
                                  first ? "" : "+");
 
751
                if (ret < 0 || ret >= end - pos)
 
752
                        return pos;
 
753
                pos += ret;
 
754
                first = 0;
 
755
        }
 
756
#endif /* CONFIG_IEEE80211W */
 
757
 
 
758
        pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
 
759
 
 
760
        if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
 
761
                ret = os_snprintf(pos, end - pos, "-preauth");
 
762
                if (ret < 0 || ret >= end - pos)
 
763
                        return pos;
 
764
                pos += ret;
 
765
        }
 
766
 
 
767
        ret = os_snprintf(pos, end - pos, "]");
 
768
        if (ret < 0 || ret >= end - pos)
 
769
                return pos;
 
770
        pos += ret;
 
771
 
 
772
        return pos;
 
773
}
 
774
 
 
775
 
 
776
#ifdef CONFIG_WPS
 
777
static char * wpa_supplicant_wps_ie_txt_buf(char *pos, char *end,
 
778
                                            struct wpabuf *wps_ie)
 
779
{
 
780
        int ret;
 
781
        const char *txt;
 
782
 
 
783
        if (wps_ie == NULL)
 
784
                return pos;
 
785
        if (wps_is_selected_pbc_registrar(wps_ie))
 
786
                txt = "[WPS-PBC]";
 
787
        else if (wps_is_selected_pin_registrar(wps_ie))
 
788
                txt = "[WPS-PIN]";
 
789
        else
 
790
                txt = "[WPS]";
 
791
 
 
792
        ret = os_snprintf(pos, end - pos, "%s", txt);
 
793
        if (ret >= 0 && ret < end - pos)
 
794
                pos += ret;
 
795
        wpabuf_free(wps_ie);
 
796
        return pos;
 
797
}
 
798
#endif /* CONFIG_WPS */
 
799
 
 
800
 
 
801
static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
 
802
                                        const struct wpa_bss *bss)
 
803
{
 
804
#ifdef CONFIG_WPS
 
805
        struct wpabuf *wps_ie;
 
806
        wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
 
807
        return wpa_supplicant_wps_ie_txt_buf(pos, end, wps_ie);
 
808
#else /* CONFIG_WPS */
 
809
        return pos;
 
810
#endif /* CONFIG_WPS */
 
811
}
 
812
 
 
813
 
 
814
/* Format one result on one text line into a buffer. */
 
815
static int wpa_supplicant_ctrl_iface_scan_result(
 
816
        const struct wpa_bss *bss, char *buf, size_t buflen)
 
817
{
 
818
        char *pos, *end;
 
819
        int ret;
 
820
        const u8 *ie, *ie2;
 
821
 
 
822
        pos = buf;
 
823
        end = buf + buflen;
 
824
 
 
825
        ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
 
826
                          MAC2STR(bss->bssid), bss->freq, bss->level);
 
827
        if (ret < 0 || ret >= end - pos)
 
828
                return pos - buf;
 
829
        pos += ret;
 
830
        ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 
831
        if (ie)
 
832
                pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
 
833
        ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
 
834
        if (ie2)
 
835
                pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
 
836
        pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
 
837
        if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
 
838
                ret = os_snprintf(pos, end - pos, "[WEP]");
 
839
                if (ret < 0 || ret >= end - pos)
 
840
                        return pos - buf;
 
841
                pos += ret;
 
842
        }
 
843
        if (bss->caps & IEEE80211_CAP_IBSS) {
 
844
                ret = os_snprintf(pos, end - pos, "[IBSS]");
 
845
                if (ret < 0 || ret >= end - pos)
 
846
                        return pos - buf;
 
847
                pos += ret;
 
848
        }
 
849
        if (bss->caps & IEEE80211_CAP_ESS) {
 
850
                ret = os_snprintf(pos, end - pos, "[ESS]");
 
851
                if (ret < 0 || ret >= end - pos)
 
852
                        return pos - buf;
 
853
                pos += ret;
 
854
        }
 
855
 
 
856
        ret = os_snprintf(pos, end - pos, "\t%s",
 
857
                          wpa_ssid_txt(bss->ssid, bss->ssid_len));
 
858
        if (ret < 0 || ret >= end - pos)
 
859
                return pos - buf;
 
860
        pos += ret;
 
861
 
 
862
        ret = os_snprintf(pos, end - pos, "\n");
 
863
        if (ret < 0 || ret >= end - pos)
 
864
                return pos - buf;
 
865
        pos += ret;
 
866
 
 
867
        return pos - buf;
 
868
}
 
869
 
 
870
 
 
871
static int wpa_supplicant_ctrl_iface_scan_results(
 
872
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
873
{
 
874
        char *pos, *end;
 
875
        struct wpa_bss *bss;
 
876
        int ret;
 
877
 
 
878
        pos = buf;
 
879
        end = buf + buflen;
 
880
        ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
 
881
                          "flags / ssid\n");
 
882
        if (ret < 0 || ret >= end - pos)
 
883
                return pos - buf;
 
884
        pos += ret;
 
885
 
 
886
        dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
 
887
                ret = wpa_supplicant_ctrl_iface_scan_result(bss, pos,
 
888
                                                            end - pos);
 
889
                if (ret < 0 || ret >= end - pos)
 
890
                        return pos - buf;
 
891
                pos += ret;
 
892
        }
 
893
 
 
894
        return pos - buf;
 
895
}
 
896
 
 
897
 
 
898
static int wpa_supplicant_ctrl_iface_select_network(
 
899
        struct wpa_supplicant *wpa_s, char *cmd)
 
900
{
 
901
        int id;
 
902
        struct wpa_ssid *ssid;
 
903
 
 
904
        /* cmd: "<network id>" or "any" */
 
905
        if (os_strcmp(cmd, "any") == 0) {
 
906
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
 
907
                ssid = NULL;
 
908
        } else {
 
909
                id = atoi(cmd);
 
910
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
 
911
 
 
912
                ssid = wpa_config_get_network(wpa_s->conf, id);
 
913
                if (ssid == NULL) {
 
914
                        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
 
915
                                   "network id=%d", id);
 
916
                        return -1;
 
917
                }
 
918
        }
 
919
 
 
920
        wpa_supplicant_select_network(wpa_s, ssid);
 
921
 
 
922
        return 0;
 
923
}
 
924
 
 
925
 
 
926
static int wpa_supplicant_ctrl_iface_enable_network(
 
927
        struct wpa_supplicant *wpa_s, char *cmd)
 
928
{
 
929
        int id;
 
930
        struct wpa_ssid *ssid;
 
931
 
 
932
        /* cmd: "<network id>" or "all" */
 
933
        if (os_strcmp(cmd, "all") == 0) {
 
934
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
 
935
                ssid = NULL;
 
936
        } else {
 
937
                id = atoi(cmd);
 
938
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
 
939
 
 
940
                ssid = wpa_config_get_network(wpa_s->conf, id);
 
941
                if (ssid == NULL) {
 
942
                        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
 
943
                                   "network id=%d", id);
 
944
                        return -1;
 
945
                }
 
946
        }
 
947
        wpa_supplicant_enable_network(wpa_s, ssid);
 
948
 
 
949
        return 0;
 
950
}
 
951
 
 
952
 
 
953
static int wpa_supplicant_ctrl_iface_disable_network(
 
954
        struct wpa_supplicant *wpa_s, char *cmd)
 
955
{
 
956
        int id;
 
957
        struct wpa_ssid *ssid;
 
958
 
 
959
        /* cmd: "<network id>" or "all" */
 
960
        if (os_strcmp(cmd, "all") == 0) {
 
961
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
 
962
                ssid = NULL;
 
963
        } else {
 
964
                id = atoi(cmd);
 
965
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
 
966
 
 
967
                ssid = wpa_config_get_network(wpa_s->conf, id);
 
968
                if (ssid == NULL) {
 
969
                        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
 
970
                                   "network id=%d", id);
 
971
                        return -1;
 
972
                }
 
973
        }
 
974
        wpa_supplicant_disable_network(wpa_s, ssid);
 
975
 
 
976
        return 0;
 
977
}
 
978
 
 
979
 
 
980
static int wpa_supplicant_ctrl_iface_add_network(
 
981
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
982
{
 
983
        struct wpa_ssid *ssid;
 
984
        int ret;
 
985
 
 
986
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
 
987
 
 
988
        ssid = wpa_config_add_network(wpa_s->conf);
 
989
        if (ssid == NULL)
 
990
                return -1;
 
991
 
 
992
        wpas_notify_network_added(wpa_s, ssid);
 
993
 
 
994
        ssid->disabled = 1;
 
995
        wpa_config_set_network_defaults(ssid);
 
996
 
 
997
        ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
 
998
        if (ret < 0 || (size_t) ret >= buflen)
 
999
                return -1;
 
1000
        return ret;
 
1001
}
 
1002
 
 
1003
 
 
1004
static int wpa_supplicant_ctrl_iface_remove_network(
 
1005
        struct wpa_supplicant *wpa_s, char *cmd)
 
1006
{
 
1007
        int id;
 
1008
        struct wpa_ssid *ssid;
 
1009
 
 
1010
        /* cmd: "<network id>" or "all" */
 
1011
        if (os_strcmp(cmd, "all") == 0) {
 
1012
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
 
1013
                ssid = wpa_s->conf->ssid;
 
1014
                while (ssid) {
 
1015
                        struct wpa_ssid *remove_ssid = ssid;
 
1016
                        id = ssid->id;
 
1017
                        ssid = ssid->next;
 
1018
                        wpas_notify_network_removed(wpa_s, remove_ssid);
 
1019
                        wpa_config_remove_network(wpa_s->conf, id);
 
1020
                }
 
1021
                if (wpa_s->current_ssid) {
 
1022
                        eapol_sm_invalidate_cached_session(wpa_s->eapol);
 
1023
                        wpa_supplicant_disassociate(wpa_s,
 
1024
                                                    WLAN_REASON_DEAUTH_LEAVING);
 
1025
                }
 
1026
                return 0;
 
1027
        }
 
1028
 
 
1029
        id = atoi(cmd);
 
1030
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
 
1031
 
 
1032
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
1033
        if (ssid == NULL ||
 
1034
            wpa_config_remove_network(wpa_s->conf, id) < 0) {
 
1035
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
1036
                           "id=%d", id);
 
1037
                return -1;
 
1038
        }
 
1039
 
 
1040
        if (ssid == wpa_s->current_ssid) {
 
1041
                /*
 
1042
                 * Invalidate the EAP session cache if the current network is
 
1043
                 * removed.
 
1044
                 */
 
1045
                eapol_sm_invalidate_cached_session(wpa_s->eapol);
 
1046
 
 
1047
                wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
 
1048
        }
 
1049
 
 
1050
        return 0;
 
1051
}
 
1052
 
 
1053
 
 
1054
static int wpa_supplicant_ctrl_iface_set_network(
 
1055
        struct wpa_supplicant *wpa_s, char *cmd)
 
1056
{
 
1057
        int id;
 
1058
        struct wpa_ssid *ssid;
 
1059
        char *name, *value;
 
1060
 
 
1061
        /* cmd: "<network id> <variable name> <value>" */
 
1062
        name = os_strchr(cmd, ' ');
 
1063
        if (name == NULL)
 
1064
                return -1;
 
1065
        *name++ = '\0';
 
1066
 
 
1067
        value = os_strchr(name, ' ');
 
1068
        if (value == NULL)
 
1069
                return -1;
 
1070
        *value++ = '\0';
 
1071
 
 
1072
        id = atoi(cmd);
 
1073
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
 
1074
                   id, name);
 
1075
        wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
 
1076
                              (u8 *) value, os_strlen(value));
 
1077
 
 
1078
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
1079
        if (ssid == NULL) {
 
1080
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
1081
                           "id=%d", id);
 
1082
                return -1;
 
1083
        }
 
1084
 
 
1085
        if (wpa_config_set(ssid, name, value, 0) < 0) {
 
1086
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
 
1087
                           "variable '%s'", name);
 
1088
                return -1;
 
1089
        }
 
1090
 
 
1091
        if (wpa_s->current_ssid == ssid) {
 
1092
                /*
 
1093
                 * Invalidate the EAP session cache if anything in the current
 
1094
                 * configuration changes.
 
1095
                 */
 
1096
                eapol_sm_invalidate_cached_session(wpa_s->eapol);
 
1097
        }
 
1098
 
 
1099
        if ((os_strcmp(name, "psk") == 0 &&
 
1100
             value[0] == '"' && ssid->ssid_len) ||
 
1101
            (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
 
1102
                wpa_config_update_psk(ssid);
 
1103
        else if (os_strcmp(name, "priority") == 0)
 
1104
                wpa_config_update_prio_list(wpa_s->conf);
 
1105
 
 
1106
        return 0;
 
1107
}
 
1108
 
 
1109
 
 
1110
static int wpa_supplicant_ctrl_iface_get_network(
 
1111
        struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
 
1112
{
 
1113
        int id;
 
1114
        size_t res;
 
1115
        struct wpa_ssid *ssid;
 
1116
        char *name, *value;
 
1117
 
 
1118
        /* cmd: "<network id> <variable name>" */
 
1119
        name = os_strchr(cmd, ' ');
 
1120
        if (name == NULL || buflen == 0)
 
1121
                return -1;
 
1122
        *name++ = '\0';
 
1123
 
 
1124
        id = atoi(cmd);
 
1125
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
 
1126
                   id, name);
 
1127
 
 
1128
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
1129
        if (ssid == NULL) {
 
1130
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
1131
                           "id=%d", id);
 
1132
                return -1;
 
1133
        }
 
1134
 
 
1135
        value = wpa_config_get_no_key(ssid, name);
 
1136
        if (value == NULL) {
 
1137
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
 
1138
                           "variable '%s'", name);
 
1139
                return -1;
 
1140
        }
 
1141
 
 
1142
        res = os_strlcpy(buf, value, buflen);
 
1143
        if (res >= buflen) {
 
1144
                os_free(value);
 
1145
                return -1;
 
1146
        }
 
1147
 
 
1148
        os_free(value);
 
1149
 
 
1150
        return res;
 
1151
}
 
1152
 
 
1153
 
 
1154
#ifndef CONFIG_NO_CONFIG_WRITE
 
1155
static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
 
1156
{
 
1157
        int ret;
 
1158
 
 
1159
        if (!wpa_s->conf->update_config) {
 
1160
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
 
1161
                           "to update configuration (update_config=0)");
 
1162
                return -1;
 
1163
        }
 
1164
 
 
1165
        ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
 
1166
        if (ret) {
 
1167
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
 
1168
                           "update configuration");
 
1169
        } else {
 
1170
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
 
1171
                           " updated");
 
1172
        }
 
1173
 
 
1174
        return ret;
 
1175
}
 
1176
#endif /* CONFIG_NO_CONFIG_WRITE */
 
1177
 
 
1178
 
 
1179
static int ctrl_iface_get_capability_pairwise(int res, char *strict,
 
1180
                                              struct wpa_driver_capa *capa,
 
1181
                                              char *buf, size_t buflen)
 
1182
{
 
1183
        int ret, first = 1;
 
1184
        char *pos, *end;
 
1185
        size_t len;
 
1186
 
 
1187
        pos = buf;
 
1188
        end = pos + buflen;
 
1189
 
 
1190
        if (res < 0) {
 
1191
                if (strict)
 
1192
                        return 0;
 
1193
                len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
 
1194
                if (len >= buflen)
 
1195
                        return -1;
 
1196
                return len;
 
1197
        }
 
1198
 
 
1199
        if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
1200
                ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
 
1201
                if (ret < 0 || ret >= end - pos)
 
1202
                        return pos - buf;
 
1203
                pos += ret;
 
1204
                first = 0;
 
1205
        }
 
1206
 
 
1207
        if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
1208
                ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
 
1209
                if (ret < 0 || ret >= end - pos)
 
1210
                        return pos - buf;
 
1211
                pos += ret;
 
1212
                first = 0;
 
1213
        }
 
1214
 
 
1215
        if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
1216
                ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
 
1217
                if (ret < 0 || ret >= end - pos)
 
1218
                        return pos - buf;
 
1219
                pos += ret;
 
1220
                first = 0;
 
1221
        }
 
1222
 
 
1223
        return pos - buf;
 
1224
}
 
1225
 
 
1226
 
 
1227
static int ctrl_iface_get_capability_group(int res, char *strict,
 
1228
                                           struct wpa_driver_capa *capa,
 
1229
                                           char *buf, size_t buflen)
 
1230
{
 
1231
        int ret, first = 1;
 
1232
        char *pos, *end;
 
1233
        size_t len;
 
1234
 
 
1235
        pos = buf;
 
1236
        end = pos + buflen;
 
1237
 
 
1238
        if (res < 0) {
 
1239
                if (strict)
 
1240
                        return 0;
 
1241
                len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
 
1242
                if (len >= buflen)
 
1243
                        return -1;
 
1244
                return len;
 
1245
        }
 
1246
 
 
1247
        if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
1248
                ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
 
1249
                if (ret < 0 || ret >= end - pos)
 
1250
                        return pos - buf;
 
1251
                pos += ret;
 
1252
                first = 0;
 
1253
        }
 
1254
 
 
1255
        if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
1256
                ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
 
1257
                if (ret < 0 || ret >= end - pos)
 
1258
                        return pos - buf;
 
1259
                pos += ret;
 
1260
                first = 0;
 
1261
        }
 
1262
 
 
1263
        if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
 
1264
                ret = os_snprintf(pos, end - pos, "%sWEP104",
 
1265
                                  first ? "" : " ");
 
1266
                if (ret < 0 || ret >= end - pos)
 
1267
                        return pos - buf;
 
1268
                pos += ret;
 
1269
                first = 0;
 
1270
        }
 
1271
 
 
1272
        if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
 
1273
                ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
 
1274
                if (ret < 0 || ret >= end - pos)
 
1275
                        return pos - buf;
 
1276
                pos += ret;
 
1277
                first = 0;
 
1278
        }
 
1279
 
 
1280
        return pos - buf;
 
1281
}
 
1282
 
 
1283
 
 
1284
static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
 
1285
                                              struct wpa_driver_capa *capa,
 
1286
                                              char *buf, size_t buflen)
 
1287
{
 
1288
        int ret;
 
1289
        char *pos, *end;
 
1290
        size_t len;
 
1291
 
 
1292
        pos = buf;
 
1293
        end = pos + buflen;
 
1294
 
 
1295
        if (res < 0) {
 
1296
                if (strict)
 
1297
                        return 0;
 
1298
                len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
 
1299
                                 "NONE", buflen);
 
1300
                if (len >= buflen)
 
1301
                        return -1;
 
1302
                return len;
 
1303
        }
 
1304
 
 
1305
        ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
 
1306
        if (ret < 0 || ret >= end - pos)
 
1307
                return pos - buf;
 
1308
        pos += ret;
 
1309
 
 
1310
        if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
1311
                              WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
 
1312
                ret = os_snprintf(pos, end - pos, " WPA-EAP");
 
1313
                if (ret < 0 || ret >= end - pos)
 
1314
                        return pos - buf;
 
1315
                pos += ret;
 
1316
        }
 
1317
 
 
1318
        if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
 
1319
                              WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
1320
                ret = os_snprintf(pos, end - pos, " WPA-PSK");
 
1321
                if (ret < 0 || ret >= end - pos)
 
1322
                        return pos - buf;
 
1323
                pos += ret;
 
1324
        }
 
1325
 
 
1326
        if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
1327
                ret = os_snprintf(pos, end - pos, " WPA-NONE");
 
1328
                if (ret < 0 || ret >= end - pos)
 
1329
                        return pos - buf;
 
1330
                pos += ret;
 
1331
        }
 
1332
 
 
1333
        return pos - buf;
 
1334
}
 
1335
 
 
1336
 
 
1337
static int ctrl_iface_get_capability_proto(int res, char *strict,
 
1338
                                           struct wpa_driver_capa *capa,
 
1339
                                           char *buf, size_t buflen)
 
1340
{
 
1341
        int ret, first = 1;
 
1342
        char *pos, *end;
 
1343
        size_t len;
 
1344
 
 
1345
        pos = buf;
 
1346
        end = pos + buflen;
 
1347
 
 
1348
        if (res < 0) {
 
1349
                if (strict)
 
1350
                        return 0;
 
1351
                len = os_strlcpy(buf, "RSN WPA", buflen);
 
1352
                if (len >= buflen)
 
1353
                        return -1;
 
1354
                return len;
 
1355
        }
 
1356
 
 
1357
        if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
 
1358
                              WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
1359
                ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
 
1360
                if (ret < 0 || ret >= end - pos)
 
1361
                        return pos - buf;
 
1362
                pos += ret;
 
1363
                first = 0;
 
1364
        }
 
1365
 
 
1366
        if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
1367
                              WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
 
1368
                ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
 
1369
                if (ret < 0 || ret >= end - pos)
 
1370
                        return pos - buf;
 
1371
                pos += ret;
 
1372
                first = 0;
 
1373
        }
 
1374
 
 
1375
        return pos - buf;
 
1376
}
 
1377
 
 
1378
 
 
1379
static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
 
1380
                                              struct wpa_driver_capa *capa,
 
1381
                                              char *buf, size_t buflen)
 
1382
{
 
1383
        int ret, first = 1;
 
1384
        char *pos, *end;
 
1385
        size_t len;
 
1386
 
 
1387
        pos = buf;
 
1388
        end = pos + buflen;
 
1389
 
 
1390
        if (res < 0) {
 
1391
                if (strict)
 
1392
                        return 0;
 
1393
                len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
 
1394
                if (len >= buflen)
 
1395
                        return -1;
 
1396
                return len;
 
1397
        }
 
1398
 
 
1399
        if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
 
1400
                ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
 
1401
                if (ret < 0 || ret >= end - pos)
 
1402
                        return pos - buf;
 
1403
                pos += ret;
 
1404
                first = 0;
 
1405
        }
 
1406
 
 
1407
        if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
 
1408
                ret = os_snprintf(pos, end - pos, "%sSHARED",
 
1409
                                  first ? "" : " ");
 
1410
                if (ret < 0 || ret >= end - pos)
 
1411
                        return pos - buf;
 
1412
                pos += ret;
 
1413
                first = 0;
 
1414
        }
 
1415
 
 
1416
        if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
 
1417
                ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
 
1418
                if (ret < 0 || ret >= end - pos)
 
1419
                        return pos - buf;
 
1420
                pos += ret;
 
1421
                first = 0;
 
1422
        }
 
1423
 
 
1424
        return pos - buf;
 
1425
}
 
1426
 
 
1427
 
 
1428
static int wpa_supplicant_ctrl_iface_get_capability(
 
1429
        struct wpa_supplicant *wpa_s, const char *_field, char *buf,
 
1430
        size_t buflen)
 
1431
{
 
1432
        struct wpa_driver_capa capa;
 
1433
        int res;
 
1434
        char *strict;
 
1435
        char field[30];
 
1436
        size_t len;
 
1437
 
 
1438
        /* Determine whether or not strict checking was requested */
 
1439
        len = os_strlcpy(field, _field, sizeof(field));
 
1440
        if (len >= sizeof(field))
 
1441
                return -1;
 
1442
        strict = os_strchr(field, ' ');
 
1443
        if (strict != NULL) {
 
1444
                *strict++ = '\0';
 
1445
                if (os_strcmp(strict, "strict") != 0)
 
1446
                        return -1;
 
1447
        }
 
1448
 
 
1449
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
 
1450
                field, strict ? strict : "");
 
1451
 
 
1452
        if (os_strcmp(field, "eap") == 0) {
 
1453
                return eap_get_names(buf, buflen);
 
1454
        }
 
1455
 
 
1456
        res = wpa_drv_get_capa(wpa_s, &capa);
 
1457
 
 
1458
        if (os_strcmp(field, "pairwise") == 0)
 
1459
                return ctrl_iface_get_capability_pairwise(res, strict, &capa,
 
1460
                                                          buf, buflen);
 
1461
 
 
1462
        if (os_strcmp(field, "group") == 0)
 
1463
                return ctrl_iface_get_capability_group(res, strict, &capa,
 
1464
                                                       buf, buflen);
 
1465
 
 
1466
        if (os_strcmp(field, "key_mgmt") == 0)
 
1467
                return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
 
1468
                                                          buf, buflen);
 
1469
 
 
1470
        if (os_strcmp(field, "proto") == 0)
 
1471
                return ctrl_iface_get_capability_proto(res, strict, &capa,
 
1472
                                                       buf, buflen);
 
1473
 
 
1474
        if (os_strcmp(field, "auth_alg") == 0)
 
1475
                return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
 
1476
                                                          buf, buflen);
 
1477
 
 
1478
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
 
1479
                   field);
 
1480
 
 
1481
        return -1;
 
1482
}
 
1483
 
 
1484
 
 
1485
static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
 
1486
                                         const char *cmd, char *buf,
 
1487
                                         size_t buflen)
 
1488
{
 
1489
        u8 bssid[ETH_ALEN];
 
1490
        size_t i;
 
1491
        struct wpa_bss *bss;
 
1492
        int ret;
 
1493
        char *pos, *end;
 
1494
        const u8 *ie, *ie2;
 
1495
 
 
1496
        if (os_strcmp(cmd, "FIRST") == 0)
 
1497
                bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
 
1498
        else if (os_strncmp(cmd, "ID-", 3) == 0) {
 
1499
                i = atoi(cmd + 3);
 
1500
                bss = wpa_bss_get_id(wpa_s, i);
 
1501
        } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
 
1502
                i = atoi(cmd + 5);
 
1503
                bss = wpa_bss_get_id(wpa_s, i);
 
1504
                if (bss) {
 
1505
                        struct dl_list *next = bss->list_id.next;
 
1506
                        if (next == &wpa_s->bss_id)
 
1507
                                bss = NULL;
 
1508
                        else
 
1509
                                bss = dl_list_entry(next, struct wpa_bss,
 
1510
                                                    list_id);
 
1511
                }
 
1512
        } else if (hwaddr_aton(cmd, bssid) == 0)
 
1513
                bss = wpa_bss_get_bssid(wpa_s, bssid);
 
1514
        else {
 
1515
                struct wpa_bss *tmp;
 
1516
                i = atoi(cmd);
 
1517
                bss = NULL;
 
1518
                dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
 
1519
                {
 
1520
                        if (i-- == 0) {
 
1521
                                bss = tmp;
 
1522
                                break;
 
1523
                        }
 
1524
                }
 
1525
        }
 
1526
 
 
1527
        if (bss == NULL)
 
1528
                return 0;
 
1529
 
 
1530
        pos = buf;
 
1531
        end = buf + buflen;
 
1532
        ret = os_snprintf(pos, end - pos,
 
1533
                          "id=%u\n"
 
1534
                          "bssid=" MACSTR "\n"
 
1535
                          "freq=%d\n"
 
1536
                          "beacon_int=%d\n"
 
1537
                          "capabilities=0x%04x\n"
 
1538
                          "qual=%d\n"
 
1539
                          "noise=%d\n"
 
1540
                          "level=%d\n"
 
1541
                          "tsf=%016llu\n"
 
1542
                          "ie=",
 
1543
                          bss->id,
 
1544
                          MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
 
1545
                          bss->caps, bss->qual, bss->noise, bss->level,
 
1546
                          (unsigned long long) bss->tsf);
 
1547
        if (ret < 0 || ret >= end - pos)
 
1548
                return pos - buf;
 
1549
        pos += ret;
 
1550
 
 
1551
        ie = (const u8 *) (bss + 1);
 
1552
        for (i = 0; i < bss->ie_len; i++) {
 
1553
                ret = os_snprintf(pos, end - pos, "%02x", *ie++);
 
1554
                if (ret < 0 || ret >= end - pos)
 
1555
                        return pos - buf;
 
1556
                pos += ret;
 
1557
        }
 
1558
 
 
1559
        ret = os_snprintf(pos, end - pos, "\n");
 
1560
        if (ret < 0 || ret >= end - pos)
 
1561
                return pos - buf;
 
1562
        pos += ret;
 
1563
 
 
1564
        ret = os_snprintf(pos, end - pos, "flags=");
 
1565
        if (ret < 0 || ret >= end - pos)
 
1566
                return pos - buf;
 
1567
        pos += ret;
 
1568
 
 
1569
        ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 
1570
        if (ie)
 
1571
                pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
 
1572
        ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
 
1573
        if (ie2)
 
1574
                pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
 
1575
        pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
 
1576
        if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
 
1577
                ret = os_snprintf(pos, end - pos, "[WEP]");
 
1578
                if (ret < 0 || ret >= end - pos)
 
1579
                        return pos - buf;
 
1580
                pos += ret;
 
1581
        }
 
1582
        if (bss->caps & IEEE80211_CAP_IBSS) {
 
1583
                ret = os_snprintf(pos, end - pos, "[IBSS]");
 
1584
                if (ret < 0 || ret >= end - pos)
 
1585
                        return pos - buf;
 
1586
                pos += ret;
 
1587
        }
 
1588
        if (bss->caps & IEEE80211_CAP_ESS) {
 
1589
                ret = os_snprintf(pos, end - pos, "[ESS]");
 
1590
                if (ret < 0 || ret >= end - pos)
 
1591
                        return pos - buf;
 
1592
                pos += ret;
 
1593
        }
 
1594
 
 
1595
        ret = os_snprintf(pos, end - pos, "\n");
 
1596
        if (ret < 0 || ret >= end - pos)
 
1597
                return pos - buf;
 
1598
        pos += ret;
 
1599
 
 
1600
        ret = os_snprintf(pos, end - pos, "ssid=%s\n",
 
1601
                          wpa_ssid_txt(bss->ssid, bss->ssid_len));
 
1602
        if (ret < 0 || ret >= end - pos)
 
1603
                return pos - buf;
 
1604
        pos += ret;
 
1605
 
 
1606
#ifdef CONFIG_WPS
 
1607
        ie = (const u8 *) (bss + 1);
 
1608
        ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
 
1609
        if (ret < 0 || ret >= end - pos)
 
1610
                return pos - buf;
 
1611
        pos += ret;
 
1612
#endif /* CONFIG_WPS */
 
1613
 
 
1614
        return pos - buf;
 
1615
}
 
1616
 
 
1617
 
 
1618
static int wpa_supplicant_ctrl_iface_ap_scan(
 
1619
        struct wpa_supplicant *wpa_s, char *cmd)
 
1620
{
 
1621
        int ap_scan = atoi(cmd);
 
1622
        return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
 
1623
}
 
1624
 
 
1625
 
 
1626
static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
 
1627
{
 
1628
        u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff";
 
1629
 
 
1630
        wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
 
1631
        /* MLME-DELETEKEYS.request */
 
1632
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0);
 
1633
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0);
 
1634
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0);
 
1635
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0);
 
1636
#ifdef CONFIG_IEEE80211W
 
1637
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 4, 0, NULL, 0, NULL, 0);
 
1638
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 5, 0, NULL, 0, NULL, 0);
 
1639
#endif /* CONFIG_IEEE80211W */
 
1640
 
 
1641
        wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
 
1642
                        0);
 
1643
        /* MLME-SETPROTECTION.request(None) */
 
1644
        wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
 
1645
                                   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
 
1646
                                   MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
 
1647
        wpa_sm_drop_sa(wpa_s->wpa);
 
1648
}
 
1649
 
 
1650
 
 
1651
static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
 
1652
                                          char *addr)
 
1653
{
 
1654
        u8 bssid[ETH_ALEN];
 
1655
        struct wpa_bss *bss;
 
1656
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
1657
 
 
1658
        if (hwaddr_aton(addr, bssid)) {
 
1659
                wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
 
1660
                           "address '%s'", addr);
 
1661
                return -1;
 
1662
        }
 
1663
 
 
1664
        wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
 
1665
 
 
1666
        bss = wpa_bss_get_bssid(wpa_s, bssid);
 
1667
        if (!bss) {
 
1668
                wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
 
1669
                           "from BSS table");
 
1670
                return -1;
 
1671
        }
 
1672
 
 
1673
        /*
 
1674
         * TODO: Find best network configuration block from configuration to
 
1675
         * allow roaming to other networks
 
1676
         */
 
1677
 
 
1678
        if (!ssid) {
 
1679
                wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
 
1680
                           "configuration known for the target AP");
 
1681
                return -1;
 
1682
        }
 
1683
 
 
1684
        wpa_s->reassociate = 1;
 
1685
        wpa_supplicant_connect(wpa_s, bss, ssid);
 
1686
 
 
1687
        return 0;
 
1688
}
 
1689
 
 
1690
 
 
1691
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 
1692
                                         char *buf, size_t *resp_len)
 
1693
{
 
1694
        char *reply;
 
1695
        const int reply_size = 2048;
 
1696
        int ctrl_rsp = 0;
 
1697
        int reply_len;
 
1698
 
 
1699
        if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
 
1700
            os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
 
1701
                wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
 
1702
                                      (const u8 *) buf, os_strlen(buf));
 
1703
        } else {
 
1704
                wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
 
1705
                                  (const u8 *) buf, os_strlen(buf));
 
1706
        }
 
1707
 
 
1708
        reply = os_malloc(reply_size);
 
1709
        if (reply == NULL) {
 
1710
                *resp_len = 1;
 
1711
                return NULL;
 
1712
        }
 
1713
 
 
1714
        os_memcpy(reply, "OK\n", 3);
 
1715
        reply_len = 3;
 
1716
 
 
1717
        if (os_strcmp(buf, "PING") == 0) {
 
1718
                os_memcpy(reply, "PONG\n", 5);
 
1719
                reply_len = 5;
 
1720
        } else if (os_strcmp(buf, "MIB") == 0) {
 
1721
                reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
 
1722
                if (reply_len >= 0) {
 
1723
                        int res;
 
1724
                        res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
 
1725
                                               reply_size - reply_len);
 
1726
                        if (res < 0)
 
1727
                                reply_len = -1;
 
1728
                        else
 
1729
                                reply_len += res;
 
1730
                }
 
1731
        } else if (os_strncmp(buf, "STATUS", 6) == 0) {
 
1732
                reply_len = wpa_supplicant_ctrl_iface_status(
 
1733
                        wpa_s, buf + 6, reply, reply_size);
 
1734
        } else if (os_strcmp(buf, "PMKSA") == 0) {
 
1735
                reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
 
1736
                                                    reply_size);
 
1737
        } else if (os_strncmp(buf, "SET ", 4) == 0) {
 
1738
                if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
 
1739
                        reply_len = -1;
 
1740
        } else if (os_strcmp(buf, "LOGON") == 0) {
 
1741
                eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
 
1742
        } else if (os_strcmp(buf, "LOGOFF") == 0) {
 
1743
                eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
 
1744
        } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
 
1745
                wpa_s->disconnected = 0;
 
1746
                wpa_s->reassociate = 1;
 
1747
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1748
        } else if (os_strcmp(buf, "RECONNECT") == 0) {
 
1749
                if (wpa_s->disconnected) {
 
1750
                        wpa_s->disconnected = 0;
 
1751
                        wpa_s->reassociate = 1;
 
1752
                        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1753
                }
 
1754
#ifdef IEEE8021X_EAPOL
 
1755
        } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
 
1756
                if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
 
1757
                        reply_len = -1;
 
1758
#endif /* IEEE8021X_EAPOL */
 
1759
#ifdef CONFIG_PEERKEY
 
1760
        } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
 
1761
                if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
 
1762
                        reply_len = -1;
 
1763
#endif /* CONFIG_PEERKEY */
 
1764
#ifdef CONFIG_IEEE80211R
 
1765
        } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
 
1766
                if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
 
1767
                        reply_len = -1;
 
1768
#endif /* CONFIG_IEEE80211R */
 
1769
#ifdef CONFIG_WPS
 
1770
        } else if (os_strcmp(buf, "WPS_PBC") == 0) {
 
1771
                if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
 
1772
                        reply_len = -1;
 
1773
        } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
 
1774
                if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
 
1775
                        reply_len = -1;
 
1776
        } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
 
1777
                reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
 
1778
                                                              reply,
 
1779
                                                              reply_size);
 
1780
#ifdef CONFIG_WPS_OOB
 
1781
        } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
 
1782
                if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
 
1783
                        reply_len = -1;
 
1784
#endif /* CONFIG_WPS_OOB */
 
1785
        } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
 
1786
                if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
 
1787
                        reply_len = -1;
 
1788
#ifdef CONFIG_WPS_ER
 
1789
        } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
 
1790
                if (wpas_wps_er_start(wpa_s))
 
1791
                        reply_len = -1;
 
1792
        } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
 
1793
                if (wpas_wps_er_stop(wpa_s))
 
1794
                        reply_len = -1;
 
1795
        } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
 
1796
                if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
 
1797
                        reply_len = -1;
 
1798
        } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
 
1799
                if (wpas_wps_er_pbc(wpa_s, buf + 11))
 
1800
                        reply_len = -1;
 
1801
        } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
 
1802
                if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
 
1803
                        reply_len = -1;
 
1804
#endif /* CONFIG_WPS_ER */
 
1805
#endif /* CONFIG_WPS */
 
1806
#ifdef CONFIG_IBSS_RSN
 
1807
        } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
 
1808
                if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
 
1809
                        reply_len = -1;
 
1810
#endif /* CONFIG_IBSS_RSN */
 
1811
        } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
 
1812
        {
 
1813
                if (wpa_supplicant_ctrl_iface_ctrl_rsp(
 
1814
                            wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
 
1815
                        reply_len = -1;
 
1816
                else
 
1817
                        ctrl_rsp = 1;
 
1818
        } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
 
1819
                if (wpa_supplicant_reload_configuration(wpa_s))
 
1820
                        reply_len = -1;
 
1821
        } else if (os_strcmp(buf, "TERMINATE") == 0) {
 
1822
                wpa_supplicant_terminate_proc(wpa_s->global);
 
1823
        } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
 
1824
                if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
 
1825
                        reply_len = -1;
 
1826
        } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
 
1827
                reply_len = wpa_supplicant_ctrl_iface_list_networks(
 
1828
                        wpa_s, reply, reply_size);
 
1829
        } else if (os_strcmp(buf, "DISCONNECT") == 0) {
 
1830
                wpa_s->reassociate = 0;
 
1831
                wpa_s->disconnected = 1;
 
1832
                wpa_supplicant_deauthenticate(wpa_s,
 
1833
                                              WLAN_REASON_DEAUTH_LEAVING);
 
1834
        } else if (os_strcmp(buf, "SCAN") == 0) {
 
1835
                wpa_s->scan_req = 2;
 
1836
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1837
        } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
 
1838
                reply_len = wpa_supplicant_ctrl_iface_scan_results(
 
1839
                        wpa_s, reply, reply_size);
 
1840
        } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
 
1841
                if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
 
1842
                        reply_len = -1;
 
1843
        } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
 
1844
                if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
 
1845
                        reply_len = -1;
 
1846
        } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
 
1847
                if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
 
1848
                        reply_len = -1;
 
1849
        } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
 
1850
                reply_len = wpa_supplicant_ctrl_iface_add_network(
 
1851
                        wpa_s, reply, reply_size);
 
1852
        } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
 
1853
                if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
 
1854
                        reply_len = -1;
 
1855
        } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
 
1856
                if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
 
1857
                        reply_len = -1;
 
1858
        } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
 
1859
                reply_len = wpa_supplicant_ctrl_iface_get_network(
 
1860
                        wpa_s, buf + 12, reply, reply_size);
 
1861
#ifndef CONFIG_NO_CONFIG_WRITE
 
1862
        } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
 
1863
                if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
 
1864
                        reply_len = -1;
 
1865
#endif /* CONFIG_NO_CONFIG_WRITE */
 
1866
        } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
 
1867
                reply_len = wpa_supplicant_ctrl_iface_get_capability(
 
1868
                        wpa_s, buf + 15, reply, reply_size);
 
1869
        } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
 
1870
                if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
 
1871
                        reply_len = -1;
 
1872
        } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
 
1873
                reply_len = wpa_supplicant_global_iface_list(
 
1874
                        wpa_s->global, reply, reply_size);
 
1875
        } else if (os_strcmp(buf, "INTERFACES") == 0) {
 
1876
                reply_len = wpa_supplicant_global_iface_interfaces(
 
1877
                        wpa_s->global, reply, reply_size);
 
1878
        } else if (os_strncmp(buf, "BSS ", 4) == 0) {
 
1879
                reply_len = wpa_supplicant_ctrl_iface_bss(
 
1880
                        wpa_s, buf + 4, reply, reply_size);
 
1881
#ifdef CONFIG_AP
 
1882
        } else if (os_strcmp(buf, "STA-FIRST") == 0) {
 
1883
                reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
 
1884
        } else if (os_strncmp(buf, "STA ", 4) == 0) {
 
1885
                reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
 
1886
                                              reply_size);
 
1887
        } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
 
1888
                reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
 
1889
                                                   reply_size);
 
1890
#endif /* CONFIG_AP */
 
1891
        } else if (os_strcmp(buf, "SUSPEND") == 0) {
 
1892
                wpas_notify_suspend(wpa_s->global);
 
1893
        } else if (os_strcmp(buf, "RESUME") == 0) {
 
1894
                wpas_notify_resume(wpa_s->global);
 
1895
        } else if (os_strcmp(buf, "DROP_SA") == 0) {
 
1896
                wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
 
1897
        } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
 
1898
                if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
 
1899
                        reply_len = -1;
 
1900
        } else {
 
1901
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 
1902
                reply_len = 16;
 
1903
        }
 
1904
 
 
1905
        if (reply_len < 0) {
 
1906
                os_memcpy(reply, "FAIL\n", 5);
 
1907
                reply_len = 5;
 
1908
        }
 
1909
 
 
1910
        if (ctrl_rsp)
 
1911
                eapol_sm_notify_ctrl_response(wpa_s->eapol);
 
1912
 
 
1913
        *resp_len = reply_len;
 
1914
        return reply;
 
1915
}
 
1916
 
 
1917
 
 
1918
static int wpa_supplicant_global_iface_add(struct wpa_global *global,
 
1919
                                           char *cmd)
 
1920
{
 
1921
        struct wpa_interface iface;
 
1922
        char *pos;
 
1923
 
 
1924
        /*
 
1925
         * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
 
1926
         * TAB<bridge_ifname>
 
1927
         */
 
1928
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
1929
 
 
1930
        os_memset(&iface, 0, sizeof(iface));
 
1931
 
 
1932
        do {
 
1933
                iface.ifname = pos = cmd;
 
1934
                pos = os_strchr(pos, '\t');
 
1935
                if (pos)
 
1936
                        *pos++ = '\0';
 
1937
                if (iface.ifname[0] == '\0')
 
1938
                        return -1;
 
1939
                if (pos == NULL)
 
1940
                        break;
 
1941
 
 
1942
                iface.confname = pos;
 
1943
                pos = os_strchr(pos, '\t');
 
1944
                if (pos)
 
1945
                        *pos++ = '\0';
 
1946
                if (iface.confname[0] == '\0')
 
1947
                        iface.confname = NULL;
 
1948
                if (pos == NULL)
 
1949
                        break;
 
1950
 
 
1951
                iface.driver = pos;
 
1952
                pos = os_strchr(pos, '\t');
 
1953
                if (pos)
 
1954
                        *pos++ = '\0';
 
1955
                if (iface.driver[0] == '\0')
 
1956
                        iface.driver = NULL;
 
1957
                if (pos == NULL)
 
1958
                        break;
 
1959
 
 
1960
                iface.ctrl_interface = pos;
 
1961
                pos = os_strchr(pos, '\t');
 
1962
                if (pos)
 
1963
                        *pos++ = '\0';
 
1964
                if (iface.ctrl_interface[0] == '\0')
 
1965
                        iface.ctrl_interface = NULL;
 
1966
                if (pos == NULL)
 
1967
                        break;
 
1968
 
 
1969
                iface.driver_param = pos;
 
1970
                pos = os_strchr(pos, '\t');
 
1971
                if (pos)
 
1972
                        *pos++ = '\0';
 
1973
                if (iface.driver_param[0] == '\0')
 
1974
                        iface.driver_param = NULL;
 
1975
                if (pos == NULL)
 
1976
                        break;
 
1977
 
 
1978
                iface.bridge_ifname = pos;
 
1979
                pos = os_strchr(pos, '\t');
 
1980
                if (pos)
 
1981
                        *pos++ = '\0';
 
1982
                if (iface.bridge_ifname[0] == '\0')
 
1983
                        iface.bridge_ifname = NULL;
 
1984
                if (pos == NULL)
 
1985
                        break;
 
1986
        } while (0);
 
1987
 
 
1988
        if (wpa_supplicant_get_iface(global, iface.ifname))
 
1989
                return -1;
 
1990
 
 
1991
        return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
 
1992
}
 
1993
 
 
1994
 
 
1995
static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
 
1996
                                              char *cmd)
 
1997
{
 
1998
        struct wpa_supplicant *wpa_s;
 
1999
 
 
2000
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
 
2001
 
 
2002
        wpa_s = wpa_supplicant_get_iface(global, cmd);
 
2003
        if (wpa_s == NULL)
 
2004
                return -1;
 
2005
        return wpa_supplicant_remove_iface(global, wpa_s);
 
2006
}
 
2007
 
 
2008
 
 
2009
static void wpa_free_iface_info(struct wpa_interface_info *iface)
 
2010
{
 
2011
        struct wpa_interface_info *prev;
 
2012
 
 
2013
        while (iface) {
 
2014
                prev = iface;
 
2015
                iface = iface->next;
 
2016
 
 
2017
                os_free(prev->ifname);
 
2018
                os_free(prev->desc);
 
2019
                os_free(prev);
 
2020
        }
 
2021
}
 
2022
 
 
2023
 
 
2024
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
 
2025
                                            char *buf, int len)
 
2026
{
 
2027
        int i, res;
 
2028
        struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
 
2029
        char *pos, *end;
 
2030
 
 
2031
        for (i = 0; wpa_drivers[i]; i++) {
 
2032
                struct wpa_driver_ops *drv = wpa_drivers[i];
 
2033
                if (drv->get_interfaces == NULL)
 
2034
                        continue;
 
2035
                tmp = drv->get_interfaces(global->drv_priv[i]);
 
2036
                if (tmp == NULL)
 
2037
                        continue;
 
2038
 
 
2039
                if (last == NULL)
 
2040
                        iface = last = tmp;
 
2041
                else
 
2042
                        last->next = tmp;
 
2043
                while (last->next)
 
2044
                        last = last->next;
 
2045
        }
 
2046
 
 
2047
        pos = buf;
 
2048
        end = buf + len;
 
2049
        for (tmp = iface; tmp; tmp = tmp->next) {
 
2050
                res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
 
2051
                                  tmp->drv_name, tmp->ifname,
 
2052
                                  tmp->desc ? tmp->desc : "");
 
2053
                if (res < 0 || res >= end - pos) {
 
2054
                        *pos = '\0';
 
2055
                        break;
 
2056
                }
 
2057
                pos += res;
 
2058
        }
 
2059
 
 
2060
        wpa_free_iface_info(iface);
 
2061
 
 
2062
        return pos - buf;
 
2063
}
 
2064
 
 
2065
 
 
2066
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 
2067
                                                  char *buf, int len)
 
2068
{
 
2069
        int res;
 
2070
        char *pos, *end;
 
2071
        struct wpa_supplicant *wpa_s;
 
2072
 
 
2073
        wpa_s = global->ifaces;
 
2074
        pos = buf;
 
2075
        end = buf + len;
 
2076
 
 
2077
        while (wpa_s) {
 
2078
                res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
 
2079
                if (res < 0 || res >= end - pos) {
 
2080
                        *pos = '\0';
 
2081
                        break;
 
2082
                }
 
2083
                pos += res;
 
2084
                wpa_s = wpa_s->next;
 
2085
        }
 
2086
        return pos - buf;
 
2087
}
 
2088
 
 
2089
 
 
2090
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
 
2091
                                                char *buf, size_t *resp_len)
 
2092
{
 
2093
        char *reply;
 
2094
        const int reply_size = 2048;
 
2095
        int reply_len;
 
2096
 
 
2097
        wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
 
2098
                          (const u8 *) buf, os_strlen(buf));
 
2099
 
 
2100
        reply = os_malloc(reply_size);
 
2101
        if (reply == NULL) {
 
2102
                *resp_len = 1;
 
2103
                return NULL;
 
2104
        }
 
2105
 
 
2106
        os_memcpy(reply, "OK\n", 3);
 
2107
        reply_len = 3;
 
2108
 
 
2109
        if (os_strcmp(buf, "PING") == 0) {
 
2110
                os_memcpy(reply, "PONG\n", 5);
 
2111
                reply_len = 5;
 
2112
        } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
 
2113
                if (wpa_supplicant_global_iface_add(global, buf + 14))
 
2114
                        reply_len = -1;
 
2115
        } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
 
2116
                if (wpa_supplicant_global_iface_remove(global, buf + 17))
 
2117
                        reply_len = -1;
 
2118
        } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
 
2119
                reply_len = wpa_supplicant_global_iface_list(
 
2120
                        global, reply, reply_size);
 
2121
        } else if (os_strcmp(buf, "INTERFACES") == 0) {
 
2122
                reply_len = wpa_supplicant_global_iface_interfaces(
 
2123
                        global, reply, reply_size);
 
2124
        } else if (os_strcmp(buf, "TERMINATE") == 0) {
 
2125
                wpa_supplicant_terminate_proc(global);
 
2126
        } else if (os_strcmp(buf, "SUSPEND") == 0) {
 
2127
                wpas_notify_suspend(global);
 
2128
        } else if (os_strcmp(buf, "RESUME") == 0) {
 
2129
                wpas_notify_resume(global);
 
2130
        } else {
 
2131
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 
2132
                reply_len = 16;
 
2133
        }
 
2134
 
 
2135
        if (reply_len < 0) {
 
2136
                os_memcpy(reply, "FAIL\n", 5);
 
2137
                reply_len = 5;
 
2138
        }
 
2139
 
 
2140
        *resp_len = reply_len;
 
2141
        return reply;
 
2142
}