~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to ctrl_iface.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2007-08-26 16:06:57 UTC
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20070826160657-mxk5ivjjh65ptxlr
Tags: upstream-0.6.0+0.5.8
ImportĀ upstreamĀ versionĀ 0.6.0+0.5.8

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-2006, Jouni Malinen <j@w1.fi>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * Alternatively, this software may be distributed under the terms of BSD
 
10
 * license.
 
11
 *
 
12
 * See README and COPYING for more details.
 
13
 */
 
14
 
 
15
#include "includes.h"
 
16
 
 
17
#include "common.h"
 
18
#include "eloop.h"
 
19
#include "wpa.h"
 
20
#include "wpa_supplicant.h"
 
21
#include "config.h"
 
22
#include "eapol_sm.h"
 
23
#include "wpa_supplicant_i.h"
 
24
#include "ctrl_iface.h"
 
25
#include "l2_packet.h"
 
26
#include "preauth.h"
 
27
#include "pmksa_cache.h"
 
28
#include "wpa_ctrl.h"
 
29
#include "eap.h"
 
30
 
 
31
 
 
32
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 
33
                                                  char *buf, int len);
 
34
 
 
35
 
 
36
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
 
37
                                         char *cmd)
 
38
{
 
39
        char *value;
 
40
        int ret = 0;
 
41
 
 
42
        value = os_strchr(cmd, ' ');
 
43
        if (value == NULL)
 
44
                return -1;
 
45
        *value++ = '\0';
 
46
 
 
47
        wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
 
48
        if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
 
49
                eapol_sm_configure(wpa_s->eapol,
 
50
                                   atoi(value), -1, -1, -1);
 
51
        } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
 
52
                eapol_sm_configure(wpa_s->eapol,
 
53
                                   -1, atoi(value), -1, -1);
 
54
        } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
 
55
                eapol_sm_configure(wpa_s->eapol,
 
56
                                   -1, -1, atoi(value), -1);
 
57
        } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
 
58
                eapol_sm_configure(wpa_s->eapol,
 
59
                                   -1, -1, -1, atoi(value));
 
60
        } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
 
61
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
 
62
                                     atoi(value)))
 
63
                        ret = -1;
 
64
        } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
 
65
                   0) {
 
66
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
 
67
                                     atoi(value)))
 
68
                        ret = -1;
 
69
        } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
 
70
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
 
71
                        ret = -1;
 
72
        } else
 
73
                ret = -1;
 
74
 
 
75
        return ret;
 
76
}
 
77
 
 
78
 
 
79
static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
 
80
                                             char *addr)
 
81
{
 
82
        u8 bssid[ETH_ALEN];
 
83
 
 
84
        if (hwaddr_aton(addr, bssid)) {
 
85
                wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
 
86
                           "'%s'", addr);
 
87
                return -1;
 
88
        }
 
89
 
 
90
        wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
 
91
        rsn_preauth_deinit(wpa_s->wpa);
 
92
        if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid))
 
93
                return -1;
 
94
 
 
95
        return 0;
 
96
}
 
97
 
 
98
 
 
99
#ifdef CONFIG_PEERKEY
 
100
/* MLME-STKSTART.request(peer) */
 
101
static int wpa_supplicant_ctrl_iface_stkstart(
 
102
        struct wpa_supplicant *wpa_s, char *addr)
 
103
{
 
104
        u8 peer[ETH_ALEN];
 
105
 
 
106
        if (hwaddr_aton(addr, peer)) {
 
107
                wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
 
108
                           "address '%s'", peer);
 
109
                return -1;
 
110
        }
 
111
 
 
112
        wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
 
113
                   MAC2STR(peer));
 
114
 
 
115
        return wpa_sm_stkstart(wpa_s->wpa, peer);
 
116
}
 
117
#endif /* CONFIG_PEERKEY */
 
118
 
 
119
 
 
120
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
 
121
                                              char *rsp)
 
122
{
 
123
#ifdef IEEE8021X_EAPOL
 
124
        char *pos, *id_pos;
 
125
        int id;
 
126
        struct wpa_ssid *ssid;
 
127
 
 
128
        pos = os_strchr(rsp, '-');
 
129
        if (pos == NULL)
 
130
                return -1;
 
131
        *pos++ = '\0';
 
132
        id_pos = pos;
 
133
        pos = os_strchr(pos, ':');
 
134
        if (pos == NULL)
 
135
                return -1;
 
136
        *pos++ = '\0';
 
137
        id = atoi(id_pos);
 
138
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
 
139
        wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
 
140
                              (u8 *) pos, os_strlen(pos));
 
141
 
 
142
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
143
        if (ssid == NULL) {
 
144
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
 
145
                           "to update", id);
 
146
                return -1;
 
147
        }
 
148
 
 
149
        if (os_strcmp(rsp, "IDENTITY") == 0) {
 
150
                os_free(ssid->identity);
 
151
                ssid->identity = (u8 *) os_strdup(pos);
 
152
                ssid->identity_len = os_strlen(pos);
 
153
                ssid->pending_req_identity = 0;
 
154
                if (ssid == wpa_s->current_ssid)
 
155
                        wpa_s->reassociate = 1;
 
156
        } else if (os_strcmp(rsp, "PASSWORD") == 0) {
 
157
                os_free(ssid->password);
 
158
                ssid->password = (u8 *) os_strdup(pos);
 
159
                ssid->password_len = os_strlen(pos);
 
160
                ssid->pending_req_password = 0;
 
161
                if (ssid == wpa_s->current_ssid)
 
162
                        wpa_s->reassociate = 1;
 
163
        } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
 
164
                os_free(ssid->new_password);
 
165
                ssid->new_password = (u8 *) os_strdup(pos);
 
166
                ssid->new_password_len = os_strlen(pos);
 
167
                ssid->pending_req_new_password = 0;
 
168
                if (ssid == wpa_s->current_ssid)
 
169
                        wpa_s->reassociate = 1;
 
170
        } else if (os_strcmp(rsp, "PIN") == 0) {
 
171
                os_free(ssid->pin);
 
172
                ssid->pin = os_strdup(pos);
 
173
                ssid->pending_req_pin = 0;
 
174
                if (ssid == wpa_s->current_ssid)
 
175
                        wpa_s->reassociate = 1;
 
176
        } else if (os_strcmp(rsp, "OTP") == 0) {
 
177
                os_free(ssid->otp);
 
178
                ssid->otp = (u8 *) os_strdup(pos);
 
179
                ssid->otp_len = os_strlen(pos);
 
180
                os_free(ssid->pending_req_otp);
 
181
                ssid->pending_req_otp = NULL;
 
182
                ssid->pending_req_otp_len = 0;
 
183
        } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
 
184
                os_free(ssid->private_key_passwd);
 
185
                ssid->private_key_passwd = (u8 *) os_strdup(pos);
 
186
                ssid->pending_req_passphrase = 0;
 
187
                if (ssid == wpa_s->current_ssid)
 
188
                        wpa_s->reassociate = 1;
 
189
        } else {
 
190
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
 
191
                return -1;
 
192
        }
 
193
 
 
194
        return 0;
 
195
#else /* IEEE8021X_EAPOL */
 
196
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
 
197
        return -1;
 
198
#endif /* IEEE8021X_EAPOL */
 
199
}
 
200
 
 
201
 
 
202
static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
 
203
                                            const char *params,
 
204
                                            char *buf, size_t buflen)
 
205
{
 
206
        char *pos, *end, tmp[30];
 
207
        int res, verbose, ret;
 
208
 
 
209
        verbose = os_strcmp(params, "-VERBOSE") == 0;
 
210
        pos = buf;
 
211
        end = buf + buflen;
 
212
        if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
 
213
                struct wpa_ssid *ssid = wpa_s->current_ssid;
 
214
                ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
 
215
                                  MAC2STR(wpa_s->bssid));
 
216
                if (ret < 0 || ret >= end - pos)
 
217
                        return pos - buf;
 
218
                pos += ret;
 
219
                if (ssid) {
 
220
                        u8 *_ssid = ssid->ssid;
 
221
                        size_t ssid_len = ssid->ssid_len;
 
222
                        u8 ssid_buf[MAX_SSID_LEN];
 
223
                        if (ssid_len == 0) {
 
224
                                int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
 
225
                                if (_res < 0)
 
226
                                        ssid_len = 0;
 
227
                                else
 
228
                                        ssid_len = _res;
 
229
                                _ssid = ssid_buf;
 
230
                        }
 
231
                        ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
 
232
                                          wpa_ssid_txt(_ssid, ssid_len),
 
233
                                          ssid->id);
 
234
                        if (ret < 0 || ret >= end - pos)
 
235
                                return pos - buf;
 
236
                        pos += ret;
 
237
 
 
238
                        if (ssid->id_str) {
 
239
                                ret = os_snprintf(pos, end - pos,
 
240
                                                  "id_str=%s\n",
 
241
                                                  ssid->id_str);
 
242
                                if (ret < 0 || ret >= end - pos)
 
243
                                        return pos - buf;
 
244
                                pos += ret;
 
245
                        }
 
246
                }
 
247
 
 
248
                pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
 
249
        }
 
250
        ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
 
251
                          wpa_supplicant_state_txt(wpa_s->wpa_state));
 
252
        if (ret < 0 || ret >= end - pos)
 
253
                return pos - buf;
 
254
        pos += ret;
 
255
 
 
256
        if (wpa_s->l2 &&
 
257
            l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
 
258
                ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
 
259
                if (ret < 0 || ret >= end - pos)
 
260
                        return pos - buf;
 
261
                pos += ret;
 
262
        }
 
263
 
 
264
        if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
 
265
            wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 
266
                res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
 
267
                                          verbose);
 
268
                if (res >= 0)
 
269
                        pos += res;
 
270
        }
 
271
 
 
272
        res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
 
273
        if (res >= 0)
 
274
                pos += res;
 
275
 
 
276
        return pos - buf;
 
277
}
 
278
 
 
279
 
 
280
static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
 
281
                                           char *cmd)
 
282
{
 
283
        char *pos;
 
284
        int id;
 
285
        struct wpa_ssid *ssid;
 
286
        u8 bssid[ETH_ALEN];
 
287
 
 
288
        /* cmd: "<network id> <BSSID>" */
 
289
        pos = os_strchr(cmd, ' ');
 
290
        if (pos == NULL)
 
291
                return -1;
 
292
        *pos++ = '\0';
 
293
        id = atoi(cmd);
 
294
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
 
295
        if (hwaddr_aton(pos, bssid)) {
 
296
                wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
 
297
                return -1;
 
298
        }
 
299
 
 
300
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
301
        if (ssid == NULL) {
 
302
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
 
303
                           "to update", id);
 
304
                return -1;
 
305
        }
 
306
 
 
307
        os_memcpy(ssid->bssid, bssid, ETH_ALEN);
 
308
        ssid->bssid_set =
 
309
                os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
 
310
                
 
311
 
 
312
        return 0;
 
313
}
 
314
 
 
315
 
 
316
static int wpa_supplicant_ctrl_iface_list_networks(
 
317
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
318
{
 
319
        char *pos, *end;
 
320
        struct wpa_ssid *ssid;
 
321
        int ret;
 
322
 
 
323
        pos = buf;
 
324
        end = buf + buflen;
 
325
        ret = os_snprintf(pos, end - pos,
 
326
                          "network id / ssid / bssid / flags\n");
 
327
        if (ret < 0 || ret >= end - pos)
 
328
                return pos - buf;
 
329
        pos += ret;
 
330
 
 
331
        ssid = wpa_s->conf->ssid;
 
332
        while (ssid) {
 
333
                ret = os_snprintf(pos, end - pos, "%d\t%s",
 
334
                                  ssid->id,
 
335
                                  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
 
336
                if (ret < 0 || ret >= end - pos)
 
337
                        return pos - buf;
 
338
                pos += ret;
 
339
                if (ssid->bssid_set) {
 
340
                        ret = os_snprintf(pos, end - pos, "\t" MACSTR,
 
341
                                          MAC2STR(ssid->bssid));
 
342
                } else {
 
343
                        ret = os_snprintf(pos, end - pos, "\tany");
 
344
                }
 
345
                if (ret < 0 || ret >= end - pos)
 
346
                        return pos - buf;
 
347
                pos += ret;
 
348
                ret = os_snprintf(pos, end - pos, "\t%s%s",
 
349
                                  ssid == wpa_s->current_ssid ?
 
350
                                  "[CURRENT]" : "",
 
351
                                  ssid->disabled ? "[DISABLED]" : "");
 
352
                if (ret < 0 || ret >= end - pos)
 
353
                        return pos - buf;
 
354
                pos += ret;
 
355
                ret = os_snprintf(pos, end - pos, "\n");
 
356
                if (ret < 0 || ret >= end - pos)
 
357
                        return pos - buf;
 
358
                pos += ret;
 
359
 
 
360
                ssid = ssid->next;
 
361
        }
 
362
 
 
363
        return pos - buf;
 
364
}
 
365
 
 
366
 
 
367
static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
 
368
{
 
369
        int first = 1, ret;
 
370
        ret = os_snprintf(pos, end - pos, "-");
 
371
        if (ret < 0 || ret >= end - pos)
 
372
                return pos;
 
373
        pos += ret;
 
374
        if (cipher & WPA_CIPHER_NONE) {
 
375
                ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
 
376
                if (ret < 0 || ret >= end - pos)
 
377
                        return pos;
 
378
                pos += ret;
 
379
                first = 0;
 
380
        }
 
381
        if (cipher & WPA_CIPHER_WEP40) {
 
382
                ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
 
383
                if (ret < 0 || ret >= end - pos)
 
384
                        return pos;
 
385
                pos += ret;
 
386
                first = 0;
 
387
        }
 
388
        if (cipher & WPA_CIPHER_WEP104) {
 
389
                ret = os_snprintf(pos, end - pos, "%sWEP104",
 
390
                                  first ? "" : "+");
 
391
                if (ret < 0 || ret >= end - pos)
 
392
                        return pos;
 
393
                pos += ret;
 
394
                first = 0;
 
395
        }
 
396
        if (cipher & WPA_CIPHER_TKIP) {
 
397
                ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
 
398
                if (ret < 0 || ret >= end - pos)
 
399
                        return pos;
 
400
                pos += ret;
 
401
                first = 0;
 
402
        }
 
403
        if (cipher & WPA_CIPHER_CCMP) {
 
404
                ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
 
405
                if (ret < 0 || ret >= end - pos)
 
406
                        return pos;
 
407
                pos += ret;
 
408
                first = 0;
 
409
        }
 
410
        return pos;
 
411
}
 
412
 
 
413
 
 
414
static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
 
415
                                    const u8 *ie, size_t ie_len)
 
416
{
 
417
        struct wpa_ie_data data;
 
418
        int first, ret;
 
419
 
 
420
        ret = os_snprintf(pos, end - pos, "[%s-", proto);
 
421
        if (ret < 0 || ret >= end - pos)
 
422
                return pos;
 
423
        pos += ret;
 
424
 
 
425
        if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
 
426
                ret = os_snprintf(pos, end - pos, "?]");
 
427
                if (ret < 0 || ret >= end - pos)
 
428
                        return pos;
 
429
                pos += ret;
 
430
                return pos;
 
431
        }
 
432
 
 
433
        first = 1;
 
434
        if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
 
435
                ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
 
436
                if (ret < 0 || ret >= end - pos)
 
437
                        return pos;
 
438
                pos += ret;
 
439
                first = 0;
 
440
        }
 
441
        if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
 
442
                ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
 
443
                if (ret < 0 || ret >= end - pos)
 
444
                        return pos;
 
445
                pos += ret;
 
446
                first = 0;
 
447
        }
 
448
        if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
 
449
                ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
 
450
                if (ret < 0 || ret >= end - pos)
 
451
                        return pos;
 
452
                pos += ret;
 
453
                first = 0;
 
454
        }
 
455
 
 
456
        pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
 
457
 
 
458
        if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
 
459
                ret = os_snprintf(pos, end - pos, "-preauth");
 
460
                if (ret < 0 || ret >= end - pos)
 
461
                        return pos;
 
462
                pos += ret;
 
463
        }
 
464
 
 
465
        ret = os_snprintf(pos, end - pos, "]");
 
466
        if (ret < 0 || ret >= end - pos)
 
467
                return pos;
 
468
        pos += ret;
 
469
 
 
470
        return pos;
 
471
}
 
472
 
 
473
 
 
474
static int wpa_supplicant_ctrl_iface_scan_results(
 
475
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
476
{
 
477
        char *pos, *end;
 
478
        struct wpa_scan_result *res;
 
479
        int i, ret;
 
480
 
 
481
        if (wpa_s->scan_results == NULL &&
 
482
            wpa_supplicant_get_scan_results(wpa_s) < 0)
 
483
                return 0;
 
484
        if (wpa_s->scan_results == NULL)
 
485
                return 0;
 
486
 
 
487
        pos = buf;
 
488
        end = buf + buflen;
 
489
        ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
 
490
                          "flags / ssid\n");
 
491
        if (ret < 0 || ret >= end - pos)
 
492
                return pos - buf;
 
493
        pos += ret;
 
494
 
 
495
        for (i = 0; i < wpa_s->num_scan_results; i++) {
 
496
                res = &wpa_s->scan_results[i];
 
497
                ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
 
498
                                  MAC2STR(res->bssid), res->freq, res->level);
 
499
                if (ret < 0 || ret >= end - pos)
 
500
                        return pos - buf;
 
501
                pos += ret;
 
502
                if (res->wpa_ie_len) {
 
503
                        pos = wpa_supplicant_ie_txt(pos, end, "WPA",
 
504
                                                    res->wpa_ie,
 
505
                                                    res->wpa_ie_len);
 
506
                }
 
507
                if (res->rsn_ie_len) {
 
508
                        pos = wpa_supplicant_ie_txt(pos, end, "WPA2",
 
509
                                                    res->rsn_ie,
 
510
                                                    res->rsn_ie_len);
 
511
                }
 
512
                if (!res->wpa_ie_len && !res->rsn_ie_len &&
 
513
                    res->caps & IEEE80211_CAP_PRIVACY) {
 
514
                        ret = os_snprintf(pos, end - pos, "[WEP]");
 
515
                        if (ret < 0 || ret >= end - pos)
 
516
                                return pos - buf;
 
517
                        pos += ret;
 
518
                }
 
519
                if (res->caps & IEEE80211_CAP_IBSS) {
 
520
                        ret = os_snprintf(pos, end - pos, "[IBSS]");
 
521
                        if (ret < 0 || ret >= end - pos)
 
522
                                return pos - buf;
 
523
                        pos += ret;
 
524
                }
 
525
 
 
526
                ret = os_snprintf(pos, end - pos, "\t%s",
 
527
                                  wpa_ssid_txt(res->ssid, res->ssid_len));
 
528
                if (ret < 0 || ret >= end - pos)
 
529
                        return pos - buf;
 
530
                pos += ret;
 
531
 
 
532
                ret = os_snprintf(pos, end - pos, "\n");
 
533
                if (ret < 0 || ret >= end - pos)
 
534
                        return pos - buf;
 
535
                pos += ret;
 
536
        }
 
537
 
 
538
        return pos - buf;
 
539
}
 
540
 
 
541
 
 
542
static int wpa_supplicant_ctrl_iface_select_network(
 
543
        struct wpa_supplicant *wpa_s, char *cmd)
 
544
{
 
545
        int id;
 
546
        struct wpa_ssid *ssid;
 
547
 
 
548
        /* cmd: "<network id>" or "any" */
 
549
        if (os_strcmp(cmd, "any") == 0) {
 
550
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
 
551
                ssid = wpa_s->conf->ssid;
 
552
                while (ssid) {
 
553
                        ssid->disabled = 0;
 
554
                        ssid = ssid->next;
 
555
                }
 
556
                wpa_s->reassociate = 1;
 
557
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
558
                return 0;
 
559
        }
 
560
 
 
561
        id = atoi(cmd);
 
562
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
 
563
 
 
564
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
565
        if (ssid == NULL) {
 
566
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
567
                           "id=%d", id);
 
568
                return -1;
 
569
        }
 
570
 
 
571
        if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
 
572
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
573
 
 
574
        /* Mark all other networks disabled and trigger reassociation */
 
575
        ssid = wpa_s->conf->ssid;
 
576
        while (ssid) {
 
577
                ssid->disabled = id != ssid->id;
 
578
                ssid = ssid->next;
 
579
        }
 
580
        wpa_s->reassociate = 1;
 
581
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
582
 
 
583
        return 0;
 
584
}
 
585
 
 
586
 
 
587
static int wpa_supplicant_ctrl_iface_enable_network(
 
588
        struct wpa_supplicant *wpa_s, char *cmd)
 
589
{
 
590
        int id;
 
591
        struct wpa_ssid *ssid;
 
592
 
 
593
        /* cmd: "<network id>" */
 
594
        id = atoi(cmd);
 
595
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
 
596
 
 
597
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
598
        if (ssid == NULL) {
 
599
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
600
                           "id=%d", id);
 
601
                return -1;
 
602
        }
 
603
 
 
604
        if (wpa_s->current_ssid == NULL && ssid->disabled) {
 
605
                /*
 
606
                 * Try to reassociate since there is no current configuration
 
607
                 * and a new network was made available. */
 
608
                wpa_s->reassociate = 1;
 
609
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
610
        }
 
611
        ssid->disabled = 0;
 
612
 
 
613
        return 0;
 
614
}
 
615
 
 
616
 
 
617
static int wpa_supplicant_ctrl_iface_disable_network(
 
618
        struct wpa_supplicant *wpa_s, char *cmd)
 
619
{
 
620
        int id;
 
621
        struct wpa_ssid *ssid;
 
622
 
 
623
        /* cmd: "<network id>" */
 
624
        id = atoi(cmd);
 
625
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
 
626
 
 
627
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
628
        if (ssid == NULL) {
 
629
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
630
                           "id=%d", id);
 
631
                return -1;
 
632
        }
 
633
 
 
634
        if (ssid == wpa_s->current_ssid)
 
635
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
636
        ssid->disabled = 1;
 
637
 
 
638
        return 0;
 
639
}
 
640
 
 
641
 
 
642
static int wpa_supplicant_ctrl_iface_add_network(
 
643
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
644
{
 
645
        struct wpa_ssid *ssid;
 
646
        int ret;
 
647
 
 
648
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
 
649
 
 
650
        ssid = wpa_config_add_network(wpa_s->conf);
 
651
        if (ssid == NULL)
 
652
                return -1;
 
653
        ssid->disabled = 1;
 
654
        wpa_config_set_network_defaults(ssid);
 
655
 
 
656
        ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
 
657
        if (ret < 0 || (size_t) ret >= buflen)
 
658
                return -1;
 
659
        return ret;
 
660
}
 
661
 
 
662
 
 
663
static int wpa_supplicant_ctrl_iface_remove_network(
 
664
        struct wpa_supplicant *wpa_s, char *cmd)
 
665
{
 
666
        int id;
 
667
        struct wpa_ssid *ssid;
 
668
 
 
669
        /* cmd: "<network id>" */
 
670
        id = atoi(cmd);
 
671
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
 
672
 
 
673
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
674
        if (ssid == NULL ||
 
675
            wpa_config_remove_network(wpa_s->conf, id) < 0) {
 
676
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
677
                           "id=%d", id);
 
678
                return -1;
 
679
        }
 
680
 
 
681
        if (ssid == wpa_s->current_ssid) {
 
682
                /*
 
683
                 * Invalidate the EAP session cache if the current network is
 
684
                 * removed.
 
685
                 */
 
686
                eapol_sm_invalidate_cached_session(wpa_s->eapol);
 
687
 
 
688
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
689
        }
 
690
 
 
691
        return 0;
 
692
}
 
693
 
 
694
 
 
695
static int wpa_supplicant_ctrl_iface_set_network(
 
696
        struct wpa_supplicant *wpa_s, char *cmd)
 
697
{
 
698
        int id;
 
699
        struct wpa_ssid *ssid;
 
700
        char *name, *value;
 
701
 
 
702
        /* cmd: "<network id> <variable name> <value>" */
 
703
        name = os_strchr(cmd, ' ');
 
704
        if (name == NULL)
 
705
                return -1;
 
706
        *name++ = '\0';
 
707
 
 
708
        value = os_strchr(name, ' ');
 
709
        if (value == NULL)
 
710
                return -1;
 
711
        *value++ = '\0';
 
712
 
 
713
        id = atoi(cmd);
 
714
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
 
715
                   id, name);
 
716
        wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
 
717
                              (u8 *) value, os_strlen(value));
 
718
 
 
719
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
720
        if (ssid == NULL) {
 
721
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
722
                           "id=%d", id);
 
723
                return -1;
 
724
        }
 
725
 
 
726
        if (wpa_config_set(ssid, name, value, 0) < 0) {
 
727
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
 
728
                           "variable '%s'", name);
 
729
                return -1;
 
730
        }
 
731
 
 
732
        if (wpa_s->current_ssid == ssid) {
 
733
                /*
 
734
                 * Invalidate the EAP session cache if anything in the current
 
735
                 * configuration changes.
 
736
                 */
 
737
                eapol_sm_invalidate_cached_session(wpa_s->eapol);
 
738
        }
 
739
 
 
740
        if ((os_strcmp(name, "psk") == 0 &&
 
741
             value[0] == '"' && ssid->ssid_len) ||
 
742
            (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
 
743
                wpa_config_update_psk(ssid);
 
744
 
 
745
        return 0;
 
746
}
 
747
 
 
748
 
 
749
static int wpa_supplicant_ctrl_iface_get_network(
 
750
        struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
 
751
{
 
752
        int id;
 
753
        struct wpa_ssid *ssid;
 
754
        char *name, *value;
 
755
 
 
756
        /* cmd: "<network id> <variable name>" */
 
757
        name = os_strchr(cmd, ' ');
 
758
        if (name == NULL || buflen == 0)
 
759
                return -1;
 
760
        *name++ = '\0';
 
761
 
 
762
        id = atoi(cmd);
 
763
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
 
764
                   id, name);
 
765
 
 
766
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
767
        if (ssid == NULL) {
 
768
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
769
                           "id=%d", id);
 
770
                return -1;
 
771
        }
 
772
 
 
773
        value = wpa_config_get_no_key(ssid, name);
 
774
        if (value == NULL) {
 
775
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
 
776
                           "variable '%s'", name);
 
777
                return -1;
 
778
        }
 
779
 
 
780
        os_snprintf(buf, buflen, "%s", value);
 
781
        buf[buflen - 1] = '\0';
 
782
 
 
783
        os_free(value);
 
784
 
 
785
        return os_strlen(buf);
 
786
}
 
787
 
 
788
 
 
789
static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
 
790
{
 
791
        int ret;
 
792
 
 
793
        if (!wpa_s->conf->update_config) {
 
794
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
 
795
                           "to update configuration (update_config=0)");
 
796
                return -1;
 
797
        }
 
798
 
 
799
        ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
 
800
        if (ret) {
 
801
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
 
802
                           "update configuration");
 
803
        } else {
 
804
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
 
805
                           " updated");
 
806
        }
 
807
 
 
808
        return ret;
 
809
}
 
810
 
 
811
 
 
812
static int wpa_supplicant_ctrl_iface_get_capability(
 
813
        struct wpa_supplicant *wpa_s, const char *_field, char *buf,
 
814
        size_t buflen)
 
815
{
 
816
        struct wpa_driver_capa capa;
 
817
        int res, first = 1, ret;
 
818
        char *pos, *end, *strict;
 
819
        char field[30];
 
820
 
 
821
        /* Determine whether or not strict checking was requested */
 
822
        os_snprintf(field, sizeof(field), "%s", _field);
 
823
        field[sizeof(field) - 1] = '\0';
 
824
        strict = os_strchr(field, ' ');
 
825
        if (strict != NULL) {
 
826
                *strict++ = '\0';
 
827
                if (os_strcmp(strict, "strict") != 0)
 
828
                        return -1;
 
829
        }
 
830
 
 
831
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
 
832
                field, strict ? strict : "");
 
833
 
 
834
        if (os_strcmp(field, "eap") == 0) {
 
835
                return eap_get_names(buf, buflen);
 
836
        }
 
837
 
 
838
        res = wpa_drv_get_capa(wpa_s, &capa);
 
839
 
 
840
        pos = buf;
 
841
        end = pos + buflen;
 
842
 
 
843
        if (os_strcmp(field, "pairwise") == 0) {
 
844
                if (res < 0) {
 
845
                        if (strict)
 
846
                                return 0;
 
847
                        ret = os_snprintf(buf, buflen, "CCMP TKIP NONE");
 
848
                        if (ret < 0 || (size_t) ret >= buflen)
 
849
                                return -1;
 
850
                        return ret;
 
851
                }
 
852
 
 
853
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
854
                        ret = os_snprintf(pos, end - pos, "%sCCMP",
 
855
                                          first ? "" : " ");
 
856
                        if (ret < 0 || ret >= end - pos)
 
857
                                return pos - buf;
 
858
                        pos += ret;
 
859
                        first = 0;
 
860
                }
 
861
 
 
862
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
863
                        ret = os_snprintf(pos, end - pos, "%sTKIP",
 
864
                                          first ? "" : " ");
 
865
                        if (ret < 0 || ret >= end - pos)
 
866
                                return pos - buf;
 
867
                        pos += ret;
 
868
                        first = 0;
 
869
                }
 
870
 
 
871
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
872
                        ret = os_snprintf(pos, end - pos, "%sNONE",
 
873
                                          first ? "" : " ");
 
874
                        if (ret < 0 || ret >= end - pos)
 
875
                                return pos - buf;
 
876
                        pos += ret;
 
877
                        first = 0;
 
878
                }
 
879
 
 
880
                return pos - buf;
 
881
        }
 
882
 
 
883
        if (os_strcmp(field, "group") == 0) {
 
884
                if (res < 0) {
 
885
                        if (strict)
 
886
                                return 0;
 
887
                        ret = os_snprintf(buf, buflen,
 
888
                                          "CCMP TKIP WEP104 WEP40");
 
889
                        if (ret < 0 || (size_t) ret >= buflen)
 
890
                                return -1;
 
891
                        return ret;
 
892
                }
 
893
 
 
894
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
895
                        ret = os_snprintf(pos, end - pos, "%sCCMP",
 
896
                                          first ? "" : " ");
 
897
                        if (ret < 0 || ret >= end - pos)
 
898
                                return pos - buf;
 
899
                        pos += ret;
 
900
                        first = 0;
 
901
                }
 
902
 
 
903
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
904
                        ret = os_snprintf(pos, end - pos, "%sTKIP",
 
905
                                          first ? "" : " ");
 
906
                        if (ret < 0 || ret >= end - pos)
 
907
                                return pos - buf;
 
908
                        pos += ret;
 
909
                        first = 0;
 
910
                }
 
911
 
 
912
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
 
913
                        ret = os_snprintf(pos, end - pos, "%sWEP104",
 
914
                                          first ? "" : " ");
 
915
                        if (ret < 0 || ret >= end - pos)
 
916
                                return pos - buf;
 
917
                        pos += ret;
 
918
                        first = 0;
 
919
                }
 
920
 
 
921
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
 
922
                        ret = os_snprintf(pos, end - pos, "%sWEP40",
 
923
                                          first ? "" : " ");
 
924
                        if (ret < 0 || ret >= end - pos)
 
925
                                return pos - buf;
 
926
                        pos += ret;
 
927
                        first = 0;
 
928
                }
 
929
 
 
930
                return pos - buf;
 
931
        }
 
932
 
 
933
        if (os_strcmp(field, "key_mgmt") == 0) {
 
934
                if (res < 0) {
 
935
                        if (strict)
 
936
                                return 0;
 
937
                        ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP "
 
938
                                          "IEEE8021X WPA-NONE NONE");
 
939
                        if (ret < 0 || (size_t) ret >= buflen)
 
940
                                return -1;
 
941
                        return ret;
 
942
                }
 
943
 
 
944
                ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
 
945
                if (ret < 0 || ret >= end - pos)
 
946
                        return pos - buf;
 
947
                pos += ret;
 
948
 
 
949
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
950
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
 
951
                        ret = os_snprintf(pos, end - pos, " WPA-EAP");
 
952
                        if (ret < 0 || ret >= end - pos)
 
953
                                return pos - buf;
 
954
                        pos += ret;
 
955
                }
 
956
 
 
957
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
 
958
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
959
                        ret = os_snprintf(pos, end - pos, " WPA-PSK");
 
960
                        if (ret < 0 || ret >= end - pos)
 
961
                                return pos - buf;
 
962
                        pos += ret;
 
963
                }
 
964
 
 
965
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
966
                        ret = os_snprintf(pos, end - pos, " WPA-NONE");
 
967
                        if (ret < 0 || ret >= end - pos)
 
968
                                return pos - buf;
 
969
                        pos += ret;
 
970
                }
 
971
 
 
972
                return pos - buf;
 
973
        }
 
974
 
 
975
        if (os_strcmp(field, "proto") == 0) {
 
976
                if (res < 0) {
 
977
                        if (strict)
 
978
                                return 0;
 
979
                        ret = os_snprintf(buf, buflen, "RSN WPA");
 
980
                        if (ret < 0 || (size_t) ret >= buflen)
 
981
                                return -1;
 
982
                        return ret;
 
983
                }
 
984
 
 
985
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
 
986
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
987
                        ret = os_snprintf(pos, end - pos, "%sRSN",
 
988
                                          first ? "" : " ");
 
989
                        if (ret < 0 || ret >= end - pos)
 
990
                                return pos - buf;
 
991
                        pos += ret;
 
992
                        first = 0;
 
993
                }
 
994
 
 
995
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
996
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
 
997
                        ret = os_snprintf(pos, end - pos, "%sWPA",
 
998
                                          first ? "" : " ");
 
999
                        if (ret < 0 || ret >= end - pos)
 
1000
                                return pos - buf;
 
1001
                        pos += ret;
 
1002
                        first = 0;
 
1003
                }
 
1004
 
 
1005
                return pos - buf;
 
1006
        }
 
1007
 
 
1008
        if (os_strcmp(field, "auth_alg") == 0) {
 
1009
                if (res < 0) {
 
1010
                        if (strict)
 
1011
                                return 0;
 
1012
                        ret = os_snprintf(buf, buflen, "OPEN SHARED LEAP");
 
1013
                        if (ret < 0 || (size_t) ret >= buflen)
 
1014
                                return -1;
 
1015
                        return ret;
 
1016
                }
 
1017
 
 
1018
                if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
 
1019
                        ret = os_snprintf(pos, end - pos, "%sOPEN",
 
1020
                                          first ? "" : " ");
 
1021
                        if (ret < 0 || ret >= end - pos)
 
1022
                                return pos - buf;
 
1023
                        pos += ret;
 
1024
                        first = 0;
 
1025
                }
 
1026
 
 
1027
                if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
 
1028
                        ret = os_snprintf(pos, end - pos, "%sSHARED",
 
1029
                                          first ? "" : " ");
 
1030
                        if (ret < 0 || ret >= end - pos)
 
1031
                                return pos - buf;
 
1032
                        pos += ret;
 
1033
                        first = 0;
 
1034
                }
 
1035
 
 
1036
                if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
 
1037
                        ret = os_snprintf(pos, end - pos, "%sLEAP",
 
1038
                                          first ? "" : " ");
 
1039
                        if (ret < 0 || ret >= end - pos)
 
1040
                                return pos - buf;
 
1041
                        pos += ret;
 
1042
                        first = 0;
 
1043
                }
 
1044
 
 
1045
                return pos - buf;
 
1046
        }
 
1047
 
 
1048
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
 
1049
                   field);
 
1050
 
 
1051
        return -1;
 
1052
}
 
1053
 
 
1054
 
 
1055
static int wpa_supplicant_ctrl_iface_ap_scan(
 
1056
        struct wpa_supplicant *wpa_s, char *cmd)
 
1057
{
 
1058
        int ap_scan = atoi(cmd);
 
1059
 
 
1060
        if (ap_scan < 0 || ap_scan > 2)
 
1061
                return -1;
 
1062
        wpa_s->conf->ap_scan = ap_scan;
 
1063
        return 0;
 
1064
}
 
1065
 
 
1066
 
 
1067
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 
1068
                                         char *buf, size_t *resp_len)
 
1069
{
 
1070
        char *reply;
 
1071
        const int reply_size = 2048;
 
1072
        int ctrl_rsp = 0;
 
1073
        int reply_len;
 
1074
 
 
1075
        if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
 
1076
            os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
 
1077
                wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
 
1078
                                      (const u8 *) buf, os_strlen(buf));
 
1079
        } else {
 
1080
                wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
 
1081
                                  (const u8 *) buf, os_strlen(buf));
 
1082
        }
 
1083
 
 
1084
        reply = os_malloc(reply_size);
 
1085
        if (reply == NULL) {
 
1086
                *resp_len = 1;
 
1087
                return NULL;
 
1088
        }
 
1089
 
 
1090
        os_memcpy(reply, "OK\n", 3);
 
1091
        reply_len = 3;
 
1092
 
 
1093
        if (os_strcmp(buf, "PING") == 0) {
 
1094
                os_memcpy(reply, "PONG\n", 5);
 
1095
                reply_len = 5;
 
1096
        } else if (os_strcmp(buf, "MIB") == 0) {
 
1097
                reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
 
1098
                if (reply_len >= 0) {
 
1099
                        int res;
 
1100
                        res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
 
1101
                                               reply_size - reply_len);
 
1102
                        if (res < 0)
 
1103
                                reply_len = -1;
 
1104
                        else
 
1105
                                reply_len += res;
 
1106
                }
 
1107
        } else if (os_strncmp(buf, "STATUS", 6) == 0) {
 
1108
                reply_len = wpa_supplicant_ctrl_iface_status(
 
1109
                        wpa_s, buf + 6, reply, reply_size);
 
1110
        } else if (os_strcmp(buf, "PMKSA") == 0) {
 
1111
                reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
 
1112
        } else if (os_strncmp(buf, "SET ", 4) == 0) {
 
1113
                if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
 
1114
                        reply_len = -1;
 
1115
        } else if (os_strcmp(buf, "LOGON") == 0) {
 
1116
                eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
 
1117
        } else if (os_strcmp(buf, "LOGOFF") == 0) {
 
1118
                eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
 
1119
        } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
 
1120
                wpa_s->disconnected = 0;
 
1121
                wpa_s->reassociate = 1;
 
1122
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1123
        } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
 
1124
                if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
 
1125
                        reply_len = -1;
 
1126
#ifdef CONFIG_PEERKEY
 
1127
        } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
 
1128
                if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
 
1129
                        reply_len = -1;
 
1130
#endif /* CONFIG_PEERKEY */
 
1131
        } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
 
1132
        {
 
1133
                if (wpa_supplicant_ctrl_iface_ctrl_rsp(
 
1134
                            wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
 
1135
                        reply_len = -1;
 
1136
                else
 
1137
                        ctrl_rsp = 1;
 
1138
        } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
 
1139
                if (wpa_supplicant_reload_configuration(wpa_s))
 
1140
                        reply_len = -1;
 
1141
        } else if (os_strcmp(buf, "TERMINATE") == 0) {
 
1142
                eloop_terminate();
 
1143
        } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
 
1144
                if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
 
1145
                        reply_len = -1;
 
1146
        } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
 
1147
                reply_len = wpa_supplicant_ctrl_iface_list_networks(
 
1148
                        wpa_s, reply, reply_size);
 
1149
        } else if (os_strcmp(buf, "DISCONNECT") == 0) {
 
1150
                wpa_s->disconnected = 1;
 
1151
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
1152
        } else if (os_strcmp(buf, "SCAN") == 0) {
 
1153
                wpa_s->scan_req = 2;
 
1154
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1155
        } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
 
1156
                reply_len = wpa_supplicant_ctrl_iface_scan_results(
 
1157
                        wpa_s, reply, reply_size);
 
1158
        } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
 
1159
                if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
 
1160
                        reply_len = -1;
 
1161
        } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
 
1162
                if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
 
1163
                        reply_len = -1;
 
1164
        } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
 
1165
                if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
 
1166
                        reply_len = -1;
 
1167
        } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
 
1168
                reply_len = wpa_supplicant_ctrl_iface_add_network(
 
1169
                        wpa_s, reply, reply_size);
 
1170
        } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
 
1171
                if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
 
1172
                        reply_len = -1;
 
1173
        } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
 
1174
                if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
 
1175
                        reply_len = -1;
 
1176
        } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
 
1177
                reply_len = wpa_supplicant_ctrl_iface_get_network(
 
1178
                        wpa_s, buf + 12, reply, reply_size);
 
1179
        } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
 
1180
                if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
 
1181
                        reply_len = -1;
 
1182
        } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
 
1183
                reply_len = wpa_supplicant_ctrl_iface_get_capability(
 
1184
                        wpa_s, buf + 15, reply, reply_size);
 
1185
        } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
 
1186
                if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
 
1187
                        reply_len = -1;
 
1188
        } else if (os_strcmp(buf, "INTERFACES") == 0) {
 
1189
                reply_len = wpa_supplicant_global_iface_interfaces(
 
1190
                        wpa_s->global, reply, reply_size);
 
1191
        } else {
 
1192
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 
1193
                reply_len = 16;
 
1194
        }
 
1195
 
 
1196
        if (reply_len < 0) {
 
1197
                os_memcpy(reply, "FAIL\n", 5);
 
1198
                reply_len = 5;
 
1199
        }
 
1200
 
 
1201
        if (ctrl_rsp)
 
1202
                eapol_sm_notify_ctrl_response(wpa_s->eapol);
 
1203
 
 
1204
        *resp_len = reply_len;
 
1205
        return reply;
 
1206
}
 
1207
 
 
1208
 
 
1209
static int wpa_supplicant_global_iface_add(struct wpa_global *global,
 
1210
                                           char *cmd)
 
1211
{
 
1212
        struct wpa_interface iface;
 
1213
        char *pos;
 
1214
 
 
1215
        /*
 
1216
         * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
 
1217
         * TAB<bridge_ifname>
 
1218
         */
 
1219
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
1220
 
 
1221
        os_memset(&iface, 0, sizeof(iface));
 
1222
 
 
1223
        do {
 
1224
                iface.ifname = pos = cmd;
 
1225
                pos = os_strchr(pos, '\t');
 
1226
                if (pos)
 
1227
                        *pos++ = '\0';
 
1228
                if (iface.ifname[0] == '\0')
 
1229
                        return -1;
 
1230
                if (pos == NULL)
 
1231
                        break;
 
1232
 
 
1233
                iface.confname = pos;
 
1234
                pos = os_strchr(pos, '\t');
 
1235
                if (pos)
 
1236
                        *pos++ = '\0';
 
1237
                if (iface.confname[0] == '\0')
 
1238
                        iface.confname = NULL;
 
1239
                if (pos == NULL)
 
1240
                        break;
 
1241
 
 
1242
                iface.driver = pos;
 
1243
                pos = os_strchr(pos, '\t');
 
1244
                if (pos)
 
1245
                        *pos++ = '\0';
 
1246
                if (iface.driver[0] == '\0')
 
1247
                        iface.driver = NULL;
 
1248
                if (pos == NULL)
 
1249
                        break;
 
1250
 
 
1251
                iface.ctrl_interface = pos;
 
1252
                pos = os_strchr(pos, '\t');
 
1253
                if (pos)
 
1254
                        *pos++ = '\0';
 
1255
                if (iface.ctrl_interface[0] == '\0')
 
1256
                        iface.ctrl_interface = NULL;
 
1257
                if (pos == NULL)
 
1258
                        break;
 
1259
 
 
1260
                iface.driver_param = pos;
 
1261
                pos = os_strchr(pos, '\t');
 
1262
                if (pos)
 
1263
                        *pos++ = '\0';
 
1264
                if (iface.driver_param[0] == '\0')
 
1265
                        iface.driver_param = NULL;
 
1266
                if (pos == NULL)
 
1267
                        break;
 
1268
 
 
1269
                iface.bridge_ifname = pos;
 
1270
                pos = os_strchr(pos, '\t');
 
1271
                if (pos)
 
1272
                        *pos++ = '\0';
 
1273
                if (iface.bridge_ifname[0] == '\0')
 
1274
                        iface.bridge_ifname = NULL;
 
1275
                if (pos == NULL)
 
1276
                        break;
 
1277
        } while (0);
 
1278
 
 
1279
        if (wpa_supplicant_get_iface(global, iface.ifname))
 
1280
                return -1;
 
1281
 
 
1282
        return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
 
1283
}
 
1284
 
 
1285
 
 
1286
static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
 
1287
                                              char *cmd)
 
1288
{
 
1289
        struct wpa_supplicant *wpa_s;
 
1290
 
 
1291
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
 
1292
 
 
1293
        wpa_s = wpa_supplicant_get_iface(global, cmd);
 
1294
        if (wpa_s == NULL)
 
1295
                return -1;
 
1296
        return wpa_supplicant_remove_iface(global, wpa_s);
 
1297
}
 
1298
 
 
1299
 
 
1300
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 
1301
                                                  char *buf, int len)
 
1302
{
 
1303
        int res;
 
1304
        char *pos, *end;
 
1305
        struct wpa_supplicant *wpa_s;
 
1306
 
 
1307
        wpa_s = global->ifaces;
 
1308
        pos = buf;
 
1309
        end = buf + len;
 
1310
 
 
1311
        while (wpa_s) {
 
1312
                res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
 
1313
                if (res < 0 || res >= end - pos) {
 
1314
                        *pos = '\0';
 
1315
                        break;
 
1316
                }
 
1317
                pos += res;
 
1318
                wpa_s = wpa_s->next;
 
1319
        }
 
1320
        return pos - buf;
 
1321
}
 
1322
 
 
1323
 
 
1324
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
 
1325
                                                char *buf, size_t *resp_len)
 
1326
{
 
1327
        char *reply;
 
1328
        const int reply_size = 2048;
 
1329
        int reply_len;
 
1330
 
 
1331
        wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
 
1332
                          (const u8 *) buf, os_strlen(buf));
 
1333
 
 
1334
        reply = os_malloc(reply_size);
 
1335
        if (reply == NULL) {
 
1336
                *resp_len = 1;
 
1337
                return NULL;
 
1338
        }
 
1339
 
 
1340
        os_memcpy(reply, "OK\n", 3);
 
1341
        reply_len = 3;
 
1342
 
 
1343
        if (os_strcmp(buf, "PING") == 0) {
 
1344
                os_memcpy(reply, "PONG\n", 5);
 
1345
                reply_len = 5;
 
1346
        } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
 
1347
                if (wpa_supplicant_global_iface_add(global, buf + 14))
 
1348
                        reply_len = -1;
 
1349
        } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
 
1350
                if (wpa_supplicant_global_iface_remove(global, buf + 17))
 
1351
                        reply_len = -1;
 
1352
        } else if (os_strcmp(buf, "INTERFACES") == 0) {
 
1353
                reply_len = wpa_supplicant_global_iface_interfaces(
 
1354
                        global, reply, reply_size);
 
1355
        } else if (os_strcmp(buf, "TERMINATE") == 0) {
 
1356
                eloop_terminate();
 
1357
        } else {
 
1358
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 
1359
                reply_len = 16;
 
1360
        }
 
1361
 
 
1362
        if (reply_len < 0) {
 
1363
                os_memcpy(reply, "FAIL\n", 5);
 
1364
                reply_len = 5;
 
1365
        }
 
1366
 
 
1367
        *resp_len = reply_len;
 
1368
        return reply;
 
1369
}