blob: a163c281fd9250ae56793049198bee5b0349989f [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
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/version.h"
20#include "common/ieee802_11_defs.h"
21#include "common/wpa_ctrl.h"
22#include "eap_peer/eap.h"
23#include "eapol_supp/eapol_supp_sm.h"
24#include "rsn_supp/wpa.h"
25#include "rsn_supp/preauth.h"
26#include "rsn_supp/pmksa_cache.h"
27#include "l2_packet/l2_packet.h"
28#include "wps/wps.h"
29#include "config.h"
30#include "wpa_supplicant_i.h"
31#include "driver_i.h"
32#include "wps_supplicant.h"
33#include "ibss_rsn.h"
34#include "ap.h"
35#include "p2p_supplicant.h"
36#include "p2p/p2p.h"
37#include "notify.h"
38#include "bss.h"
39#include "scan.h"
40#include "ctrl_iface.h"
Dmitry Shmidte19501d2011-03-16 14:32:18 -070041#include "blacklist.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042
43extern struct wpa_driver_ops *wpa_drivers[];
44
45static int wpa_supplicant_global_iface_list(struct wpa_global *global,
46 char *buf, int len);
47static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
48 char *buf, int len);
49
50
51static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
52 char *cmd)
53{
54 char *value;
55 int ret = 0;
56
57 value = os_strchr(cmd, ' ');
58 if (value == NULL)
59 return -1;
60 *value++ = '\0';
61
62 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
63 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
64 eapol_sm_configure(wpa_s->eapol,
65 atoi(value), -1, -1, -1);
66 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
67 eapol_sm_configure(wpa_s->eapol,
68 -1, atoi(value), -1, -1);
69 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
70 eapol_sm_configure(wpa_s->eapol,
71 -1, -1, atoi(value), -1);
72 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
73 eapol_sm_configure(wpa_s->eapol,
74 -1, -1, -1, atoi(value));
75 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
76 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
77 atoi(value)))
78 ret = -1;
79 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
80 0) {
81 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
82 atoi(value)))
83 ret = -1;
84 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
85 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
86 ret = -1;
87 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
88 wpa_s->wps_fragment_size = atoi(value);
89#ifdef CONFIG_WPS_TESTING
90 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
91 long int val;
92 val = strtol(value, NULL, 0);
93 if (val < 0 || val > 0xff) {
94 ret = -1;
95 wpa_printf(MSG_DEBUG, "WPS: Invalid "
96 "wps_version_number %ld", val);
97 } else {
98 wps_version_number = val;
99 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
100 "version %u.%u",
101 (wps_version_number & 0xf0) >> 4,
102 wps_version_number & 0x0f);
103 }
104 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
105 wps_testing_dummy_cred = atoi(value);
106 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
107 wps_testing_dummy_cred);
108#endif /* CONFIG_WPS_TESTING */
109 } else if (os_strcasecmp(cmd, "ampdu") == 0) {
110 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
111 ret = -1;
112#ifdef CONFIG_TDLS_TESTING
113 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
114 extern unsigned int tdls_testing;
115 tdls_testing = strtol(value, NULL, 0);
116 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
117#endif /* CONFIG_TDLS_TESTING */
118#ifdef CONFIG_TDLS
119 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
120 int disabled = atoi(value);
121 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
122 if (disabled) {
123 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
124 ret = -1;
125 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
126 ret = -1;
127 wpa_tdls_enable(wpa_s->wpa, !disabled);
128#endif /* CONFIG_TDLS */
129 } else {
130 value[-1] = '=';
131 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
132 if (ret == 0)
133 wpa_supplicant_update_config(wpa_s);
134 }
135
136 return ret;
137}
138
139
140static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
141 char *cmd, char *buf, size_t buflen)
142{
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700143 int res = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700144
145 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
146
147 if (os_strcmp(cmd, "version") == 0) {
148 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700149 } else if (os_strcasecmp(cmd, "country") == 0) {
150 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
151 res = os_snprintf(buf, buflen, "%c%c",
152 wpa_s->conf->country[0],
153 wpa_s->conf->country[1]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700154 }
155
Dmitry Shmidt6f3bdcf2011-04-19 16:42:47 -0700156 if (res < 0 || (unsigned int) res >= buflen)
157 return -1;
158 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700159}
160
161
162#ifdef IEEE8021X_EAPOL
163static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
164 char *addr)
165{
166 u8 bssid[ETH_ALEN];
167 struct wpa_ssid *ssid = wpa_s->current_ssid;
168
169 if (hwaddr_aton(addr, bssid)) {
170 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
171 "'%s'", addr);
172 return -1;
173 }
174
175 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
176 rsn_preauth_deinit(wpa_s->wpa);
177 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
178 return -1;
179
180 return 0;
181}
182#endif /* IEEE8021X_EAPOL */
183
184
185#ifdef CONFIG_PEERKEY
186/* MLME-STKSTART.request(peer) */
187static int wpa_supplicant_ctrl_iface_stkstart(
188 struct wpa_supplicant *wpa_s, char *addr)
189{
190 u8 peer[ETH_ALEN];
191
192 if (hwaddr_aton(addr, peer)) {
193 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
194 "address '%s'", addr);
195 return -1;
196 }
197
198 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
199 MAC2STR(peer));
200
201 return wpa_sm_stkstart(wpa_s->wpa, peer);
202}
203#endif /* CONFIG_PEERKEY */
204
205
206#ifdef CONFIG_TDLS
207
208static int wpa_supplicant_ctrl_iface_tdls_discover(
209 struct wpa_supplicant *wpa_s, char *addr)
210{
211 u8 peer[ETH_ALEN];
212
213 if (hwaddr_aton(addr, peer)) {
214 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
215 "address '%s'", addr);
216 return -1;
217 }
218
219 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
220 MAC2STR(peer));
221
222 return wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
223}
224
225
226static int wpa_supplicant_ctrl_iface_tdls_setup(
227 struct wpa_supplicant *wpa_s, char *addr)
228{
229 u8 peer[ETH_ALEN];
230 int ret;
231
232 if (hwaddr_aton(addr, peer)) {
233 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
234 "address '%s'", addr);
235 return -1;
236 }
237
238 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
239 MAC2STR(peer));
240
241 ret = wpa_tdls_reneg(wpa_s->wpa, peer);
242 if (ret)
243 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
244 return ret;
245}
246
247
248static int wpa_supplicant_ctrl_iface_tdls_teardown(
249 struct wpa_supplicant *wpa_s, char *addr)
250{
251 u8 peer[ETH_ALEN];
252
253 if (hwaddr_aton(addr, peer)) {
254 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
255 "address '%s'", addr);
256 return -1;
257 }
258
259 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
260 MAC2STR(peer));
261
262 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
263}
264
265#endif /* CONFIG_TDLS */
266
267
268#ifdef CONFIG_IEEE80211R
269static int wpa_supplicant_ctrl_iface_ft_ds(
270 struct wpa_supplicant *wpa_s, char *addr)
271{
272 u8 target_ap[ETH_ALEN];
273 struct wpa_bss *bss;
274 const u8 *mdie;
275
276 if (hwaddr_aton(addr, target_ap)) {
277 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
278 "address '%s'", addr);
279 return -1;
280 }
281
282 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
283
284 bss = wpa_bss_get_bssid(wpa_s, target_ap);
285 if (bss)
286 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
287 else
288 mdie = NULL;
289
290 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
291}
292#endif /* CONFIG_IEEE80211R */
293
294
295#ifdef CONFIG_WPS
296static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
297 char *cmd)
298{
299 u8 bssid[ETH_ALEN], *_bssid = bssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -0700300#ifdef CONFIG_P2P
301 u8 p2p_dev_addr[ETH_ALEN];
302#endif /* CONFIG_P2P */
303#ifdef CONFIG_AP
304 u8 *_p2p_dev_addr = NULL;
305#endif /* CONFIG_AP */
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700306#ifdef ANDROID_BRCM_P2P_PATCH
307 struct wpa_supplicant *iface;
308#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700309 if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
310 _bssid = NULL;
311#ifdef CONFIG_P2P
312 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
313 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
314 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
315 "P2P Device Address '%s'",
316 cmd + 13);
317 return -1;
318 }
319 _p2p_dev_addr = p2p_dev_addr;
320#endif /* CONFIG_P2P */
321 } else if (hwaddr_aton(cmd, bssid)) {
322 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
323 cmd);
324 return -1;
325 }
326
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700327#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
328 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
329 if (iface->ap_iface){
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -0700330 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: iface 0x%08x wpa_s->ap_iface %p", (u32)iface, iface->ap_iface);
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700331 wpa_supplicant_ap_wps_pbc(iface, _bssid, _p2p_dev_addr);
332 return 0;
333 }
334 else
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -0700335 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: ap_iface is not set iface 0x%08x", (u32)iface);
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700336 }
337#elif defined CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700338 if (wpa_s->ap_iface)
339 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
340#endif /* CONFIG_AP */
341
342 return wpas_wps_start_pbc(wpa_s, _bssid, 0);
343}
344
345
346static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
347 char *cmd, char *buf,
348 size_t buflen)
349{
350 u8 bssid[ETH_ALEN], *_bssid = bssid;
351 char *pin;
352 int ret;
353
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700354#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700355 struct wpa_supplicant *iface;
356#endif
357
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700358 pin = os_strchr(cmd, ' ');
359 if (pin)
360 *pin++ = '\0';
361
362 if (os_strcmp(cmd, "any") == 0)
363 _bssid = NULL;
364 else if (hwaddr_aton(cmd, bssid)) {
365 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
366 cmd);
367 return -1;
368 }
369
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700370#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700371 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
372 if (iface->ap_iface){
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -0700373 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: iface 0x%08x wpa_s->ap_iface %p", (u32)iface, iface->ap_iface);
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700374 /* Call the wps registrar for the main interface */
375 wpa_supplicant_ap_wps_pin(iface, _bssid, pin,
376 buf, buflen);
377 return 0;
378 }
379 else
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -0700380 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: ap_iface is not set iface 0x%08x", (u32)iface);
Dmitry Shmidt497c1d52011-07-21 15:19:46 -0700381 }
382#elif defined CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 if (wpa_s->ap_iface)
384 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
385 buf, buflen);
386#endif /* CONFIG_AP */
387
388 if (pin) {
389 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
390 DEV_PW_DEFAULT);
391 if (ret < 0)
392 return -1;
393 ret = os_snprintf(buf, buflen, "%s", pin);
394 if (ret < 0 || (size_t) ret >= buflen)
395 return -1;
396 return ret;
397 }
398
399 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
400 if (ret < 0)
401 return -1;
402
403 /* Return the generated PIN */
404 ret = os_snprintf(buf, buflen, "%08d", ret);
405 if (ret < 0 || (size_t) ret >= buflen)
406 return -1;
407 return ret;
408}
409
410
411static int wpa_supplicant_ctrl_iface_wps_check_pin(
412 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
413{
414 char pin[9];
415 size_t len;
416 char *pos;
417 int ret;
418
419 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
420 (u8 *) cmd, os_strlen(cmd));
421 for (pos = cmd, len = 0; *pos != '\0'; pos++) {
422 if (*pos < '0' || *pos > '9')
423 continue;
424 pin[len++] = *pos;
425 if (len == 9) {
426 wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
427 return -1;
428 }
429 }
430 if (len != 4 && len != 8) {
431 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
432 return -1;
433 }
434 pin[len] = '\0';
435
436 if (len == 8) {
437 unsigned int pin_val;
438 pin_val = atoi(pin);
439 if (!wps_pin_valid(pin_val)) {
440 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
441 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
442 if (ret < 0 || (size_t) ret >= buflen)
443 return -1;
444 return ret;
445 }
446 }
447
448 ret = os_snprintf(buf, buflen, "%s", pin);
449 if (ret < 0 || (size_t) ret >= buflen)
450 return -1;
451
452 return ret;
453}
454
455
456#ifdef CONFIG_WPS_OOB
457static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
458 char *cmd)
459{
460 char *path, *method, *name;
461
462 path = os_strchr(cmd, ' ');
463 if (path == NULL)
464 return -1;
465 *path++ = '\0';
466
467 method = os_strchr(path, ' ');
468 if (method == NULL)
469 return -1;
470 *method++ = '\0';
471
472 name = os_strchr(method, ' ');
473 if (name != NULL)
474 *name++ = '\0';
475
476 return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
477}
478#endif /* CONFIG_WPS_OOB */
479
480
481static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
482 char *cmd)
483{
484 u8 bssid[ETH_ALEN];
485 char *pin;
486 char *new_ssid;
487 char *new_auth;
488 char *new_encr;
489 char *new_key;
490 struct wps_new_ap_settings ap;
491
492 pin = os_strchr(cmd, ' ');
493 if (pin == NULL)
494 return -1;
495 *pin++ = '\0';
496
497 if (hwaddr_aton(cmd, bssid)) {
498 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
499 cmd);
500 return -1;
501 }
502
503 new_ssid = os_strchr(pin, ' ');
504 if (new_ssid == NULL)
505 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
506 *new_ssid++ = '\0';
507
508 new_auth = os_strchr(new_ssid, ' ');
509 if (new_auth == NULL)
510 return -1;
511 *new_auth++ = '\0';
512
513 new_encr = os_strchr(new_auth, ' ');
514 if (new_encr == NULL)
515 return -1;
516 *new_encr++ = '\0';
517
518 new_key = os_strchr(new_encr, ' ');
519 if (new_key == NULL)
520 return -1;
521 *new_key++ = '\0';
522
523 os_memset(&ap, 0, sizeof(ap));
524 ap.ssid_hex = new_ssid;
525 ap.auth = new_auth;
526 ap.encr = new_encr;
527 ap.key_hex = new_key;
528 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
529}
530
531
532#ifdef CONFIG_AP
533static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
534 char *cmd, char *buf,
535 size_t buflen)
536{
537 int timeout = 300;
538 char *pos;
539 const char *pin_txt;
540
541 if (!wpa_s->ap_iface)
542 return -1;
543
544 pos = os_strchr(cmd, ' ');
545 if (pos)
546 *pos++ = '\0';
547
548 if (os_strcmp(cmd, "disable") == 0) {
549 wpas_wps_ap_pin_disable(wpa_s);
550 return os_snprintf(buf, buflen, "OK\n");
551 }
552
553 if (os_strcmp(cmd, "random") == 0) {
554 if (pos)
555 timeout = atoi(pos);
556 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
557 if (pin_txt == NULL)
558 return -1;
559 return os_snprintf(buf, buflen, "%s", pin_txt);
560 }
561
562 if (os_strcmp(cmd, "get") == 0) {
563 pin_txt = wpas_wps_ap_pin_get(wpa_s);
564 if (pin_txt == NULL)
565 return -1;
566 return os_snprintf(buf, buflen, "%s", pin_txt);
567 }
568
569 if (os_strcmp(cmd, "set") == 0) {
570 char *pin;
571 if (pos == NULL)
572 return -1;
573 pin = pos;
574 pos = os_strchr(pos, ' ');
575 if (pos) {
576 *pos++ = '\0';
577 timeout = atoi(pos);
578 }
579 if (os_strlen(pin) > buflen)
580 return -1;
581 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
582 return -1;
583 return os_snprintf(buf, buflen, "%s", pin);
584 }
585
586 return -1;
587}
588#endif /* CONFIG_AP */
589
590
591#ifdef CONFIG_WPS_ER
592static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
593 char *cmd)
594{
595 char *uuid = cmd, *pin, *pos;
596 u8 addr_buf[ETH_ALEN], *addr = NULL;
597 pin = os_strchr(uuid, ' ');
598 if (pin == NULL)
599 return -1;
600 *pin++ = '\0';
601 pos = os_strchr(pin, ' ');
602 if (pos) {
603 *pos++ = '\0';
604 if (hwaddr_aton(pos, addr_buf) == 0)
605 addr = addr_buf;
606 }
607 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
608}
609
610
611static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
612 char *cmd)
613{
614 char *uuid = cmd, *pin;
615 pin = os_strchr(uuid, ' ');
616 if (pin == NULL)
617 return -1;
618 *pin++ = '\0';
619 return wpas_wps_er_learn(wpa_s, uuid, pin);
620}
621
622
623static int wpa_supplicant_ctrl_iface_wps_er_set_config(
624 struct wpa_supplicant *wpa_s, char *cmd)
625{
626 char *uuid = cmd, *id;
627 id = os_strchr(uuid, ' ');
628 if (id == NULL)
629 return -1;
630 *id++ = '\0';
631 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
632}
633
634
635static int wpa_supplicant_ctrl_iface_wps_er_config(
636 struct wpa_supplicant *wpa_s, char *cmd)
637{
638 char *pin;
639 char *new_ssid;
640 char *new_auth;
641 char *new_encr;
642 char *new_key;
643 struct wps_new_ap_settings ap;
644
645 pin = os_strchr(cmd, ' ');
646 if (pin == NULL)
647 return -1;
648 *pin++ = '\0';
649
650 new_ssid = os_strchr(pin, ' ');
651 if (new_ssid == NULL)
652 return -1;
653 *new_ssid++ = '\0';
654
655 new_auth = os_strchr(new_ssid, ' ');
656 if (new_auth == NULL)
657 return -1;
658 *new_auth++ = '\0';
659
660 new_encr = os_strchr(new_auth, ' ');
661 if (new_encr == NULL)
662 return -1;
663 *new_encr++ = '\0';
664
665 new_key = os_strchr(new_encr, ' ');
666 if (new_key == NULL)
667 return -1;
668 *new_key++ = '\0';
669
670 os_memset(&ap, 0, sizeof(ap));
671 ap.ssid_hex = new_ssid;
672 ap.auth = new_auth;
673 ap.encr = new_encr;
674 ap.key_hex = new_key;
675 return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
676}
677#endif /* CONFIG_WPS_ER */
678
679#endif /* CONFIG_WPS */
680
681
682#ifdef CONFIG_IBSS_RSN
683static int wpa_supplicant_ctrl_iface_ibss_rsn(
684 struct wpa_supplicant *wpa_s, char *addr)
685{
686 u8 peer[ETH_ALEN];
687
688 if (hwaddr_aton(addr, peer)) {
689 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
690 "address '%s'", addr);
691 return -1;
692 }
693
694 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
695 MAC2STR(peer));
696
697 return ibss_rsn_start(wpa_s->ibss_rsn, peer);
698}
699#endif /* CONFIG_IBSS_RSN */
700
701
702static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
703 char *rsp)
704{
705#ifdef IEEE8021X_EAPOL
706 char *pos, *id_pos;
707 int id;
708 struct wpa_ssid *ssid;
709 struct eap_peer_config *eap;
710
711 pos = os_strchr(rsp, '-');
712 if (pos == NULL)
713 return -1;
714 *pos++ = '\0';
715 id_pos = pos;
716 pos = os_strchr(pos, ':');
717 if (pos == NULL)
718 return -1;
719 *pos++ = '\0';
720 id = atoi(id_pos);
721 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
722 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
723 (u8 *) pos, os_strlen(pos));
724
725 ssid = wpa_config_get_network(wpa_s->conf, id);
726 if (ssid == NULL) {
727 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
728 "to update", id);
729 return -1;
730 }
731 eap = &ssid->eap;
732
733 if (os_strcmp(rsp, "IDENTITY") == 0) {
734 os_free(eap->identity);
735 eap->identity = (u8 *) os_strdup(pos);
736 eap->identity_len = os_strlen(pos);
737 eap->pending_req_identity = 0;
738 if (ssid == wpa_s->current_ssid)
739 wpa_s->reassociate = 1;
740 } else if (os_strcmp(rsp, "PASSWORD") == 0) {
741 os_free(eap->password);
742 eap->password = (u8 *) os_strdup(pos);
743 eap->password_len = os_strlen(pos);
744 eap->pending_req_password = 0;
745 if (ssid == wpa_s->current_ssid)
746 wpa_s->reassociate = 1;
747 } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
748 os_free(eap->new_password);
749 eap->new_password = (u8 *) os_strdup(pos);
750 eap->new_password_len = os_strlen(pos);
751 eap->pending_req_new_password = 0;
752 if (ssid == wpa_s->current_ssid)
753 wpa_s->reassociate = 1;
754 } else if (os_strcmp(rsp, "PIN") == 0) {
755 os_free(eap->pin);
756 eap->pin = os_strdup(pos);
757 eap->pending_req_pin = 0;
758 if (ssid == wpa_s->current_ssid)
759 wpa_s->reassociate = 1;
760 } else if (os_strcmp(rsp, "OTP") == 0) {
761 os_free(eap->otp);
762 eap->otp = (u8 *) os_strdup(pos);
763 eap->otp_len = os_strlen(pos);
764 os_free(eap->pending_req_otp);
765 eap->pending_req_otp = NULL;
766 eap->pending_req_otp_len = 0;
767 } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
768 os_free(eap->private_key_passwd);
769 eap->private_key_passwd = (u8 *) os_strdup(pos);
770 eap->pending_req_passphrase = 0;
771 if (ssid == wpa_s->current_ssid)
772 wpa_s->reassociate = 1;
773 } else {
774 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
775 return -1;
776 }
777
778 return 0;
779#else /* IEEE8021X_EAPOL */
780 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
781 return -1;
782#endif /* IEEE8021X_EAPOL */
783}
784
785
786static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
787 const char *params,
788 char *buf, size_t buflen)
789{
790 char *pos, *end, tmp[30];
791 int res, verbose, ret;
792
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700793#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
794 /* We have to send status command to p2p interface if p2p_interface is started
795 * otherwise we can send it to primary interface
796 */
797 struct wpa_supplicant* ifs;
798 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
799 if ( (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO ) ||(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT )) {
800 wpa_s = ifs;
801 break;
802 }
803 }
804#endif /* defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_P2P */
805
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700806 verbose = os_strcmp(params, "-VERBOSE") == 0;
807 pos = buf;
808 end = buf + buflen;
809 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
810 struct wpa_ssid *ssid = wpa_s->current_ssid;
811 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
812 MAC2STR(wpa_s->bssid));
813 if (ret < 0 || ret >= end - pos)
814 return pos - buf;
815 pos += ret;
816 if (ssid) {
817 u8 *_ssid = ssid->ssid;
818 size_t ssid_len = ssid->ssid_len;
819 u8 ssid_buf[MAX_SSID_LEN];
820 if (ssid_len == 0) {
821 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
822 if (_res < 0)
823 ssid_len = 0;
824 else
825 ssid_len = _res;
826 _ssid = ssid_buf;
827 }
828 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
829 wpa_ssid_txt(_ssid, ssid_len),
830 ssid->id);
831 if (ret < 0 || ret >= end - pos)
832 return pos - buf;
833 pos += ret;
834
835 if (ssid->id_str) {
836 ret = os_snprintf(pos, end - pos,
837 "id_str=%s\n",
838 ssid->id_str);
839 if (ret < 0 || ret >= end - pos)
840 return pos - buf;
841 pos += ret;
842 }
843
844 switch (ssid->mode) {
845 case WPAS_MODE_INFRA:
846 ret = os_snprintf(pos, end - pos,
847 "mode=station\n");
848 break;
849 case WPAS_MODE_IBSS:
850 ret = os_snprintf(pos, end - pos,
851 "mode=IBSS\n");
852 break;
853 case WPAS_MODE_AP:
854 ret = os_snprintf(pos, end - pos,
855 "mode=AP\n");
856 break;
857 case WPAS_MODE_P2P_GO:
858 ret = os_snprintf(pos, end - pos,
859 "mode=P2P GO\n");
860 break;
861 case WPAS_MODE_P2P_GROUP_FORMATION:
862 ret = os_snprintf(pos, end - pos,
863 "mode=P2P GO - group "
864 "formation\n");
865 break;
866 default:
867 ret = 0;
868 break;
869 }
870 if (ret < 0 || ret >= end - pos)
871 return pos - buf;
872 pos += ret;
873 }
874
875#ifdef CONFIG_AP
876 if (wpa_s->ap_iface) {
877 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
878 end - pos,
879 verbose);
880 } else
881#endif /* CONFIG_AP */
882 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
883 }
884 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
885 wpa_supplicant_state_txt(wpa_s->wpa_state));
886 if (ret < 0 || ret >= end - pos)
887 return pos - buf;
888 pos += ret;
889
890 if (wpa_s->l2 &&
891 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
892 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
893 if (ret < 0 || ret >= end - pos)
894 return pos - buf;
895 pos += ret;
896 }
897
898#ifdef CONFIG_P2P
899 if (wpa_s->global->p2p) {
900 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
901 "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
902 if (ret < 0 || ret >= end - pos)
903 return pos - buf;
904 pos += ret;
905 }
906#endif /* CONFIG_P2P */
907
908 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
909 MAC2STR(wpa_s->own_addr));
910 if (ret < 0 || ret >= end - pos)
911 return pos - buf;
912 pos += ret;
913
914 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
915 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
916 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
917 verbose);
918 if (res >= 0)
919 pos += res;
920 }
921
922 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
923 if (res >= 0)
924 pos += res;
925
926 return pos - buf;
927}
928
929
930static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
931 char *cmd)
932{
933 char *pos;
934 int id;
935 struct wpa_ssid *ssid;
936 u8 bssid[ETH_ALEN];
937
938 /* cmd: "<network id> <BSSID>" */
939 pos = os_strchr(cmd, ' ');
940 if (pos == NULL)
941 return -1;
942 *pos++ = '\0';
943 id = atoi(cmd);
944 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
945 if (hwaddr_aton(pos, bssid)) {
946 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
947 return -1;
948 }
949
950 ssid = wpa_config_get_network(wpa_s->conf, id);
951 if (ssid == NULL) {
952 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
953 "to update", id);
954 return -1;
955 }
956
957 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
958 ssid->bssid_set = !is_zero_ether_addr(bssid);
959
960 return 0;
961}
962
963
Dmitry Shmidt657a7042011-03-16 14:57:39 -0700964extern int wpa_debug_level;
965extern int wpa_debug_timestamp;
966
967static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
968 char *cmd, char *buf, size_t buflen)
969{
970 char *pos, *end, *stamp;
971 int ret;
972
973 if (cmd == NULL)
974 return -1;
975 /* cmd: "LOG_LEVEL [<level>]" */
976 if (*cmd == '\0') {
977 pos = buf;
978 end = buf + buflen;
979 ret = os_snprintf(pos, end-pos, "Current level: %d\n"
980 "{0-EXCESSIVE, 1-MSGDUMP, 2-DEBUG, 3-INFO, 4-WARNING, 5-ERROR}\n"
981 "Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp);
982 if ((ret < 0) || (ret >= end - pos))
983 ret = 0;
984 return ret;
985 }
986
987 cmd++;
988 stamp = os_strchr(cmd, ' ');
989 if (stamp) {
990 *stamp++ = '\0';
991 while (*stamp == ' ')
992 stamp++;
993 }
994
995 if (cmd && os_strlen(cmd))
996 wpa_debug_level = atoi(cmd);
997
998 if (stamp && os_strlen(stamp))
999 wpa_debug_timestamp = atoi(stamp);
1000
1001 os_memcpy(buf, "OK\n", 3);
1002 return 3;
1003}
1004
1005
Dmitry Shmidte19501d2011-03-16 14:32:18 -07001006static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1007 char *cmd, char *buf, size_t buflen)
1008{
1009 u8 bssid[ETH_ALEN];
1010 struct wpa_blacklist *e;
1011 char *pos, *end;
1012 int ret;
1013
1014 /* cmd: "BLACKLIST [<BSSID>]" */
1015 if (*cmd == '\0') {
1016 pos = buf;
1017 end = buf + buflen;
1018 e = wpa_s->blacklist;
1019 while (e) {
1020 ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid));
1021 if ((ret < 0) || (ret >= end - pos))
1022 return pos - buf;
1023 pos += ret;
1024 e = e->next;
1025 }
1026 return pos - buf;
1027 }
1028
1029 cmd++;
1030 if (os_strncmp(cmd, "clear", 5) == 0) {
1031 wpa_blacklist_clear(wpa_s);
1032 os_memcpy(buf, "OK\n", 3);
1033 return 3;
1034 }
1035
1036 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1037 if (hwaddr_aton(cmd, bssid)) {
1038 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
1039 return -1;
1040 }
1041
1042 /* Add the BSSID twice, so its count will be 2, causing it to be
1043 skipped when processing scan results. */
1044 ret = wpa_blacklist_add(wpa_s, bssid);
1045 if (ret < 0)
1046 return -1;
1047 ret = wpa_blacklist_add(wpa_s, bssid);
1048 if (ret < 0)
1049 return -1;
1050 os_memcpy(buf, "OK\n", 3);
1051 return 3;
1052}
1053
1054
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001055static int wpa_supplicant_ctrl_iface_list_networks(
1056 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1057{
1058 char *pos, *end;
1059 struct wpa_ssid *ssid;
1060 int ret;
1061
1062 pos = buf;
1063 end = buf + buflen;
1064 ret = os_snprintf(pos, end - pos,
1065 "network id / ssid / bssid / flags\n");
1066 if (ret < 0 || ret >= end - pos)
1067 return pos - buf;
1068 pos += ret;
1069
1070 ssid = wpa_s->conf->ssid;
1071 while (ssid) {
1072 ret = os_snprintf(pos, end - pos, "%d\t%s",
1073 ssid->id,
1074 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1075 if (ret < 0 || ret >= end - pos)
1076 return pos - buf;
1077 pos += ret;
1078 if (ssid->bssid_set) {
1079 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1080 MAC2STR(ssid->bssid));
1081 } else {
1082 ret = os_snprintf(pos, end - pos, "\tany");
1083 }
1084 if (ret < 0 || ret >= end - pos)
1085 return pos - buf;
1086 pos += ret;
1087 ret = os_snprintf(pos, end - pos, "\t%s%s%s",
1088 ssid == wpa_s->current_ssid ?
1089 "[CURRENT]" : "",
1090 ssid->disabled ? "[DISABLED]" : "",
1091 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1092 "");
1093 if (ret < 0 || ret >= end - pos)
1094 return pos - buf;
1095 pos += ret;
1096 ret = os_snprintf(pos, end - pos, "\n");
1097 if (ret < 0 || ret >= end - pos)
1098 return pos - buf;
1099 pos += ret;
1100
1101 ssid = ssid->next;
1102 }
1103
1104 return pos - buf;
1105}
1106
1107
1108static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1109{
1110 int first = 1, ret;
1111 ret = os_snprintf(pos, end - pos, "-");
1112 if (ret < 0 || ret >= end - pos)
1113 return pos;
1114 pos += ret;
1115 if (cipher & WPA_CIPHER_NONE) {
1116 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
1117 if (ret < 0 || ret >= end - pos)
1118 return pos;
1119 pos += ret;
1120 first = 0;
1121 }
1122 if (cipher & WPA_CIPHER_WEP40) {
1123 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
1124 if (ret < 0 || ret >= end - pos)
1125 return pos;
1126 pos += ret;
1127 first = 0;
1128 }
1129 if (cipher & WPA_CIPHER_WEP104) {
1130 ret = os_snprintf(pos, end - pos, "%sWEP104",
1131 first ? "" : "+");
1132 if (ret < 0 || ret >= end - pos)
1133 return pos;
1134 pos += ret;
1135 first = 0;
1136 }
1137 if (cipher & WPA_CIPHER_TKIP) {
1138 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
1139 if (ret < 0 || ret >= end - pos)
1140 return pos;
1141 pos += ret;
1142 first = 0;
1143 }
1144 if (cipher & WPA_CIPHER_CCMP) {
1145 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
1146 if (ret < 0 || ret >= end - pos)
1147 return pos;
1148 pos += ret;
1149 first = 0;
1150 }
1151 return pos;
1152}
1153
1154
1155static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1156 const u8 *ie, size_t ie_len)
1157{
1158 struct wpa_ie_data data;
1159 int first, ret;
1160
1161 ret = os_snprintf(pos, end - pos, "[%s-", proto);
1162 if (ret < 0 || ret >= end - pos)
1163 return pos;
1164 pos += ret;
1165
1166 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1167 ret = os_snprintf(pos, end - pos, "?]");
1168 if (ret < 0 || ret >= end - pos)
1169 return pos;
1170 pos += ret;
1171 return pos;
1172 }
1173
1174 first = 1;
1175 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1176 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1177 if (ret < 0 || ret >= end - pos)
1178 return pos;
1179 pos += ret;
1180 first = 0;
1181 }
1182 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1183 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1184 if (ret < 0 || ret >= end - pos)
1185 return pos;
1186 pos += ret;
1187 first = 0;
1188 }
1189 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1190 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1191 if (ret < 0 || ret >= end - pos)
1192 return pos;
1193 pos += ret;
1194 first = 0;
1195 }
1196#ifdef CONFIG_IEEE80211R
1197 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1198 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1199 first ? "" : "+");
1200 if (ret < 0 || ret >= end - pos)
1201 return pos;
1202 pos += ret;
1203 first = 0;
1204 }
1205 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1206 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1207 first ? "" : "+");
1208 if (ret < 0 || ret >= end - pos)
1209 return pos;
1210 pos += ret;
1211 first = 0;
1212 }
1213#endif /* CONFIG_IEEE80211R */
1214#ifdef CONFIG_IEEE80211W
1215 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1216 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1217 first ? "" : "+");
1218 if (ret < 0 || ret >= end - pos)
1219 return pos;
1220 pos += ret;
1221 first = 0;
1222 }
1223 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1224 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1225 first ? "" : "+");
1226 if (ret < 0 || ret >= end - pos)
1227 return pos;
1228 pos += ret;
1229 first = 0;
1230 }
1231#endif /* CONFIG_IEEE80211W */
1232
1233 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1234
1235 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1236 ret = os_snprintf(pos, end - pos, "-preauth");
1237 if (ret < 0 || ret >= end - pos)
1238 return pos;
1239 pos += ret;
1240 }
1241
1242 ret = os_snprintf(pos, end - pos, "]");
1243 if (ret < 0 || ret >= end - pos)
1244 return pos;
1245 pos += ret;
1246
1247 return pos;
1248}
1249
1250
1251#ifdef CONFIG_WPS
1252static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1253 char *pos, char *end,
1254 struct wpabuf *wps_ie)
1255{
1256 int ret;
1257 const char *txt;
1258
1259 if (wps_ie == NULL)
1260 return pos;
1261 if (wps_is_selected_pbc_registrar(wps_ie))
1262 txt = "[WPS-PBC]";
1263#ifdef CONFIG_WPS2
1264 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1265 txt = "[WPS-AUTH]";
1266#endif /* CONFIG_WPS2 */
1267 else if (wps_is_selected_pin_registrar(wps_ie))
1268 txt = "[WPS-PIN]";
1269 else
1270 txt = "[WPS]";
1271
1272 ret = os_snprintf(pos, end - pos, "%s", txt);
1273 if (ret >= 0 && ret < end - pos)
1274 pos += ret;
1275 wpabuf_free(wps_ie);
1276 return pos;
1277}
1278#endif /* CONFIG_WPS */
1279
1280
1281static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1282 char *pos, char *end,
1283 const struct wpa_bss *bss)
1284{
1285#ifdef CONFIG_WPS
1286 struct wpabuf *wps_ie;
1287 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1288 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1289#else /* CONFIG_WPS */
1290 return pos;
1291#endif /* CONFIG_WPS */
1292}
1293
1294
1295/* Format one result on one text line into a buffer. */
1296static int wpa_supplicant_ctrl_iface_scan_result(
1297 struct wpa_supplicant *wpa_s,
1298 const struct wpa_bss *bss, char *buf, size_t buflen)
1299{
1300 char *pos, *end;
1301 int ret;
1302 const u8 *ie, *ie2, *p2p;
1303
1304 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
1305 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
1306 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
1307 0)
1308 return 0; /* Do not show P2P listen discovery results here */
1309
1310 pos = buf;
1311 end = buf + buflen;
1312
1313 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1314 MAC2STR(bss->bssid), bss->freq, bss->level);
1315 if (ret < 0 || ret >= end - pos)
1316 return -1;
1317 pos += ret;
1318 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1319 if (ie)
1320 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1321 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1322 if (ie2)
1323 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1324 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1325 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1326 ret = os_snprintf(pos, end - pos, "[WEP]");
1327 if (ret < 0 || ret >= end - pos)
1328 return -1;
1329 pos += ret;
1330 }
1331 if (bss->caps & IEEE80211_CAP_IBSS) {
1332 ret = os_snprintf(pos, end - pos, "[IBSS]");
1333 if (ret < 0 || ret >= end - pos)
1334 return -1;
1335 pos += ret;
1336 }
1337 if (bss->caps & IEEE80211_CAP_ESS) {
1338 ret = os_snprintf(pos, end - pos, "[ESS]");
1339 if (ret < 0 || ret >= end - pos)
1340 return -1;
1341 pos += ret;
1342 }
1343 if (p2p) {
1344 ret = os_snprintf(pos, end - pos, "[P2P]");
1345 if (ret < 0 || ret >= end - pos)
1346 return -1;
1347 pos += ret;
1348 }
1349
1350 ret = os_snprintf(pos, end - pos, "\t%s",
1351 wpa_ssid_txt(bss->ssid, bss->ssid_len));
1352 if (ret < 0 || ret >= end - pos)
1353 return -1;
1354 pos += ret;
1355
1356 ret = os_snprintf(pos, end - pos, "\n");
1357 if (ret < 0 || ret >= end - pos)
1358 return -1;
1359 pos += ret;
1360
1361 return pos - buf;
1362}
1363
1364
1365static int wpa_supplicant_ctrl_iface_scan_results(
1366 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1367{
1368 char *pos, *end;
1369 struct wpa_bss *bss;
1370 int ret;
1371
1372 pos = buf;
1373 end = buf + buflen;
1374 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
1375 "flags / ssid\n");
1376 if (ret < 0 || ret >= end - pos)
1377 return pos - buf;
1378 pos += ret;
1379
1380 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1381 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
1382 end - pos);
1383 if (ret < 0 || ret >= end - pos)
1384 return pos - buf;
1385 pos += ret;
1386 }
1387
1388 return pos - buf;
1389}
1390
1391
1392static int wpa_supplicant_ctrl_iface_select_network(
1393 struct wpa_supplicant *wpa_s, char *cmd)
1394{
1395 int id;
1396 struct wpa_ssid *ssid;
1397
1398 /* cmd: "<network id>" or "any" */
1399 if (os_strcmp(cmd, "any") == 0) {
1400 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
1401 ssid = NULL;
1402 } else {
1403 id = atoi(cmd);
1404 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
1405
1406 ssid = wpa_config_get_network(wpa_s->conf, id);
1407 if (ssid == NULL) {
1408 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1409 "network id=%d", id);
1410 return -1;
1411 }
1412 if (ssid->disabled == 2) {
1413 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1414 "SELECT_NETWORK with persistent P2P group");
1415 return -1;
1416 }
1417 }
1418
1419 wpa_supplicant_select_network(wpa_s, ssid);
1420
1421 return 0;
1422}
1423
1424
1425static int wpa_supplicant_ctrl_iface_enable_network(
1426 struct wpa_supplicant *wpa_s, char *cmd)
1427{
1428 int id;
1429 struct wpa_ssid *ssid;
1430
1431 /* cmd: "<network id>" or "all" */
1432 if (os_strcmp(cmd, "all") == 0) {
1433 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1434 ssid = NULL;
1435 } else {
1436 id = atoi(cmd);
1437 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1438
1439 ssid = wpa_config_get_network(wpa_s->conf, id);
1440 if (ssid == NULL) {
1441 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1442 "network id=%d", id);
1443 return -1;
1444 }
1445 if (ssid->disabled == 2) {
1446 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1447 "ENABLE_NETWORK with persistent P2P group");
1448 return -1;
1449 }
1450 }
1451 wpa_supplicant_enable_network(wpa_s, ssid);
1452
1453 return 0;
1454}
1455
1456
1457static int wpa_supplicant_ctrl_iface_disable_network(
1458 struct wpa_supplicant *wpa_s, char *cmd)
1459{
1460 int id;
1461 struct wpa_ssid *ssid;
1462
1463 /* cmd: "<network id>" or "all" */
1464 if (os_strcmp(cmd, "all") == 0) {
1465 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1466 ssid = NULL;
1467 } else {
1468 id = atoi(cmd);
1469 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1470
1471 ssid = wpa_config_get_network(wpa_s->conf, id);
1472 if (ssid == NULL) {
1473 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1474 "network id=%d", id);
1475 return -1;
1476 }
1477 if (ssid->disabled == 2) {
1478 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1479 "DISABLE_NETWORK with persistent P2P "
1480 "group");
1481 return -1;
1482 }
1483 }
1484 wpa_supplicant_disable_network(wpa_s, ssid);
1485
1486 return 0;
1487}
1488
1489
1490static int wpa_supplicant_ctrl_iface_add_network(
1491 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1492{
1493 struct wpa_ssid *ssid;
1494 int ret;
1495
1496 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1497
1498 ssid = wpa_config_add_network(wpa_s->conf);
1499 if (ssid == NULL)
1500 return -1;
1501
1502 wpas_notify_network_added(wpa_s, ssid);
1503
1504 ssid->disabled = 1;
1505 wpa_config_set_network_defaults(ssid);
1506
1507 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1508 if (ret < 0 || (size_t) ret >= buflen)
1509 return -1;
1510 return ret;
1511}
1512
1513
1514static int wpa_supplicant_ctrl_iface_remove_network(
1515 struct wpa_supplicant *wpa_s, char *cmd)
1516{
1517 int id;
1518 struct wpa_ssid *ssid;
1519
1520 /* cmd: "<network id>" or "all" */
1521 if (os_strcmp(cmd, "all") == 0) {
1522 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1523 ssid = wpa_s->conf->ssid;
1524 while (ssid) {
1525 struct wpa_ssid *remove_ssid = ssid;
1526 id = ssid->id;
1527 ssid = ssid->next;
1528 wpas_notify_network_removed(wpa_s, remove_ssid);
1529 wpa_config_remove_network(wpa_s->conf, id);
1530 }
1531 if (wpa_s->current_ssid) {
1532 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Jouni Malinen75ecf522011-06-27 15:19:46 -07001533 wpa_sm_set_config(wpa_s->wpa, NULL);
1534 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535 wpa_supplicant_disassociate(wpa_s,
1536 WLAN_REASON_DEAUTH_LEAVING);
1537 }
1538 return 0;
1539 }
1540
1541 id = atoi(cmd);
1542 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1543
1544 ssid = wpa_config_get_network(wpa_s->conf, id);
1545 if (ssid == NULL ||
1546 wpa_config_remove_network(wpa_s->conf, id) < 0) {
1547 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1548 "id=%d", id);
1549 return -1;
1550 }
1551
1552 if (ssid == wpa_s->current_ssid) {
1553 /*
1554 * Invalidate the EAP session cache if the current network is
1555 * removed.
1556 */
1557 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Jouni Malinen75ecf522011-06-27 15:19:46 -07001558 wpa_sm_set_config(wpa_s->wpa, NULL);
1559 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001560
1561 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1562 }
1563
1564 return 0;
1565}
1566
1567
1568static int wpa_supplicant_ctrl_iface_set_network(
1569 struct wpa_supplicant *wpa_s, char *cmd)
1570{
1571 int id;
1572 struct wpa_ssid *ssid;
1573 char *name, *value;
1574
1575 /* cmd: "<network id> <variable name> <value>" */
1576 name = os_strchr(cmd, ' ');
1577 if (name == NULL)
1578 return -1;
1579 *name++ = '\0';
1580
1581 value = os_strchr(name, ' ');
1582 if (value == NULL)
1583 return -1;
1584 *value++ = '\0';
1585
1586 id = atoi(cmd);
1587 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1588 id, name);
1589 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1590 (u8 *) value, os_strlen(value));
1591
1592 ssid = wpa_config_get_network(wpa_s->conf, id);
1593 if (ssid == NULL) {
1594 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1595 "id=%d", id);
1596 return -1;
1597 }
1598
1599 if (wpa_config_set(ssid, name, value, 0) < 0) {
1600 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1601 "variable '%s'", name);
1602 return -1;
1603 }
1604
1605 if (wpa_s->current_ssid == ssid) {
1606 /*
1607 * Invalidate the EAP session cache if anything in the current
1608 * configuration changes.
1609 */
1610 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1611 }
1612
1613 if ((os_strcmp(name, "psk") == 0 &&
1614 value[0] == '"' && ssid->ssid_len) ||
1615 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1616 wpa_config_update_psk(ssid);
1617 else if (os_strcmp(name, "priority") == 0)
1618 wpa_config_update_prio_list(wpa_s->conf);
1619
1620 return 0;
1621}
1622
1623
1624static int wpa_supplicant_ctrl_iface_get_network(
1625 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1626{
1627 int id;
1628 size_t res;
1629 struct wpa_ssid *ssid;
1630 char *name, *value;
1631
1632 /* cmd: "<network id> <variable name>" */
1633 name = os_strchr(cmd, ' ');
1634 if (name == NULL || buflen == 0)
1635 return -1;
1636 *name++ = '\0';
1637
1638 id = atoi(cmd);
1639 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1640 id, name);
1641
1642 ssid = wpa_config_get_network(wpa_s->conf, id);
1643 if (ssid == NULL) {
1644 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1645 "id=%d", id);
1646 return -1;
1647 }
1648
1649 value = wpa_config_get_no_key(ssid, name);
1650 if (value == NULL) {
1651 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1652 "variable '%s'", name);
1653 return -1;
1654 }
1655
1656 res = os_strlcpy(buf, value, buflen);
1657 if (res >= buflen) {
1658 os_free(value);
1659 return -1;
1660 }
1661
1662 os_free(value);
1663
1664 return res;
1665}
1666
1667
1668#ifndef CONFIG_NO_CONFIG_WRITE
1669static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1670{
1671 int ret;
1672
1673 if (!wpa_s->conf->update_config) {
1674 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1675 "to update configuration (update_config=0)");
1676 return -1;
1677 }
1678
1679 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1680 if (ret) {
1681 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1682 "update configuration");
1683 } else {
1684 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1685 " updated");
1686 }
1687
1688 return ret;
1689}
1690#endif /* CONFIG_NO_CONFIG_WRITE */
1691
1692
1693static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1694 struct wpa_driver_capa *capa,
1695 char *buf, size_t buflen)
1696{
1697 int ret, first = 1;
1698 char *pos, *end;
1699 size_t len;
1700
1701 pos = buf;
1702 end = pos + buflen;
1703
1704 if (res < 0) {
1705 if (strict)
1706 return 0;
1707 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1708 if (len >= buflen)
1709 return -1;
1710 return len;
1711 }
1712
1713 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1714 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1715 if (ret < 0 || ret >= end - pos)
1716 return pos - buf;
1717 pos += ret;
1718 first = 0;
1719 }
1720
1721 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1722 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1723 if (ret < 0 || ret >= end - pos)
1724 return pos - buf;
1725 pos += ret;
1726 first = 0;
1727 }
1728
1729 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1730 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1731 if (ret < 0 || ret >= end - pos)
1732 return pos - buf;
1733 pos += ret;
1734 first = 0;
1735 }
1736
1737 return pos - buf;
1738}
1739
1740
1741static int ctrl_iface_get_capability_group(int res, char *strict,
1742 struct wpa_driver_capa *capa,
1743 char *buf, size_t buflen)
1744{
1745 int ret, first = 1;
1746 char *pos, *end;
1747 size_t len;
1748
1749 pos = buf;
1750 end = pos + buflen;
1751
1752 if (res < 0) {
1753 if (strict)
1754 return 0;
1755 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1756 if (len >= buflen)
1757 return -1;
1758 return len;
1759 }
1760
1761 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1762 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1763 if (ret < 0 || ret >= end - pos)
1764 return pos - buf;
1765 pos += ret;
1766 first = 0;
1767 }
1768
1769 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1770 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1771 if (ret < 0 || ret >= end - pos)
1772 return pos - buf;
1773 pos += ret;
1774 first = 0;
1775 }
1776
1777 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1778 ret = os_snprintf(pos, end - pos, "%sWEP104",
1779 first ? "" : " ");
1780 if (ret < 0 || ret >= end - pos)
1781 return pos - buf;
1782 pos += ret;
1783 first = 0;
1784 }
1785
1786 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1787 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1788 if (ret < 0 || ret >= end - pos)
1789 return pos - buf;
1790 pos += ret;
1791 first = 0;
1792 }
1793
1794 return pos - buf;
1795}
1796
1797
1798static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1799 struct wpa_driver_capa *capa,
1800 char *buf, size_t buflen)
1801{
1802 int ret;
1803 char *pos, *end;
1804 size_t len;
1805
1806 pos = buf;
1807 end = pos + buflen;
1808
1809 if (res < 0) {
1810 if (strict)
1811 return 0;
1812 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1813 "NONE", buflen);
1814 if (len >= buflen)
1815 return -1;
1816 return len;
1817 }
1818
1819 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1820 if (ret < 0 || ret >= end - pos)
1821 return pos - buf;
1822 pos += ret;
1823
1824 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1825 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1826 ret = os_snprintf(pos, end - pos, " WPA-EAP");
1827 if (ret < 0 || ret >= end - pos)
1828 return pos - buf;
1829 pos += ret;
1830 }
1831
1832 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1833 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1834 ret = os_snprintf(pos, end - pos, " WPA-PSK");
1835 if (ret < 0 || ret >= end - pos)
1836 return pos - buf;
1837 pos += ret;
1838 }
1839
1840 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1841 ret = os_snprintf(pos, end - pos, " WPA-NONE");
1842 if (ret < 0 || ret >= end - pos)
1843 return pos - buf;
1844 pos += ret;
1845 }
1846
1847 return pos - buf;
1848}
1849
1850
1851static int ctrl_iface_get_capability_proto(int res, char *strict,
1852 struct wpa_driver_capa *capa,
1853 char *buf, size_t buflen)
1854{
1855 int ret, first = 1;
1856 char *pos, *end;
1857 size_t len;
1858
1859 pos = buf;
1860 end = pos + buflen;
1861
1862 if (res < 0) {
1863 if (strict)
1864 return 0;
1865 len = os_strlcpy(buf, "RSN WPA", buflen);
1866 if (len >= buflen)
1867 return -1;
1868 return len;
1869 }
1870
1871 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1872 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1873 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1874 if (ret < 0 || ret >= end - pos)
1875 return pos - buf;
1876 pos += ret;
1877 first = 0;
1878 }
1879
1880 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1881 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1882 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1883 if (ret < 0 || ret >= end - pos)
1884 return pos - buf;
1885 pos += ret;
1886 first = 0;
1887 }
1888
1889 return pos - buf;
1890}
1891
1892
1893static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1894 struct wpa_driver_capa *capa,
1895 char *buf, size_t buflen)
1896{
1897 int ret, first = 1;
1898 char *pos, *end;
1899 size_t len;
1900
1901 pos = buf;
1902 end = pos + buflen;
1903
1904 if (res < 0) {
1905 if (strict)
1906 return 0;
1907 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1908 if (len >= buflen)
1909 return -1;
1910 return len;
1911 }
1912
1913 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1914 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1915 if (ret < 0 || ret >= end - pos)
1916 return pos - buf;
1917 pos += ret;
1918 first = 0;
1919 }
1920
1921 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1922 ret = os_snprintf(pos, end - pos, "%sSHARED",
1923 first ? "" : " ");
1924 if (ret < 0 || ret >= end - pos)
1925 return pos - buf;
1926 pos += ret;
1927 first = 0;
1928 }
1929
1930 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1931 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1932 if (ret < 0 || ret >= end - pos)
1933 return pos - buf;
1934 pos += ret;
1935 first = 0;
1936 }
1937
1938 return pos - buf;
1939}
1940
1941
1942static int wpa_supplicant_ctrl_iface_get_capability(
1943 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1944 size_t buflen)
1945{
1946 struct wpa_driver_capa capa;
1947 int res;
1948 char *strict;
1949 char field[30];
1950 size_t len;
1951
1952 /* Determine whether or not strict checking was requested */
1953 len = os_strlcpy(field, _field, sizeof(field));
1954 if (len >= sizeof(field))
1955 return -1;
1956 strict = os_strchr(field, ' ');
1957 if (strict != NULL) {
1958 *strict++ = '\0';
1959 if (os_strcmp(strict, "strict") != 0)
1960 return -1;
1961 }
1962
1963 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1964 field, strict ? strict : "");
1965
1966 if (os_strcmp(field, "eap") == 0) {
1967 return eap_get_names(buf, buflen);
1968 }
1969
1970 res = wpa_drv_get_capa(wpa_s, &capa);
1971
1972 if (os_strcmp(field, "pairwise") == 0)
1973 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1974 buf, buflen);
1975
1976 if (os_strcmp(field, "group") == 0)
1977 return ctrl_iface_get_capability_group(res, strict, &capa,
1978 buf, buflen);
1979
1980 if (os_strcmp(field, "key_mgmt") == 0)
1981 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1982 buf, buflen);
1983
1984 if (os_strcmp(field, "proto") == 0)
1985 return ctrl_iface_get_capability_proto(res, strict, &capa,
1986 buf, buflen);
1987
1988 if (os_strcmp(field, "auth_alg") == 0)
1989 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1990 buf, buflen);
1991
1992 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1993 field);
1994
1995 return -1;
1996}
1997
1998
1999static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
2000 const char *cmd, char *buf,
2001 size_t buflen)
2002{
2003 u8 bssid[ETH_ALEN];
2004 size_t i;
2005 struct wpa_bss *bss;
2006 int ret;
2007 char *pos, *end;
2008 const u8 *ie, *ie2;
2009
2010 if (os_strcmp(cmd, "FIRST") == 0)
2011 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
2012 else if (os_strncmp(cmd, "ID-", 3) == 0) {
2013 i = atoi(cmd + 3);
2014 bss = wpa_bss_get_id(wpa_s, i);
2015 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2016 i = atoi(cmd + 5);
2017 bss = wpa_bss_get_id(wpa_s, i);
2018 if (bss) {
2019 struct dl_list *next = bss->list_id.next;
2020 if (next == &wpa_s->bss_id)
2021 bss = NULL;
2022 else
2023 bss = dl_list_entry(next, struct wpa_bss,
2024 list_id);
2025 }
2026 } else if (hwaddr_aton(cmd, bssid) == 0)
2027 bss = wpa_bss_get_bssid(wpa_s, bssid);
2028 else {
2029 struct wpa_bss *tmp;
2030 i = atoi(cmd);
2031 bss = NULL;
2032 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
2033 {
2034 if (i-- == 0) {
2035 bss = tmp;
2036 break;
2037 }
2038 }
2039 }
2040
2041 if (bss == NULL)
2042 return 0;
2043
2044 pos = buf;
2045 end = buf + buflen;
2046 ret = os_snprintf(pos, end - pos,
2047 "id=%u\n"
2048 "bssid=" MACSTR "\n"
2049 "freq=%d\n"
2050 "beacon_int=%d\n"
2051 "capabilities=0x%04x\n"
2052 "qual=%d\n"
2053 "noise=%d\n"
2054 "level=%d\n"
2055 "tsf=%016llu\n"
2056 "ie=",
2057 bss->id,
2058 MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
2059 bss->caps, bss->qual, bss->noise, bss->level,
2060 (unsigned long long) bss->tsf);
2061 if (ret < 0 || ret >= end - pos)
2062 return pos - buf;
2063 pos += ret;
2064
2065 ie = (const u8 *) (bss + 1);
2066 for (i = 0; i < bss->ie_len; i++) {
2067 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
2068 if (ret < 0 || ret >= end - pos)
2069 return pos - buf;
2070 pos += ret;
2071 }
2072 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
2073 ret = os_snprintf(pos, end - pos, "[P2P]");
2074 if (ret < 0 || ret >= end - pos)
2075 return pos - buf;
2076 pos += ret;
2077 }
2078
2079 ret = os_snprintf(pos, end - pos, "\n");
2080 if (ret < 0 || ret >= end - pos)
2081 return pos - buf;
2082 pos += ret;
2083
2084 ret = os_snprintf(pos, end - pos, "flags=");
2085 if (ret < 0 || ret >= end - pos)
2086 return pos - buf;
2087 pos += ret;
2088
2089 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2090 if (ie)
2091 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2092 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2093 if (ie2)
2094 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2095 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2096 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2097 ret = os_snprintf(pos, end - pos, "[WEP]");
2098 if (ret < 0 || ret >= end - pos)
2099 return pos - buf;
2100 pos += ret;
2101 }
2102 if (bss->caps & IEEE80211_CAP_IBSS) {
2103 ret = os_snprintf(pos, end - pos, "[IBSS]");
2104 if (ret < 0 || ret >= end - pos)
2105 return pos - buf;
2106 pos += ret;
2107 }
2108 if (bss->caps & IEEE80211_CAP_ESS) {
2109 ret = os_snprintf(pos, end - pos, "[ESS]");
2110 if (ret < 0 || ret >= end - pos)
2111 return pos - buf;
2112 pos += ret;
2113 }
2114
2115 ret = os_snprintf(pos, end - pos, "\n");
2116 if (ret < 0 || ret >= end - pos)
2117 return pos - buf;
2118 pos += ret;
2119
2120 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
2121 wpa_ssid_txt(bss->ssid, bss->ssid_len));
2122 if (ret < 0 || ret >= end - pos)
2123 return pos - buf;
2124 pos += ret;
2125
2126#ifdef CONFIG_WPS
2127 ie = (const u8 *) (bss + 1);
2128 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
2129 if (ret < 0 || ret >= end - pos)
2130 return pos - buf;
2131 pos += ret;
2132#endif /* CONFIG_WPS */
2133
2134#ifdef CONFIG_P2P
2135 ie = (const u8 *) (bss + 1);
2136 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
2137 if (ret < 0 || ret >= end - pos)
2138 return pos - buf;
2139 pos += ret;
2140#endif /* CONFIG_P2P */
2141
2142 return pos - buf;
2143}
2144
2145
2146static int wpa_supplicant_ctrl_iface_ap_scan(
2147 struct wpa_supplicant *wpa_s, char *cmd)
2148{
2149 int ap_scan = atoi(cmd);
2150 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
2151}
2152
2153
2154static int wpa_supplicant_ctrl_iface_scan_interval(
2155 struct wpa_supplicant *wpa_s, char *cmd)
2156{
2157 int scan_int = atoi(cmd);
2158 if (scan_int < 0)
2159 return -1;
2160 wpa_s->scan_interval = scan_int;
2161 return 0;
2162}
2163
2164
2165static int wpa_supplicant_ctrl_iface_bss_expire_age(
2166 struct wpa_supplicant *wpa_s, char *cmd)
2167{
2168 int expire_age = atoi(cmd);
2169 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
2170}
2171
2172
2173static int wpa_supplicant_ctrl_iface_bss_expire_count(
2174 struct wpa_supplicant *wpa_s, char *cmd)
2175{
2176 int expire_count = atoi(cmd);
2177 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
2178}
2179
2180
2181static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
2182{
2183 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
2184 /* MLME-DELETEKEYS.request */
2185 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
2186 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
2187 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
2188 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
2189#ifdef CONFIG_IEEE80211W
2190 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
2191 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
2192#endif /* CONFIG_IEEE80211W */
2193
2194 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
2195 0);
2196 /* MLME-SETPROTECTION.request(None) */
2197 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
2198 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
2199 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2200 wpa_sm_drop_sa(wpa_s->wpa);
2201}
2202
2203
2204static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
2205 char *addr)
2206{
2207 u8 bssid[ETH_ALEN];
2208 struct wpa_bss *bss;
2209 struct wpa_ssid *ssid = wpa_s->current_ssid;
2210
2211 if (hwaddr_aton(addr, bssid)) {
2212 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
2213 "address '%s'", addr);
2214 return -1;
2215 }
2216
2217 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
2218
2219 bss = wpa_bss_get_bssid(wpa_s, bssid);
2220 if (!bss) {
2221 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
2222 "from BSS table");
2223 return -1;
2224 }
2225
2226 /*
2227 * TODO: Find best network configuration block from configuration to
2228 * allow roaming to other networks
2229 */
2230
2231 if (!ssid) {
2232 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
2233 "configuration known for the target AP");
2234 return -1;
2235 }
2236
2237 wpa_s->reassociate = 1;
2238 wpa_supplicant_connect(wpa_s, bss, ssid);
2239
2240 return 0;
2241}
2242
2243
2244#ifdef CONFIG_P2P
2245static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
2246{
2247 unsigned int timeout = atoi(cmd);
2248 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
2249
2250 if (os_strstr(cmd, "type=social"))
2251 type = P2P_FIND_ONLY_SOCIAL;
2252 else if (os_strstr(cmd, "type=progressive"))
2253 type = P2P_FIND_PROGRESSIVE;
2254
2255 return wpas_p2p_find(wpa_s, timeout, type, 0, NULL);
2256}
2257
2258
2259static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
2260 char *buf, size_t buflen)
2261{
2262 u8 addr[ETH_ALEN];
2263 char *pos, *pos2;
2264 char *pin = NULL;
2265 enum p2p_wps_method wps_method;
2266 int new_pin;
2267 int ret;
2268 int persistent_group;
2269 int join;
2270 int auth;
2271 int go_intent = -1;
2272 int freq = 0;
2273
2274 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
2275 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
2276
2277 if (hwaddr_aton(cmd, addr))
2278 return -1;
2279
2280 pos = cmd + 17;
2281 if (*pos != ' ')
2282 return -1;
2283 pos++;
2284
2285 persistent_group = os_strstr(pos, " persistent") != NULL;
2286 join = os_strstr(pos, " join") != NULL;
2287 auth = os_strstr(pos, " auth") != NULL;
2288
2289 pos2 = os_strstr(pos, " go_intent=");
2290 if (pos2) {
2291 pos2 += 11;
2292 go_intent = atoi(pos2);
2293 if (go_intent < 0 || go_intent > 15)
2294 return -1;
2295 }
2296
2297 pos2 = os_strstr(pos, " freq=");
2298 if (pos2) {
2299 pos2 += 6;
2300 freq = atoi(pos2);
2301 if (freq <= 0)
2302 return -1;
2303 }
2304
2305 if (os_strncmp(pos, "pin", 3) == 0) {
2306 /* Request random PIN (to be displayed) and enable the PIN */
2307 wps_method = WPS_PIN_DISPLAY;
2308 } else if (os_strncmp(pos, "pbc", 3) == 0) {
2309 wps_method = WPS_PBC;
2310 } else {
2311 pin = pos;
2312 pos = os_strchr(pin, ' ');
2313 wps_method = WPS_PIN_KEYPAD;
2314 if (pos) {
2315 *pos++ = '\0';
2316 if (os_strncmp(pos, "label", 5) == 0)
2317 wps_method = WPS_PIN_LABEL;
2318 else if (os_strncmp(pos, "display", 7) == 0)
2319 wps_method = WPS_PIN_DISPLAY;
2320 }
2321 }
2322
2323 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
2324 persistent_group, join, auth, go_intent,
2325 freq);
2326 if (new_pin == -2) {
2327 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
2328 return 25;
2329 }
2330 if (new_pin == -3) {
2331 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
2332 return 25;
2333 }
2334 if (new_pin < 0)
2335 return -1;
2336 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
2337 ret = os_snprintf(buf, buflen, "%08d", new_pin);
2338 if (ret < 0 || (size_t) ret >= buflen)
2339 return -1;
2340 return ret;
2341 }
2342
2343 os_memcpy(buf, "OK\n", 3);
2344 return 3;
2345}
2346
2347
2348static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
2349{
2350 unsigned int timeout = atoi(cmd);
2351 return wpas_p2p_listen(wpa_s, timeout);
2352}
2353
2354
2355static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
2356{
2357 u8 addr[ETH_ALEN];
2358 char *pos;
2359
2360 /* <addr> <config method> */
2361
2362 if (hwaddr_aton(cmd, addr))
2363 return -1;
2364
2365 pos = cmd + 17;
2366 if (*pos != ' ')
2367 return -1;
2368 pos++;
2369
2370 return wpas_p2p_prov_disc(wpa_s, addr, pos);
2371}
2372
2373
2374static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
2375 size_t buflen)
2376{
2377 struct wpa_ssid *ssid = wpa_s->current_ssid;
2378
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07002379#ifdef ANDROID_BRCM_P2P_PATCH
2380 struct wpa_supplicant *ifs = NULL;
2381
2382 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
2383 if((ifs->ap_iface) &&
2384 (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO)) {
2385 ssid = ifs->current_ssid;
2386 }
2387 }
2388#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2390 ssid->passphrase == NULL)
2391 return -1;
2392
2393 os_strlcpy(buf, ssid->passphrase, buflen);
2394 return os_strlen(buf);
2395}
2396
2397
2398static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
2399 char *buf, size_t buflen)
2400{
2401 u64 ref;
2402 int res;
2403 u8 dst_buf[ETH_ALEN], *dst;
2404 struct wpabuf *tlvs;
2405 char *pos;
2406 size_t len;
2407
2408 if (hwaddr_aton(cmd, dst_buf))
2409 return -1;
2410 dst = dst_buf;
2411 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2412 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2413 dst = NULL;
2414 pos = cmd + 17;
2415 if (*pos != ' ')
2416 return -1;
2417 pos++;
2418
2419 if (os_strncmp(pos, "upnp ", 5) == 0) {
2420 u8 version;
2421 pos += 5;
2422 if (hexstr2bin(pos, &version, 1) < 0)
2423 return -1;
2424 pos += 2;
2425 if (*pos != ' ')
2426 return -1;
2427 pos++;
2428 ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst,
2429 version, pos);
2430 } else {
2431 len = os_strlen(pos);
2432 if (len & 1)
2433 return -1;
2434 len /= 2;
2435 tlvs = wpabuf_alloc(len);
2436 if (tlvs == NULL)
2437 return -1;
2438 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
2439 wpabuf_free(tlvs);
2440 return -1;
2441 }
2442
2443 ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs);
2444 wpabuf_free(tlvs);
2445 }
2446 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
2447 if (res < 0 || (unsigned) res >= buflen)
2448 return -1;
2449 return res;
2450}
2451
2452
2453static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
2454 char *cmd)
2455{
2456 long long unsigned val;
2457 u64 req;
2458 if (sscanf(cmd, "%llx", &val) != 1)
2459 return -1;
2460 req = val;
2461 return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req);
2462}
2463
2464
2465static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
2466{
2467 int freq;
2468 u8 dst[ETH_ALEN];
2469 u8 dialog_token;
2470 struct wpabuf *resp_tlvs;
2471 char *pos, *pos2;
2472 size_t len;
2473
2474 pos = os_strchr(cmd, ' ');
2475 if (pos == NULL)
2476 return -1;
2477 *pos++ = '\0';
2478 freq = atoi(cmd);
2479 if (freq == 0)
2480 return -1;
2481
2482 if (hwaddr_aton(pos, dst))
2483 return -1;
2484 pos += 17;
2485 if (*pos != ' ')
2486 return -1;
2487 pos++;
2488
2489 pos2 = os_strchr(pos, ' ');
2490 if (pos2 == NULL)
2491 return -1;
2492 *pos2++ = '\0';
2493 dialog_token = atoi(pos);
2494
2495 len = os_strlen(pos2);
2496 if (len & 1)
2497 return -1;
2498 len /= 2;
2499 resp_tlvs = wpabuf_alloc(len);
2500 if (resp_tlvs == NULL)
2501 return -1;
2502 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
2503 wpabuf_free(resp_tlvs);
2504 return -1;
2505 }
2506
2507 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
2508 wpabuf_free(resp_tlvs);
2509 return 0;
2510}
2511
2512
2513static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
2514 char *cmd)
2515{
2516 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
2517 return 0;
2518}
2519
2520
2521static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
2522 char *cmd)
2523{
2524 char *pos;
2525 size_t len;
2526 struct wpabuf *query, *resp;
2527
2528 pos = os_strchr(cmd, ' ');
2529 if (pos == NULL)
2530 return -1;
2531 *pos++ = '\0';
2532
2533 len = os_strlen(cmd);
2534 if (len & 1)
2535 return -1;
2536 len /= 2;
2537 query = wpabuf_alloc(len);
2538 if (query == NULL)
2539 return -1;
2540 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2541 wpabuf_free(query);
2542 return -1;
2543 }
2544
2545 len = os_strlen(pos);
2546 if (len & 1) {
2547 wpabuf_free(query);
2548 return -1;
2549 }
2550 len /= 2;
2551 resp = wpabuf_alloc(len);
2552 if (resp == NULL) {
2553 wpabuf_free(query);
2554 return -1;
2555 }
2556 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
2557 wpabuf_free(query);
2558 wpabuf_free(resp);
2559 return -1;
2560 }
2561
2562 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
2563 wpabuf_free(query);
2564 wpabuf_free(resp);
2565 return -1;
2566 }
2567 return 0;
2568}
2569
2570
2571static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2572{
2573 char *pos;
2574 u8 version;
2575
2576 pos = os_strchr(cmd, ' ');
2577 if (pos == NULL)
2578 return -1;
2579 *pos++ = '\0';
2580
2581 if (hexstr2bin(cmd, &version, 1) < 0)
2582 return -1;
2583
2584 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
2585}
2586
2587
2588static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
2589{
2590 char *pos;
2591
2592 pos = os_strchr(cmd, ' ');
2593 if (pos == NULL)
2594 return -1;
2595 *pos++ = '\0';
2596
2597 if (os_strcmp(cmd, "bonjour") == 0)
2598 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
2599 if (os_strcmp(cmd, "upnp") == 0)
2600 return p2p_ctrl_service_add_upnp(wpa_s, pos);
2601 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2602 return -1;
2603}
2604
2605
2606static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
2607 char *cmd)
2608{
2609 size_t len;
2610 struct wpabuf *query;
2611 int ret;
2612
2613 len = os_strlen(cmd);
2614 if (len & 1)
2615 return -1;
2616 len /= 2;
2617 query = wpabuf_alloc(len);
2618 if (query == NULL)
2619 return -1;
2620 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2621 wpabuf_free(query);
2622 return -1;
2623 }
2624
2625 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2626 wpabuf_free(query);
2627 return ret;
2628}
2629
2630
2631static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2632{
2633 char *pos;
2634 u8 version;
2635
2636 pos = os_strchr(cmd, ' ');
2637 if (pos == NULL)
2638 return -1;
2639 *pos++ = '\0';
2640
2641 if (hexstr2bin(cmd, &version, 1) < 0)
2642 return -1;
2643
2644 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
2645}
2646
2647
2648static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
2649{
2650 char *pos;
2651
2652 pos = os_strchr(cmd, ' ');
2653 if (pos == NULL)
2654 return -1;
2655 *pos++ = '\0';
2656
2657 if (os_strcmp(cmd, "bonjour") == 0)
2658 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
2659 if (os_strcmp(cmd, "upnp") == 0)
2660 return p2p_ctrl_service_del_upnp(wpa_s, pos);
2661 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2662 return -1;
2663}
2664
2665
2666static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
2667{
2668 u8 addr[ETH_ALEN];
2669
2670 /* <addr> */
2671
2672 if (hwaddr_aton(cmd, addr))
2673 return -1;
2674
2675 return wpas_p2p_reject(wpa_s, addr);
2676}
2677
2678
2679static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
2680{
2681 char *pos;
2682 int id;
2683 struct wpa_ssid *ssid;
2684 u8 peer[ETH_ALEN];
2685
2686 id = atoi(cmd);
2687 pos = os_strstr(cmd, " peer=");
2688 if (pos) {
2689 pos += 6;
2690 if (hwaddr_aton(pos, peer))
2691 return -1;
2692 }
2693 ssid = wpa_config_get_network(wpa_s->conf, id);
2694 if (ssid == NULL || ssid->disabled != 2) {
2695 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2696 "for persistent P2P group",
2697 id);
2698 return -1;
2699 }
2700
2701 return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
2702}
2703
2704
2705static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
2706{
2707 char *pos;
2708 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
2709
2710 pos = os_strstr(cmd, " peer=");
2711 if (!pos)
2712 return -1;
2713
2714 *pos = '\0';
2715 pos += 6;
2716 if (hwaddr_aton(pos, peer)) {
2717 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
2718 return -1;
2719 }
2720
2721 pos = os_strstr(pos, " go_dev_addr=");
2722 if (pos) {
2723 pos += 13;
2724 if (hwaddr_aton(pos, go_dev_addr)) {
2725 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
2726 pos);
2727 return -1;
2728 }
2729 go_dev = go_dev_addr;
2730 }
2731
2732 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
2733}
2734
2735
2736static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
2737{
2738 if (os_strncmp(cmd, "persistent=", 11) == 0)
2739 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
2740 if (os_strncmp(cmd, "group=", 6) == 0)
2741 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
2742
2743 return -1;
2744}
2745
2746
2747static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
2748 char *cmd, int freq)
2749{
2750 int id;
2751 struct wpa_ssid *ssid;
2752
2753 id = atoi(cmd);
2754 ssid = wpa_config_get_network(wpa_s->conf, id);
2755 if (ssid == NULL || ssid->disabled != 2) {
2756 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2757 "for persistent P2P group",
2758 id);
2759 return -1;
2760 }
2761
2762 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
2763}
2764
2765
2766static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
2767{
2768 int freq = 0;
2769 char *pos;
2770
2771 pos = os_strstr(cmd, "freq=");
2772 if (pos)
2773 freq = atoi(pos + 5);
2774
2775 if (os_strncmp(cmd, "persistent=", 11) == 0)
2776 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
2777 if (os_strcmp(cmd, "persistent") == 0 ||
2778 os_strncmp(cmd, "persistent ", 11) == 0)
2779 return wpas_p2p_group_add(wpa_s, 1, freq);
2780 if (os_strncmp(cmd, "freq=", 5) == 0)
2781 return wpas_p2p_group_add(wpa_s, 0, freq);
2782
2783 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
2784 cmd);
2785 return -1;
2786}
2787
2788
2789static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
2790 char *buf, size_t buflen)
2791{
2792 u8 addr[ETH_ALEN], *addr_ptr;
2793 int next;
2794
2795 if (!wpa_s->global->p2p)
2796 return -1;
2797
2798 if (os_strcmp(cmd, "FIRST") == 0) {
2799 addr_ptr = NULL;
2800 next = 0;
2801 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2802 if (hwaddr_aton(cmd + 5, addr) < 0)
2803 return -1;
2804 addr_ptr = addr;
2805 next = 1;
2806 } else {
2807 if (hwaddr_aton(cmd, addr) < 0)
2808 return -1;
2809 addr_ptr = addr;
2810 next = 0;
2811 }
2812
2813 return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next,
2814 buf, buflen);
2815}
2816
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002817#ifdef ANDROID_BRCM_P2P_PATCH
2818struct wpa_supplicant* p2p_get_apif(struct wpa_supplicant* wpa_s)
2819{
2820 struct wpa_supplicant* iface;
2821 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
2822 if (iface->ap_iface)
2823 return iface;
2824 return wpa_s;
2825}
2826struct wpa_supplicant* p2p_get_clientif(struct wpa_supplicant* wpa_s)
2827{
2828 struct wpa_supplicant* iface;
2829 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
2830 if (iface->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
2831 return iface;
2832 return wpa_s;
2833}
2834#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835
2836static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
2837{
2838 char *param;
2839
2840 if (wpa_s->global->p2p == NULL)
2841 return -1;
2842
2843 param = os_strchr(cmd, ' ');
2844 if (param == NULL)
2845 return -1;
2846 *param++ = '\0';
2847
2848 if (os_strcmp(cmd, "discoverability") == 0) {
2849 p2p_set_client_discoverability(wpa_s->global->p2p,
2850 atoi(param));
2851 return 0;
2852 }
2853
2854 if (os_strcmp(cmd, "managed") == 0) {
2855 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
2856 return 0;
2857 }
2858
2859 if (os_strcmp(cmd, "listen_channel") == 0) {
2860 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
2861 atoi(param));
2862 }
2863
2864 if (os_strcmp(cmd, "ssid_postfix") == 0) {
2865 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
2866 os_strlen(param));
2867 }
2868
2869 if (os_strcmp(cmd, "noa") == 0) {
2870 char *pos;
2871 int count, start, duration;
2872 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
2873 count = atoi(param);
2874 pos = os_strchr(param, ',');
2875 if (pos == NULL)
2876 return -1;
2877 pos++;
2878 start = atoi(pos);
2879 pos = os_strchr(pos, ',');
2880 if (pos == NULL)
2881 return -1;
2882 pos++;
2883 duration = atoi(pos);
2884 if (count < 0 || count > 255 || start < 0 || duration < 0)
2885 return -1;
2886 if (count == 0 && duration > 0)
2887 return -1;
2888 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
2889 "start=%d duration=%d", count, start, duration);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002890#ifdef ANDROID_BRCM_P2P_PATCH
2891 return wpas_p2p_set_noa(p2p_get_apif(wpa_s), count, start, duration);
2892#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 return wpas_p2p_set_noa(wpa_s, count, start, duration);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002894#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002895 }
2896
2897 if (os_strcmp(cmd, "ps") == 0)
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002898#ifdef ANDROID_BRCM_P2P_PATCH
2899 return wpas_drv_set_p2p_powersave(p2p_get_clientif(wpa_s), atoi(param), -1, -1);
2900#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002901 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002902#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002903
2904 if (os_strcmp(cmd, "oppps") == 0)
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002905#ifdef ANDROID_BRCM_P2P_PATCH
2906 return wpas_drv_set_p2p_powersave(p2p_get_apif(wpa_s), -1, atoi(param), -1);
2907#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002909#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002910
2911 if (os_strcmp(cmd, "ctwindow") == 0)
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002912#ifdef ANDROID_BRCM_P2P_PATCH
2913 return wpa_drv_set_p2p_powersave(p2p_get_apif(wpa_s), -1, -1, atoi(param));
2914#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002915 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002916#endif
2917
2918 if (os_strcmp(cmd, "disabled") == 0) {
2919 wpa_s->global->p2p_disabled = atoi(param);
2920 wpa_printf(MSG_DEBUG, "P2P functionality %s",
2921 wpa_s->global->p2p_disabled ?
2922 "disabled" : "enabled");
2923 if (wpa_s->global->p2p_disabled) {
2924 wpas_p2p_stop_find(wpa_s);
2925 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2926 p2p_flush(wpa_s->global->p2p);
2927 }
2928 return 0;
2929 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002930
2931 if (os_strcmp(cmd, "disabled") == 0) {
2932 wpa_s->global->p2p_disabled = atoi(param);
2933 wpa_printf(MSG_DEBUG, "P2P functionality %s",
2934 wpa_s->global->p2p_disabled ?
2935 "disabled" : "enabled");
2936 if (wpa_s->global->p2p_disabled) {
2937 wpas_p2p_stop_find(wpa_s);
2938 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2939 p2p_flush(wpa_s->global->p2p);
2940 }
2941 return 0;
2942 }
2943
2944 if (os_strcmp(cmd, "force_long_sd") == 0) {
2945 wpa_s->force_long_sd = atoi(param);
2946 return 0;
2947 }
2948
2949 if (os_strcmp(cmd, "peer_filter") == 0) {
2950 u8 addr[ETH_ALEN];
2951 if (hwaddr_aton(param, addr))
2952 return -1;
2953 p2p_set_peer_filter(wpa_s->global->p2p, addr);
2954 return 0;
2955 }
2956
2957 if (os_strcmp(cmd, "cross_connect") == 0)
2958 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
2959
2960 if (os_strcmp(cmd, "go_apsd") == 0) {
2961 if (os_strcmp(param, "disable") == 0)
2962 wpa_s->set_ap_uapsd = 0;
2963 else {
2964 wpa_s->set_ap_uapsd = 1;
2965 wpa_s->ap_uapsd = atoi(param);
2966 }
2967 return 0;
2968 }
2969
2970 if (os_strcmp(cmd, "client_apsd") == 0) {
2971 if (os_strcmp(param, "disable") == 0)
2972 wpa_s->set_sta_uapsd = 0;
2973 else {
2974 int be, bk, vi, vo;
2975 char *pos;
2976 /* format: BE,BK,VI,VO;max SP Length */
2977 be = atoi(param);
2978 pos = os_strchr(param, ',');
2979 if (pos == NULL)
2980 return -1;
2981 pos++;
2982 bk = atoi(pos);
2983 pos = os_strchr(pos, ',');
2984 if (pos == NULL)
2985 return -1;
2986 pos++;
2987 vi = atoi(pos);
2988 pos = os_strchr(pos, ',');
2989 if (pos == NULL)
2990 return -1;
2991 pos++;
2992 vo = atoi(pos);
2993 /* ignore max SP Length for now */
2994
2995 wpa_s->set_sta_uapsd = 1;
2996 wpa_s->sta_uapsd = 0;
2997 if (be)
2998 wpa_s->sta_uapsd |= BIT(0);
2999 if (bk)
3000 wpa_s->sta_uapsd |= BIT(1);
3001 if (vi)
3002 wpa_s->sta_uapsd |= BIT(2);
3003 if (vo)
3004 wpa_s->sta_uapsd |= BIT(3);
3005 }
3006 return 0;
3007 }
3008
3009 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
3010 cmd);
3011
3012 return -1;
3013}
3014
3015
3016static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
3017{
3018 char *pos, *pos2;
3019 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
3020
3021 if (cmd[0]) {
3022 pos = os_strchr(cmd, ' ');
3023 if (pos == NULL)
3024 return -1;
3025 *pos++ = '\0';
3026 dur1 = atoi(cmd);
3027
3028 pos2 = os_strchr(pos, ' ');
3029 if (pos2)
3030 *pos2++ = '\0';
3031 int1 = atoi(pos);
3032 } else
3033 pos2 = NULL;
3034
3035 if (pos2) {
3036 pos = os_strchr(pos2, ' ');
3037 if (pos == NULL)
3038 return -1;
3039 *pos++ = '\0';
3040 dur2 = atoi(pos2);
3041 int2 = atoi(pos);
3042 }
3043
3044 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
3045}
3046
3047
3048static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
3049{
3050 char *pos;
3051 unsigned int period = 0, interval = 0;
3052
3053 if (cmd[0]) {
3054 pos = os_strchr(cmd, ' ');
3055 if (pos == NULL)
3056 return -1;
3057 *pos++ = '\0';
3058 period = atoi(cmd);
3059 interval = atoi(pos);
3060 }
3061
3062 return wpas_p2p_ext_listen(wpa_s, period, interval);
3063}
3064
3065#endif /* CONFIG_P2P */
3066
3067
3068static int wpa_supplicant_ctrl_iface_sta_autoconnect(
3069 struct wpa_supplicant *wpa_s, char *cmd)
3070{
3071 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
3072 return 0;
3073}
3074
3075
3076static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
3077 size_t buflen)
3078{
3079 struct wpa_signal_info si;
3080 int ret;
3081
3082 ret = wpa_drv_signal_poll(wpa_s, &si);
3083 if (ret)
3084 return -1;
3085
3086 ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
3087 "NOISE=%d\nFREQUENCY=%u\n",
3088 si.current_signal, si.current_txrate / 1000,
3089 si.current_noise, si.frequency);
3090 if (ret < 0 || (unsigned int) ret > buflen)
3091 return -1;
3092 return ret;
3093}
3094
3095
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07003096static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
3097 char *buf, size_t buflen)
3098{
3099 int ret;
3100
3101 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
3102 if (ret == 0)
3103 ret = sprintf(buf, "%s\n", "OK");
3104 return ret;
3105}
3106
3107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003108char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
3109 char *buf, size_t *resp_len)
3110{
3111 char *reply;
3112 const int reply_size = 4096;
3113 int ctrl_rsp = 0;
3114 int reply_len;
3115
3116 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
3117 os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3118 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
3119 (const u8 *) buf, os_strlen(buf));
3120 } else {
3121 int level = MSG_DEBUG;
3122 if (os_strcmp(buf, "PING") == 0)
3123 level = MSG_EXCESSIVE;
3124 wpa_hexdump_ascii(level, "RX ctrl_iface",
3125 (const u8 *) buf, os_strlen(buf));
3126 }
3127
3128 reply = os_malloc(reply_size);
3129 if (reply == NULL) {
3130 *resp_len = 1;
3131 return NULL;
3132 }
3133
3134 os_memcpy(reply, "OK\n", 3);
3135 reply_len = 3;
3136
3137 if (os_strcmp(buf, "PING") == 0) {
3138 os_memcpy(reply, "PONG\n", 5);
3139 reply_len = 5;
3140 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
3141 if (wpa_debug_reopen_file() < 0)
3142 reply_len = -1;
3143 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
3144 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
3145 } else if (os_strcmp(buf, "MIB") == 0) {
3146 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
3147 if (reply_len >= 0) {
3148 int res;
3149 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
3150 reply_size - reply_len);
3151 if (res < 0)
3152 reply_len = -1;
3153 else
3154 reply_len += res;
3155 }
3156 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
3157 reply_len = wpa_supplicant_ctrl_iface_status(
3158 wpa_s, buf + 6, reply, reply_size);
3159 } else if (os_strcmp(buf, "PMKSA") == 0) {
3160 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
3161 reply_size);
3162 } else if (os_strncmp(buf, "SET ", 4) == 0) {
3163 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
3164 reply_len = -1;
3165 } else if (os_strncmp(buf, "GET ", 4) == 0) {
3166 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
3167 reply, reply_size);
3168 } else if (os_strcmp(buf, "LOGON") == 0) {
3169 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
3170 } else if (os_strcmp(buf, "LOGOFF") == 0) {
3171 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
3172 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
3173 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3174 reply_len = -1;
3175 else {
3176 wpa_s->disconnected = 0;
3177 wpa_s->reassociate = 1;
3178 wpa_supplicant_req_scan(wpa_s, 0, 0);
3179 }
3180 } else if (os_strcmp(buf, "RECONNECT") == 0) {
3181 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3182 reply_len = -1;
3183 else if (wpa_s->disconnected) {
3184 wpa_s->disconnected = 0;
3185 wpa_s->reassociate = 1;
3186 wpa_supplicant_req_scan(wpa_s, 0, 0);
3187 }
3188#ifdef IEEE8021X_EAPOL
3189 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
3190 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
3191 reply_len = -1;
3192#endif /* IEEE8021X_EAPOL */
3193#ifdef CONFIG_PEERKEY
3194 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
3195 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
3196 reply_len = -1;
3197#endif /* CONFIG_PEERKEY */
3198#ifdef CONFIG_IEEE80211R
3199 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
3200 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
3201 reply_len = -1;
3202#endif /* CONFIG_IEEE80211R */
3203#ifdef CONFIG_WPS
3204 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
3205 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
3206 if (res == -2) {
3207 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3208 reply_len = 17;
3209 } else if (res)
3210 reply_len = -1;
3211 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
3212 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
3213 if (res == -2) {
3214 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3215 reply_len = 17;
3216 } else if (res)
3217 reply_len = -1;
3218 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
3219 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
3220 reply,
3221 reply_size);
3222 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
3223 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
3224 wpa_s, buf + 14, reply, reply_size);
3225 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
3226 if (wpas_wps_cancel(wpa_s))
3227 reply_len = -1;
3228#ifdef CONFIG_WPS_OOB
3229 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
3230 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
3231 reply_len = -1;
3232#endif /* CONFIG_WPS_OOB */
3233 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
3234 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
3235 reply_len = -1;
3236#ifdef CONFIG_AP
3237 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
3238 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
3239 wpa_s, buf + 11, reply, reply_size);
3240#endif /* CONFIG_AP */
3241#ifdef CONFIG_WPS_ER
3242 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
3243 if (wpas_wps_er_start(wpa_s, NULL))
3244 reply_len = -1;
3245 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
3246 if (wpas_wps_er_start(wpa_s, buf + 13))
3247 reply_len = -1;
3248 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
3249 if (wpas_wps_er_stop(wpa_s))
3250 reply_len = -1;
3251 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
3252 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
3253 reply_len = -1;
3254 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
3255 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
3256 if (ret == -2) {
3257 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3258 reply_len = 17;
3259 } else if (ret == -3) {
3260 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
3261 reply_len = 18;
3262 } else if (ret == -4) {
3263 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
3264 reply_len = 20;
3265 } else if (ret)
3266 reply_len = -1;
3267 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
3268 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
3269 reply_len = -1;
3270 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
3271 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
3272 buf + 18))
3273 reply_len = -1;
3274 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
3275 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
3276 reply_len = -1;
3277#endif /* CONFIG_WPS_ER */
3278#endif /* CONFIG_WPS */
3279#ifdef CONFIG_IBSS_RSN
3280 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
3281 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
3282 reply_len = -1;
3283#endif /* CONFIG_IBSS_RSN */
3284#ifdef CONFIG_P2P
3285 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
3286 if (p2p_ctrl_find(wpa_s, buf + 9))
3287 reply_len = -1;
3288 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
3289 if (p2p_ctrl_find(wpa_s, ""))
3290 reply_len = -1;
3291 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
3292 wpas_p2p_stop_find(wpa_s);
3293 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
3294 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
3295 reply_size);
3296 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
3297 if (p2p_ctrl_listen(wpa_s, buf + 11))
3298 reply_len = -1;
3299 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
3300 if (p2p_ctrl_listen(wpa_s, ""))
3301 reply_len = -1;
3302 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
3303 if (wpas_p2p_group_remove(wpa_s, buf + 17))
3304 reply_len = -1;
3305 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
3306 if (wpas_p2p_group_add(wpa_s, 0, 0))
3307 reply_len = -1;
3308 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
3309 if (p2p_ctrl_group_add(wpa_s, buf + 14))
3310 reply_len = -1;
3311 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
3312 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
3313 reply_len = -1;
3314 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
3315 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
3316 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
3317 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
3318 reply_size);
3319 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
3320 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
3321 reply_len = -1;
3322 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
3323 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
3324 reply_len = -1;
3325 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
3326 wpas_p2p_sd_service_update(wpa_s);
3327 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
3328 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
3329 reply_len = -1;
3330 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
3331 wpas_p2p_service_flush(wpa_s);
3332 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
3333 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
3334 reply_len = -1;
3335 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
3336 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
3337 reply_len = -1;
3338 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
3339 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
3340 reply_len = -1;
3341 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
3342 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
3343 reply_len = -1;
3344 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
3345 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
3346 reply_size);
3347 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
3348 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
3349 reply_len = -1;
3350 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
3351 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
3352 wpa_s->force_long_sd = 0;
3353 if (wpa_s->global->p2p)
3354 p2p_flush(wpa_s->global->p2p);
3355 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
3356 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
3357 reply_len = -1;
3358 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
3359 if (wpas_p2p_cancel(wpa_s))
3360 reply_len = -1;
3361 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07003362 #if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
3363 /* We have to send presence command to p2p interface if p2p_interface is started
3364 * otherwise we can send it to primary interface
3365 */
3366 struct wpa_supplicant* ifs;
3367 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3368 if ( (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO ) ||(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT )) {
3369 wpa_s = ifs;
3370 break;
3371 }
3372 }
3373 #endif /* defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
3375 reply_len = -1;
3376 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
3377 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
3378 reply_len = -1;
3379 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
3380 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
3381 reply_len = -1;
3382 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
3383 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
3384 reply_len = -1;
3385#endif /* CONFIG_P2P */
3386 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
3387 {
3388 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
3389 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
3390 reply_len = -1;
3391 else
3392 ctrl_rsp = 1;
3393 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
3394 if (wpa_supplicant_reload_configuration(wpa_s))
3395 reply_len = -1;
3396 } else if (os_strcmp(buf, "TERMINATE") == 0) {
3397 wpa_supplicant_terminate_proc(wpa_s->global);
3398 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
3399 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
3400 reply_len = -1;
Dmitry Shmidt657a7042011-03-16 14:57:39 -07003401 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
3402 reply_len = wpa_supplicant_ctrl_iface_log_level(wpa_s, buf + 9,
3403 reply, reply_size);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07003404 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
3405 reply_len = wpa_supplicant_ctrl_iface_blacklist(wpa_s, buf + 9,
3406 reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003407 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
3408 reply_len = wpa_supplicant_ctrl_iface_list_networks(
3409 wpa_s, reply, reply_size);
3410 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
3411 wpa_s->reassociate = 0;
3412 wpa_s->disconnected = 1;
3413 wpa_supplicant_deauthenticate(wpa_s,
3414 WLAN_REASON_DEAUTH_LEAVING);
3415 } else if (os_strcmp(buf, "SCAN") == 0) {
3416 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3417 reply_len = -1;
3418 else {
3419 if (!wpa_s->scanning &&
3420 ((wpa_s->wpa_state <= WPA_SCANNING) ||
3421 (wpa_s->wpa_state == WPA_COMPLETED))) {
3422 wpa_s->scan_req = 2;
3423 wpa_supplicant_req_scan(wpa_s, 0, 0);
3424 } else {
3425 wpa_printf(MSG_DEBUG, "Ongoing scan action - "
3426 "reject new request");
3427 reply_len = os_snprintf(reply, reply_size,
3428 "FAIL-BUSY\n");
3429 }
3430 }
3431 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
3432 reply_len = wpa_supplicant_ctrl_iface_scan_results(
3433 wpa_s, reply, reply_size);
3434 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
3435 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
3436 reply_len = -1;
3437 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
3438 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
3439 reply_len = -1;
3440 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
3441 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
3442 reply_len = -1;
3443 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
3444 reply_len = wpa_supplicant_ctrl_iface_add_network(
3445 wpa_s, reply, reply_size);
3446 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
3447 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
3448 reply_len = -1;
3449 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3450 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
3451 reply_len = -1;
3452 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
3453 reply_len = wpa_supplicant_ctrl_iface_get_network(
3454 wpa_s, buf + 12, reply, reply_size);
3455#ifndef CONFIG_NO_CONFIG_WRITE
3456 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
3457 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
3458 reply_len = -1;
3459#endif /* CONFIG_NO_CONFIG_WRITE */
3460 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
3461 reply_len = wpa_supplicant_ctrl_iface_get_capability(
3462 wpa_s, buf + 15, reply, reply_size);
3463 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
3464 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
3465 reply_len = -1;
3466 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
3467 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
3468 reply_len = -1;
3469 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3470 reply_len = wpa_supplicant_global_iface_list(
3471 wpa_s->global, reply, reply_size);
3472 } else if (os_strcmp(buf, "INTERFACES") == 0) {
3473 reply_len = wpa_supplicant_global_iface_interfaces(
3474 wpa_s->global, reply, reply_size);
3475 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
3476 reply_len = wpa_supplicant_ctrl_iface_bss(
3477 wpa_s, buf + 4, reply, reply_size);
3478#ifdef CONFIG_AP
3479 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
3480 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
3481 } else if (os_strncmp(buf, "STA ", 4) == 0) {
3482 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
3483 reply_size);
3484 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
3485 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
3486 reply_size);
3487#endif /* CONFIG_AP */
3488 } else if (os_strcmp(buf, "SUSPEND") == 0) {
3489 wpas_notify_suspend(wpa_s->global);
3490 } else if (os_strcmp(buf, "RESUME") == 0) {
3491 wpas_notify_resume(wpa_s->global);
3492 } else if (os_strcmp(buf, "DROP_SA") == 0) {
3493 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
3494 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
3495 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
3496 reply_len = -1;
3497 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
3498 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
3499 reply_len = -1;
3500 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
3501 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
3502 reply_len = -1;
3503 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
3504 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
3505 buf + 17))
3506 reply_len = -1;
3507#ifdef CONFIG_TDLS
3508 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
3509 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
3510 reply_len = -1;
3511 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
3512 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
3513 reply_len = -1;
3514 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
3515 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
3516 reply_len = -1;
3517#endif /* CONFIG_TDLS */
3518 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
3519 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
3520 reply_size);
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07003521 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
3522 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
3523 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003524 } else {
3525 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3526 reply_len = 16;
3527 }
3528
3529 if (reply_len < 0) {
3530 os_memcpy(reply, "FAIL\n", 5);
3531 reply_len = 5;
3532 }
3533
3534 if (ctrl_rsp)
3535 eapol_sm_notify_ctrl_response(wpa_s->eapol);
3536
3537 *resp_len = reply_len;
3538 return reply;
3539}
3540
3541
3542static int wpa_supplicant_global_iface_add(struct wpa_global *global,
3543 char *cmd)
3544{
3545 struct wpa_interface iface;
3546 char *pos;
3547
3548 /*
3549 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
3550 * TAB<bridge_ifname>
3551 */
3552 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
3553
3554 os_memset(&iface, 0, sizeof(iface));
3555
3556 do {
3557 iface.ifname = pos = cmd;
3558 pos = os_strchr(pos, '\t');
3559 if (pos)
3560 *pos++ = '\0';
3561 if (iface.ifname[0] == '\0')
3562 return -1;
3563 if (pos == NULL)
3564 break;
3565
3566 iface.confname = pos;
3567 pos = os_strchr(pos, '\t');
3568 if (pos)
3569 *pos++ = '\0';
3570 if (iface.confname[0] == '\0')
3571 iface.confname = NULL;
3572 if (pos == NULL)
3573 break;
3574
3575 iface.driver = pos;
3576 pos = os_strchr(pos, '\t');
3577 if (pos)
3578 *pos++ = '\0';
3579 if (iface.driver[0] == '\0')
3580 iface.driver = NULL;
3581 if (pos == NULL)
3582 break;
3583
3584 iface.ctrl_interface = pos;
3585 pos = os_strchr(pos, '\t');
3586 if (pos)
3587 *pos++ = '\0';
3588 if (iface.ctrl_interface[0] == '\0')
3589 iface.ctrl_interface = NULL;
3590 if (pos == NULL)
3591 break;
3592
3593 iface.driver_param = pos;
3594 pos = os_strchr(pos, '\t');
3595 if (pos)
3596 *pos++ = '\0';
3597 if (iface.driver_param[0] == '\0')
3598 iface.driver_param = NULL;
3599 if (pos == NULL)
3600 break;
3601
3602 iface.bridge_ifname = pos;
3603 pos = os_strchr(pos, '\t');
3604 if (pos)
3605 *pos++ = '\0';
3606 if (iface.bridge_ifname[0] == '\0')
3607 iface.bridge_ifname = NULL;
3608 if (pos == NULL)
3609 break;
3610 } while (0);
3611
3612 if (wpa_supplicant_get_iface(global, iface.ifname))
3613 return -1;
3614
3615 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
3616}
3617
3618
3619static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
3620 char *cmd)
3621{
3622 struct wpa_supplicant *wpa_s;
3623
3624 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
3625
3626 wpa_s = wpa_supplicant_get_iface(global, cmd);
3627 if (wpa_s == NULL)
3628 return -1;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003629 return wpa_supplicant_remove_iface(global, wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003630}
3631
3632
3633static void wpa_free_iface_info(struct wpa_interface_info *iface)
3634{
3635 struct wpa_interface_info *prev;
3636
3637 while (iface) {
3638 prev = iface;
3639 iface = iface->next;
3640
3641 os_free(prev->ifname);
3642 os_free(prev->desc);
3643 os_free(prev);
3644 }
3645}
3646
3647
3648static int wpa_supplicant_global_iface_list(struct wpa_global *global,
3649 char *buf, int len)
3650{
3651 int i, res;
3652 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
3653 char *pos, *end;
3654
3655 for (i = 0; wpa_drivers[i]; i++) {
3656 struct wpa_driver_ops *drv = wpa_drivers[i];
3657 if (drv->get_interfaces == NULL)
3658 continue;
3659 tmp = drv->get_interfaces(global->drv_priv[i]);
3660 if (tmp == NULL)
3661 continue;
3662
3663 if (last == NULL)
3664 iface = last = tmp;
3665 else
3666 last->next = tmp;
3667 while (last->next)
3668 last = last->next;
3669 }
3670
3671 pos = buf;
3672 end = buf + len;
3673 for (tmp = iface; tmp; tmp = tmp->next) {
3674 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
3675 tmp->drv_name, tmp->ifname,
3676 tmp->desc ? tmp->desc : "");
3677 if (res < 0 || res >= end - pos) {
3678 *pos = '\0';
3679 break;
3680 }
3681 pos += res;
3682 }
3683
3684 wpa_free_iface_info(iface);
3685
3686 return pos - buf;
3687}
3688
3689
3690static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
3691 char *buf, int len)
3692{
3693 int res;
3694 char *pos, *end;
3695 struct wpa_supplicant *wpa_s;
3696
3697 wpa_s = global->ifaces;
3698 pos = buf;
3699 end = buf + len;
3700
3701 while (wpa_s) {
3702 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
3703 if (res < 0 || res >= end - pos) {
3704 *pos = '\0';
3705 break;
3706 }
3707 pos += res;
3708 wpa_s = wpa_s->next;
3709 }
3710 return pos - buf;
3711}
3712
3713
3714char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
3715 char *buf, size_t *resp_len)
3716{
3717 char *reply;
3718 const int reply_size = 2048;
3719 int reply_len;
3720
3721 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
3722 (const u8 *) buf, os_strlen(buf));
3723
3724 reply = os_malloc(reply_size);
3725 if (reply == NULL) {
3726 *resp_len = 1;
3727 return NULL;
3728 }
3729
3730 os_memcpy(reply, "OK\n", 3);
3731 reply_len = 3;
3732
3733 if (os_strcmp(buf, "PING") == 0) {
3734 os_memcpy(reply, "PONG\n", 5);
3735 reply_len = 5;
3736 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
3737 if (wpa_supplicant_global_iface_add(global, buf + 14))
3738 reply_len = -1;
3739 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
3740 if (wpa_supplicant_global_iface_remove(global, buf + 17))
3741 reply_len = -1;
3742 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3743 reply_len = wpa_supplicant_global_iface_list(
3744 global, reply, reply_size);
3745 } else if (os_strcmp(buf, "INTERFACES") == 0) {
3746 reply_len = wpa_supplicant_global_iface_interfaces(
3747 global, reply, reply_size);
3748 } else if (os_strcmp(buf, "TERMINATE") == 0) {
3749 wpa_supplicant_terminate_proc(global);
3750 } else if (os_strcmp(buf, "SUSPEND") == 0) {
3751 wpas_notify_suspend(global);
3752 } else if (os_strcmp(buf, "RESUME") == 0) {
3753 wpas_notify_resume(global);
3754 } else {
3755 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3756 reply_len = 16;
3757 }
3758
3759 if (reply_len < 0) {
3760 os_memcpy(reply, "FAIL\n", 5);
3761 reply_len = 5;
3762 }
3763
3764 *resp_len = reply_len;
3765 return reply;
3766}