blob: c8a77e2526d828681b458211b9b14a21b63acbe9 [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
Dmitry Shmidt2fd7fa62011-12-19 11:19:09 -0800926#ifdef ANDROID
927 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
928 "id=%d state=%d BSSID=" MACSTR,
929 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
930 wpa_s->wpa_state, MAC2STR(wpa_s->pending_bssid));
931#endif /* ANDROID */
932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933 return pos - buf;
934}
935
936
937static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
938 char *cmd)
939{
940 char *pos;
941 int id;
942 struct wpa_ssid *ssid;
943 u8 bssid[ETH_ALEN];
944
945 /* cmd: "<network id> <BSSID>" */
946 pos = os_strchr(cmd, ' ');
947 if (pos == NULL)
948 return -1;
949 *pos++ = '\0';
950 id = atoi(cmd);
951 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
952 if (hwaddr_aton(pos, bssid)) {
953 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
954 return -1;
955 }
956
957 ssid = wpa_config_get_network(wpa_s->conf, id);
958 if (ssid == NULL) {
959 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
960 "to update", id);
961 return -1;
962 }
963
964 os_memcpy(ssid->bssid, bssid, ETH_ALEN);
965 ssid->bssid_set = !is_zero_ether_addr(bssid);
966
967 return 0;
968}
969
970
Dmitry Shmidt657a7042011-03-16 14:57:39 -0700971extern int wpa_debug_level;
972extern int wpa_debug_timestamp;
973
974static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
975 char *cmd, char *buf, size_t buflen)
976{
977 char *pos, *end, *stamp;
978 int ret;
979
980 if (cmd == NULL)
981 return -1;
982 /* cmd: "LOG_LEVEL [<level>]" */
983 if (*cmd == '\0') {
984 pos = buf;
985 end = buf + buflen;
986 ret = os_snprintf(pos, end-pos, "Current level: %d\n"
987 "{0-EXCESSIVE, 1-MSGDUMP, 2-DEBUG, 3-INFO, 4-WARNING, 5-ERROR}\n"
988 "Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp);
989 if ((ret < 0) || (ret >= end - pos))
990 ret = 0;
991 return ret;
992 }
993
994 cmd++;
995 stamp = os_strchr(cmd, ' ');
996 if (stamp) {
997 *stamp++ = '\0';
998 while (*stamp == ' ')
999 stamp++;
1000 }
1001
1002 if (cmd && os_strlen(cmd))
1003 wpa_debug_level = atoi(cmd);
1004
1005 if (stamp && os_strlen(stamp))
1006 wpa_debug_timestamp = atoi(stamp);
1007
1008 os_memcpy(buf, "OK\n", 3);
1009 return 3;
1010}
1011
1012
Dmitry Shmidte19501d2011-03-16 14:32:18 -07001013static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1014 char *cmd, char *buf, size_t buflen)
1015{
1016 u8 bssid[ETH_ALEN];
1017 struct wpa_blacklist *e;
1018 char *pos, *end;
1019 int ret;
1020
1021 /* cmd: "BLACKLIST [<BSSID>]" */
1022 if (*cmd == '\0') {
1023 pos = buf;
1024 end = buf + buflen;
1025 e = wpa_s->blacklist;
1026 while (e) {
1027 ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid));
1028 if ((ret < 0) || (ret >= end - pos))
1029 return pos - buf;
1030 pos += ret;
1031 e = e->next;
1032 }
1033 return pos - buf;
1034 }
1035
1036 cmd++;
1037 if (os_strncmp(cmd, "clear", 5) == 0) {
1038 wpa_blacklist_clear(wpa_s);
1039 os_memcpy(buf, "OK\n", 3);
1040 return 3;
1041 }
1042
1043 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1044 if (hwaddr_aton(cmd, bssid)) {
1045 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd);
1046 return -1;
1047 }
1048
1049 /* Add the BSSID twice, so its count will be 2, causing it to be
1050 skipped when processing scan results. */
1051 ret = wpa_blacklist_add(wpa_s, bssid);
1052 if (ret < 0)
1053 return -1;
1054 ret = wpa_blacklist_add(wpa_s, bssid);
1055 if (ret < 0)
1056 return -1;
1057 os_memcpy(buf, "OK\n", 3);
1058 return 3;
1059}
1060
1061
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062static int wpa_supplicant_ctrl_iface_list_networks(
1063 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1064{
1065 char *pos, *end;
1066 struct wpa_ssid *ssid;
1067 int ret;
1068
1069 pos = buf;
1070 end = buf + buflen;
1071 ret = os_snprintf(pos, end - pos,
1072 "network id / ssid / bssid / flags\n");
1073 if (ret < 0 || ret >= end - pos)
1074 return pos - buf;
1075 pos += ret;
1076
1077 ssid = wpa_s->conf->ssid;
1078 while (ssid) {
1079 ret = os_snprintf(pos, end - pos, "%d\t%s",
1080 ssid->id,
1081 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1082 if (ret < 0 || ret >= end - pos)
1083 return pos - buf;
1084 pos += ret;
1085 if (ssid->bssid_set) {
1086 ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1087 MAC2STR(ssid->bssid));
1088 } else {
1089 ret = os_snprintf(pos, end - pos, "\tany");
1090 }
1091 if (ret < 0 || ret >= end - pos)
1092 return pos - buf;
1093 pos += ret;
1094 ret = os_snprintf(pos, end - pos, "\t%s%s%s",
1095 ssid == wpa_s->current_ssid ?
1096 "[CURRENT]" : "",
1097 ssid->disabled ? "[DISABLED]" : "",
1098 ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1099 "");
1100 if (ret < 0 || ret >= end - pos)
1101 return pos - buf;
1102 pos += ret;
1103 ret = os_snprintf(pos, end - pos, "\n");
1104 if (ret < 0 || ret >= end - pos)
1105 return pos - buf;
1106 pos += ret;
1107
1108 ssid = ssid->next;
1109 }
1110
1111 return pos - buf;
1112}
1113
1114
1115static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1116{
1117 int first = 1, ret;
1118 ret = os_snprintf(pos, end - pos, "-");
1119 if (ret < 0 || ret >= end - pos)
1120 return pos;
1121 pos += ret;
1122 if (cipher & WPA_CIPHER_NONE) {
1123 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
1124 if (ret < 0 || ret >= end - pos)
1125 return pos;
1126 pos += ret;
1127 first = 0;
1128 }
1129 if (cipher & WPA_CIPHER_WEP40) {
1130 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
1131 if (ret < 0 || ret >= end - pos)
1132 return pos;
1133 pos += ret;
1134 first = 0;
1135 }
1136 if (cipher & WPA_CIPHER_WEP104) {
1137 ret = os_snprintf(pos, end - pos, "%sWEP104",
1138 first ? "" : "+");
1139 if (ret < 0 || ret >= end - pos)
1140 return pos;
1141 pos += ret;
1142 first = 0;
1143 }
1144 if (cipher & WPA_CIPHER_TKIP) {
1145 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
1146 if (ret < 0 || ret >= end - pos)
1147 return pos;
1148 pos += ret;
1149 first = 0;
1150 }
1151 if (cipher & WPA_CIPHER_CCMP) {
1152 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
1153 if (ret < 0 || ret >= end - pos)
1154 return pos;
1155 pos += ret;
1156 first = 0;
1157 }
1158 return pos;
1159}
1160
1161
1162static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1163 const u8 *ie, size_t ie_len)
1164{
1165 struct wpa_ie_data data;
1166 int first, ret;
1167
1168 ret = os_snprintf(pos, end - pos, "[%s-", proto);
1169 if (ret < 0 || ret >= end - pos)
1170 return pos;
1171 pos += ret;
1172
1173 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1174 ret = os_snprintf(pos, end - pos, "?]");
1175 if (ret < 0 || ret >= end - pos)
1176 return pos;
1177 pos += ret;
1178 return pos;
1179 }
1180
1181 first = 1;
1182 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1183 ret = os_snprintf(pos, end - pos, "%sEAP", 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_PSK) {
1190 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1191 if (ret < 0 || ret >= end - pos)
1192 return pos;
1193 pos += ret;
1194 first = 0;
1195 }
1196 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1197 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1198 if (ret < 0 || ret >= end - pos)
1199 return pos;
1200 pos += ret;
1201 first = 0;
1202 }
1203#ifdef CONFIG_IEEE80211R
1204 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1205 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1206 first ? "" : "+");
1207 if (ret < 0 || ret >= end - pos)
1208 return pos;
1209 pos += ret;
1210 first = 0;
1211 }
1212 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1213 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1214 first ? "" : "+");
1215 if (ret < 0 || ret >= end - pos)
1216 return pos;
1217 pos += ret;
1218 first = 0;
1219 }
1220#endif /* CONFIG_IEEE80211R */
1221#ifdef CONFIG_IEEE80211W
1222 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1223 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1224 first ? "" : "+");
1225 if (ret < 0 || ret >= end - pos)
1226 return pos;
1227 pos += ret;
1228 first = 0;
1229 }
1230 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1231 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1232 first ? "" : "+");
1233 if (ret < 0 || ret >= end - pos)
1234 return pos;
1235 pos += ret;
1236 first = 0;
1237 }
1238#endif /* CONFIG_IEEE80211W */
1239
1240 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1241
1242 if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1243 ret = os_snprintf(pos, end - pos, "-preauth");
1244 if (ret < 0 || ret >= end - pos)
1245 return pos;
1246 pos += ret;
1247 }
1248
1249 ret = os_snprintf(pos, end - pos, "]");
1250 if (ret < 0 || ret >= end - pos)
1251 return pos;
1252 pos += ret;
1253
1254 return pos;
1255}
1256
1257
1258#ifdef CONFIG_WPS
1259static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1260 char *pos, char *end,
1261 struct wpabuf *wps_ie)
1262{
1263 int ret;
1264 const char *txt;
1265
1266 if (wps_ie == NULL)
1267 return pos;
1268 if (wps_is_selected_pbc_registrar(wps_ie))
1269 txt = "[WPS-PBC]";
1270#ifdef CONFIG_WPS2
1271 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1272 txt = "[WPS-AUTH]";
1273#endif /* CONFIG_WPS2 */
1274 else if (wps_is_selected_pin_registrar(wps_ie))
1275 txt = "[WPS-PIN]";
1276 else
1277 txt = "[WPS]";
1278
1279 ret = os_snprintf(pos, end - pos, "%s", txt);
1280 if (ret >= 0 && ret < end - pos)
1281 pos += ret;
1282 wpabuf_free(wps_ie);
1283 return pos;
1284}
1285#endif /* CONFIG_WPS */
1286
1287
1288static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1289 char *pos, char *end,
1290 const struct wpa_bss *bss)
1291{
1292#ifdef CONFIG_WPS
1293 struct wpabuf *wps_ie;
1294 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1295 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1296#else /* CONFIG_WPS */
1297 return pos;
1298#endif /* CONFIG_WPS */
1299}
1300
1301
1302/* Format one result on one text line into a buffer. */
1303static int wpa_supplicant_ctrl_iface_scan_result(
1304 struct wpa_supplicant *wpa_s,
1305 const struct wpa_bss *bss, char *buf, size_t buflen)
1306{
1307 char *pos, *end;
1308 int ret;
1309 const u8 *ie, *ie2, *p2p;
1310
1311 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
1312 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
1313 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
1314 0)
1315 return 0; /* Do not show P2P listen discovery results here */
1316
1317 pos = buf;
1318 end = buf + buflen;
1319
1320 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1321 MAC2STR(bss->bssid), bss->freq, bss->level);
1322 if (ret < 0 || ret >= end - pos)
1323 return -1;
1324 pos += ret;
1325 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1326 if (ie)
1327 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1328 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1329 if (ie2)
1330 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1331 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1332 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1333 ret = os_snprintf(pos, end - pos, "[WEP]");
1334 if (ret < 0 || ret >= end - pos)
1335 return -1;
1336 pos += ret;
1337 }
1338 if (bss->caps & IEEE80211_CAP_IBSS) {
1339 ret = os_snprintf(pos, end - pos, "[IBSS]");
1340 if (ret < 0 || ret >= end - pos)
1341 return -1;
1342 pos += ret;
1343 }
1344 if (bss->caps & IEEE80211_CAP_ESS) {
1345 ret = os_snprintf(pos, end - pos, "[ESS]");
1346 if (ret < 0 || ret >= end - pos)
1347 return -1;
1348 pos += ret;
1349 }
1350 if (p2p) {
1351 ret = os_snprintf(pos, end - pos, "[P2P]");
1352 if (ret < 0 || ret >= end - pos)
1353 return -1;
1354 pos += ret;
1355 }
1356
1357 ret = os_snprintf(pos, end - pos, "\t%s",
1358 wpa_ssid_txt(bss->ssid, bss->ssid_len));
1359 if (ret < 0 || ret >= end - pos)
1360 return -1;
1361 pos += ret;
1362
1363 ret = os_snprintf(pos, end - pos, "\n");
1364 if (ret < 0 || ret >= end - pos)
1365 return -1;
1366 pos += ret;
1367
1368 return pos - buf;
1369}
1370
1371
1372static int wpa_supplicant_ctrl_iface_scan_results(
1373 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1374{
1375 char *pos, *end;
1376 struct wpa_bss *bss;
1377 int ret;
1378
1379 pos = buf;
1380 end = buf + buflen;
1381 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
1382 "flags / ssid\n");
1383 if (ret < 0 || ret >= end - pos)
1384 return pos - buf;
1385 pos += ret;
1386
1387 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1388 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
1389 end - pos);
1390 if (ret < 0 || ret >= end - pos)
1391 return pos - buf;
1392 pos += ret;
1393 }
1394
1395 return pos - buf;
1396}
1397
1398
1399static int wpa_supplicant_ctrl_iface_select_network(
1400 struct wpa_supplicant *wpa_s, char *cmd)
1401{
1402 int id;
1403 struct wpa_ssid *ssid;
1404
1405 /* cmd: "<network id>" or "any" */
1406 if (os_strcmp(cmd, "any") == 0) {
1407 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
1408 ssid = NULL;
1409 } else {
1410 id = atoi(cmd);
1411 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
1412
1413 ssid = wpa_config_get_network(wpa_s->conf, id);
1414 if (ssid == NULL) {
1415 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1416 "network id=%d", id);
1417 return -1;
1418 }
1419 if (ssid->disabled == 2) {
1420 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1421 "SELECT_NETWORK with persistent P2P group");
1422 return -1;
1423 }
1424 }
1425
1426 wpa_supplicant_select_network(wpa_s, ssid);
1427
1428 return 0;
1429}
1430
1431
1432static int wpa_supplicant_ctrl_iface_enable_network(
1433 struct wpa_supplicant *wpa_s, char *cmd)
1434{
1435 int id;
1436 struct wpa_ssid *ssid;
1437
1438 /* cmd: "<network id>" or "all" */
1439 if (os_strcmp(cmd, "all") == 0) {
1440 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1441 ssid = NULL;
1442 } else {
1443 id = atoi(cmd);
1444 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1445
1446 ssid = wpa_config_get_network(wpa_s->conf, id);
1447 if (ssid == NULL) {
1448 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1449 "network id=%d", id);
1450 return -1;
1451 }
1452 if (ssid->disabled == 2) {
1453 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1454 "ENABLE_NETWORK with persistent P2P group");
1455 return -1;
1456 }
1457 }
1458 wpa_supplicant_enable_network(wpa_s, ssid);
1459
1460 return 0;
1461}
1462
1463
1464static int wpa_supplicant_ctrl_iface_disable_network(
1465 struct wpa_supplicant *wpa_s, char *cmd)
1466{
1467 int id;
1468 struct wpa_ssid *ssid;
1469
1470 /* cmd: "<network id>" or "all" */
1471 if (os_strcmp(cmd, "all") == 0) {
1472 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1473 ssid = NULL;
1474 } else {
1475 id = atoi(cmd);
1476 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1477
1478 ssid = wpa_config_get_network(wpa_s->conf, id);
1479 if (ssid == NULL) {
1480 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1481 "network id=%d", id);
1482 return -1;
1483 }
1484 if (ssid->disabled == 2) {
1485 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1486 "DISABLE_NETWORK with persistent P2P "
1487 "group");
1488 return -1;
1489 }
1490 }
1491 wpa_supplicant_disable_network(wpa_s, ssid);
1492
1493 return 0;
1494}
1495
1496
1497static int wpa_supplicant_ctrl_iface_add_network(
1498 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1499{
1500 struct wpa_ssid *ssid;
1501 int ret;
1502
1503 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1504
1505 ssid = wpa_config_add_network(wpa_s->conf);
1506 if (ssid == NULL)
1507 return -1;
1508
1509 wpas_notify_network_added(wpa_s, ssid);
1510
1511 ssid->disabled = 1;
1512 wpa_config_set_network_defaults(ssid);
1513
1514 ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1515 if (ret < 0 || (size_t) ret >= buflen)
1516 return -1;
1517 return ret;
1518}
1519
1520
1521static int wpa_supplicant_ctrl_iface_remove_network(
1522 struct wpa_supplicant *wpa_s, char *cmd)
1523{
1524 int id;
1525 struct wpa_ssid *ssid;
1526
1527 /* cmd: "<network id>" or "all" */
1528 if (os_strcmp(cmd, "all") == 0) {
1529 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1530 ssid = wpa_s->conf->ssid;
1531 while (ssid) {
1532 struct wpa_ssid *remove_ssid = ssid;
1533 id = ssid->id;
1534 ssid = ssid->next;
1535 wpas_notify_network_removed(wpa_s, remove_ssid);
1536 wpa_config_remove_network(wpa_s->conf, id);
1537 }
1538 if (wpa_s->current_ssid) {
1539 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Jouni Malinen75ecf522011-06-27 15:19:46 -07001540 wpa_sm_set_config(wpa_s->wpa, NULL);
1541 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001542 wpa_supplicant_disassociate(wpa_s,
1543 WLAN_REASON_DEAUTH_LEAVING);
1544 }
1545 return 0;
1546 }
1547
1548 id = atoi(cmd);
1549 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1550
1551 ssid = wpa_config_get_network(wpa_s->conf, id);
1552 if (ssid == NULL ||
1553 wpa_config_remove_network(wpa_s->conf, id) < 0) {
1554 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1555 "id=%d", id);
1556 return -1;
1557 }
1558
1559 if (ssid == wpa_s->current_ssid) {
1560 /*
1561 * Invalidate the EAP session cache if the current network is
1562 * removed.
1563 */
1564 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Jouni Malinen75ecf522011-06-27 15:19:46 -07001565 wpa_sm_set_config(wpa_s->wpa, NULL);
1566 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001567
1568 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1569 }
1570
1571 return 0;
1572}
1573
1574
1575static int wpa_supplicant_ctrl_iface_set_network(
1576 struct wpa_supplicant *wpa_s, char *cmd)
1577{
1578 int id;
1579 struct wpa_ssid *ssid;
1580 char *name, *value;
1581
1582 /* cmd: "<network id> <variable name> <value>" */
1583 name = os_strchr(cmd, ' ');
1584 if (name == NULL)
1585 return -1;
1586 *name++ = '\0';
1587
1588 value = os_strchr(name, ' ');
1589 if (value == NULL)
1590 return -1;
1591 *value++ = '\0';
1592
1593 id = atoi(cmd);
1594 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1595 id, name);
1596 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1597 (u8 *) value, os_strlen(value));
1598
1599 ssid = wpa_config_get_network(wpa_s->conf, id);
1600 if (ssid == NULL) {
1601 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1602 "id=%d", id);
1603 return -1;
1604 }
1605
1606 if (wpa_config_set(ssid, name, value, 0) < 0) {
1607 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1608 "variable '%s'", name);
1609 return -1;
1610 }
1611
1612 if (wpa_s->current_ssid == ssid) {
1613 /*
1614 * Invalidate the EAP session cache if anything in the current
1615 * configuration changes.
1616 */
1617 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1618 }
1619
1620 if ((os_strcmp(name, "psk") == 0 &&
1621 value[0] == '"' && ssid->ssid_len) ||
1622 (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1623 wpa_config_update_psk(ssid);
1624 else if (os_strcmp(name, "priority") == 0)
1625 wpa_config_update_prio_list(wpa_s->conf);
1626
1627 return 0;
1628}
1629
1630
1631static int wpa_supplicant_ctrl_iface_get_network(
1632 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1633{
1634 int id;
1635 size_t res;
1636 struct wpa_ssid *ssid;
1637 char *name, *value;
1638
1639 /* cmd: "<network id> <variable name>" */
1640 name = os_strchr(cmd, ' ');
1641 if (name == NULL || buflen == 0)
1642 return -1;
1643 *name++ = '\0';
1644
1645 id = atoi(cmd);
1646 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1647 id, name);
1648
1649 ssid = wpa_config_get_network(wpa_s->conf, id);
1650 if (ssid == NULL) {
1651 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1652 "id=%d", id);
1653 return -1;
1654 }
1655
1656 value = wpa_config_get_no_key(ssid, name);
1657 if (value == NULL) {
1658 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1659 "variable '%s'", name);
1660 return -1;
1661 }
1662
1663 res = os_strlcpy(buf, value, buflen);
1664 if (res >= buflen) {
1665 os_free(value);
1666 return -1;
1667 }
1668
1669 os_free(value);
1670
1671 return res;
1672}
1673
1674
1675#ifndef CONFIG_NO_CONFIG_WRITE
1676static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1677{
1678 int ret;
1679
1680 if (!wpa_s->conf->update_config) {
1681 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1682 "to update configuration (update_config=0)");
1683 return -1;
1684 }
1685
1686 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1687 if (ret) {
1688 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1689 "update configuration");
1690 } else {
1691 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1692 " updated");
1693 }
1694
1695 return ret;
1696}
1697#endif /* CONFIG_NO_CONFIG_WRITE */
1698
1699
1700static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1701 struct wpa_driver_capa *capa,
1702 char *buf, size_t buflen)
1703{
1704 int ret, first = 1;
1705 char *pos, *end;
1706 size_t len;
1707
1708 pos = buf;
1709 end = pos + buflen;
1710
1711 if (res < 0) {
1712 if (strict)
1713 return 0;
1714 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1715 if (len >= buflen)
1716 return -1;
1717 return len;
1718 }
1719
1720 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1721 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1722 if (ret < 0 || ret >= end - pos)
1723 return pos - buf;
1724 pos += ret;
1725 first = 0;
1726 }
1727
1728 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1729 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1730 if (ret < 0 || ret >= end - pos)
1731 return pos - buf;
1732 pos += ret;
1733 first = 0;
1734 }
1735
1736 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1737 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1738 if (ret < 0 || ret >= end - pos)
1739 return pos - buf;
1740 pos += ret;
1741 first = 0;
1742 }
1743
1744 return pos - buf;
1745}
1746
1747
1748static int ctrl_iface_get_capability_group(int res, char *strict,
1749 struct wpa_driver_capa *capa,
1750 char *buf, size_t buflen)
1751{
1752 int ret, first = 1;
1753 char *pos, *end;
1754 size_t len;
1755
1756 pos = buf;
1757 end = pos + buflen;
1758
1759 if (res < 0) {
1760 if (strict)
1761 return 0;
1762 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1763 if (len >= buflen)
1764 return -1;
1765 return len;
1766 }
1767
1768 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1769 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1770 if (ret < 0 || ret >= end - pos)
1771 return pos - buf;
1772 pos += ret;
1773 first = 0;
1774 }
1775
1776 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1777 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1778 if (ret < 0 || ret >= end - pos)
1779 return pos - buf;
1780 pos += ret;
1781 first = 0;
1782 }
1783
1784 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1785 ret = os_snprintf(pos, end - pos, "%sWEP104",
1786 first ? "" : " ");
1787 if (ret < 0 || ret >= end - pos)
1788 return pos - buf;
1789 pos += ret;
1790 first = 0;
1791 }
1792
1793 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1794 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1795 if (ret < 0 || ret >= end - pos)
1796 return pos - buf;
1797 pos += ret;
1798 first = 0;
1799 }
1800
1801 return pos - buf;
1802}
1803
1804
1805static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1806 struct wpa_driver_capa *capa,
1807 char *buf, size_t buflen)
1808{
1809 int ret;
1810 char *pos, *end;
1811 size_t len;
1812
1813 pos = buf;
1814 end = pos + buflen;
1815
1816 if (res < 0) {
1817 if (strict)
1818 return 0;
1819 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1820 "NONE", buflen);
1821 if (len >= buflen)
1822 return -1;
1823 return len;
1824 }
1825
1826 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1827 if (ret < 0 || ret >= end - pos)
1828 return pos - buf;
1829 pos += ret;
1830
1831 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1832 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1833 ret = os_snprintf(pos, end - pos, " WPA-EAP");
1834 if (ret < 0 || ret >= end - pos)
1835 return pos - buf;
1836 pos += ret;
1837 }
1838
1839 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1840 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1841 ret = os_snprintf(pos, end - pos, " WPA-PSK");
1842 if (ret < 0 || ret >= end - pos)
1843 return pos - buf;
1844 pos += ret;
1845 }
1846
1847 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1848 ret = os_snprintf(pos, end - pos, " WPA-NONE");
1849 if (ret < 0 || ret >= end - pos)
1850 return pos - buf;
1851 pos += ret;
1852 }
1853
1854 return pos - buf;
1855}
1856
1857
1858static int ctrl_iface_get_capability_proto(int res, char *strict,
1859 struct wpa_driver_capa *capa,
1860 char *buf, size_t buflen)
1861{
1862 int ret, first = 1;
1863 char *pos, *end;
1864 size_t len;
1865
1866 pos = buf;
1867 end = pos + buflen;
1868
1869 if (res < 0) {
1870 if (strict)
1871 return 0;
1872 len = os_strlcpy(buf, "RSN WPA", buflen);
1873 if (len >= buflen)
1874 return -1;
1875 return len;
1876 }
1877
1878 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1879 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1880 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1881 if (ret < 0 || ret >= end - pos)
1882 return pos - buf;
1883 pos += ret;
1884 first = 0;
1885 }
1886
1887 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1888 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1889 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1890 if (ret < 0 || ret >= end - pos)
1891 return pos - buf;
1892 pos += ret;
1893 first = 0;
1894 }
1895
1896 return pos - buf;
1897}
1898
1899
1900static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1901 struct wpa_driver_capa *capa,
1902 char *buf, size_t buflen)
1903{
1904 int ret, first = 1;
1905 char *pos, *end;
1906 size_t len;
1907
1908 pos = buf;
1909 end = pos + buflen;
1910
1911 if (res < 0) {
1912 if (strict)
1913 return 0;
1914 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1915 if (len >= buflen)
1916 return -1;
1917 return len;
1918 }
1919
1920 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1921 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1922 if (ret < 0 || ret >= end - pos)
1923 return pos - buf;
1924 pos += ret;
1925 first = 0;
1926 }
1927
1928 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1929 ret = os_snprintf(pos, end - pos, "%sSHARED",
1930 first ? "" : " ");
1931 if (ret < 0 || ret >= end - pos)
1932 return pos - buf;
1933 pos += ret;
1934 first = 0;
1935 }
1936
1937 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1938 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1939 if (ret < 0 || ret >= end - pos)
1940 return pos - buf;
1941 pos += ret;
1942 first = 0;
1943 }
1944
1945 return pos - buf;
1946}
1947
1948
1949static int wpa_supplicant_ctrl_iface_get_capability(
1950 struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1951 size_t buflen)
1952{
1953 struct wpa_driver_capa capa;
1954 int res;
1955 char *strict;
1956 char field[30];
1957 size_t len;
1958
1959 /* Determine whether or not strict checking was requested */
1960 len = os_strlcpy(field, _field, sizeof(field));
1961 if (len >= sizeof(field))
1962 return -1;
1963 strict = os_strchr(field, ' ');
1964 if (strict != NULL) {
1965 *strict++ = '\0';
1966 if (os_strcmp(strict, "strict") != 0)
1967 return -1;
1968 }
1969
1970 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1971 field, strict ? strict : "");
1972
1973 if (os_strcmp(field, "eap") == 0) {
1974 return eap_get_names(buf, buflen);
1975 }
1976
1977 res = wpa_drv_get_capa(wpa_s, &capa);
1978
1979 if (os_strcmp(field, "pairwise") == 0)
1980 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1981 buf, buflen);
1982
1983 if (os_strcmp(field, "group") == 0)
1984 return ctrl_iface_get_capability_group(res, strict, &capa,
1985 buf, buflen);
1986
1987 if (os_strcmp(field, "key_mgmt") == 0)
1988 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1989 buf, buflen);
1990
1991 if (os_strcmp(field, "proto") == 0)
1992 return ctrl_iface_get_capability_proto(res, strict, &capa,
1993 buf, buflen);
1994
1995 if (os_strcmp(field, "auth_alg") == 0)
1996 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1997 buf, buflen);
1998
1999 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
2000 field);
2001
2002 return -1;
2003}
2004
2005
2006static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
2007 const char *cmd, char *buf,
2008 size_t buflen)
2009{
2010 u8 bssid[ETH_ALEN];
2011 size_t i;
2012 struct wpa_bss *bss;
2013 int ret;
2014 char *pos, *end;
2015 const u8 *ie, *ie2;
2016
2017 if (os_strcmp(cmd, "FIRST") == 0)
2018 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
2019 else if (os_strncmp(cmd, "ID-", 3) == 0) {
2020 i = atoi(cmd + 3);
2021 bss = wpa_bss_get_id(wpa_s, i);
2022 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2023 i = atoi(cmd + 5);
2024 bss = wpa_bss_get_id(wpa_s, i);
2025 if (bss) {
2026 struct dl_list *next = bss->list_id.next;
2027 if (next == &wpa_s->bss_id)
2028 bss = NULL;
2029 else
2030 bss = dl_list_entry(next, struct wpa_bss,
2031 list_id);
2032 }
2033 } else if (hwaddr_aton(cmd, bssid) == 0)
2034 bss = wpa_bss_get_bssid(wpa_s, bssid);
2035 else {
2036 struct wpa_bss *tmp;
2037 i = atoi(cmd);
2038 bss = NULL;
2039 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
2040 {
2041 if (i-- == 0) {
2042 bss = tmp;
2043 break;
2044 }
2045 }
2046 }
2047
2048 if (bss == NULL)
2049 return 0;
2050
2051 pos = buf;
2052 end = buf + buflen;
2053 ret = os_snprintf(pos, end - pos,
2054 "id=%u\n"
2055 "bssid=" MACSTR "\n"
2056 "freq=%d\n"
2057 "beacon_int=%d\n"
2058 "capabilities=0x%04x\n"
2059 "qual=%d\n"
2060 "noise=%d\n"
2061 "level=%d\n"
2062 "tsf=%016llu\n"
2063 "ie=",
2064 bss->id,
2065 MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
2066 bss->caps, bss->qual, bss->noise, bss->level,
2067 (unsigned long long) bss->tsf);
2068 if (ret < 0 || ret >= end - pos)
2069 return pos - buf;
2070 pos += ret;
2071
2072 ie = (const u8 *) (bss + 1);
2073 for (i = 0; i < bss->ie_len; i++) {
2074 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
2075 if (ret < 0 || ret >= end - pos)
2076 return pos - buf;
2077 pos += ret;
2078 }
2079 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
2080 ret = os_snprintf(pos, end - pos, "[P2P]");
2081 if (ret < 0 || ret >= end - pos)
2082 return pos - buf;
2083 pos += ret;
2084 }
2085
2086 ret = os_snprintf(pos, end - pos, "\n");
2087 if (ret < 0 || ret >= end - pos)
2088 return pos - buf;
2089 pos += ret;
2090
2091 ret = os_snprintf(pos, end - pos, "flags=");
2092 if (ret < 0 || ret >= end - pos)
2093 return pos - buf;
2094 pos += ret;
2095
2096 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2097 if (ie)
2098 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2099 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2100 if (ie2)
2101 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2102 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2103 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2104 ret = os_snprintf(pos, end - pos, "[WEP]");
2105 if (ret < 0 || ret >= end - pos)
2106 return pos - buf;
2107 pos += ret;
2108 }
2109 if (bss->caps & IEEE80211_CAP_IBSS) {
2110 ret = os_snprintf(pos, end - pos, "[IBSS]");
2111 if (ret < 0 || ret >= end - pos)
2112 return pos - buf;
2113 pos += ret;
2114 }
2115 if (bss->caps & IEEE80211_CAP_ESS) {
2116 ret = os_snprintf(pos, end - pos, "[ESS]");
2117 if (ret < 0 || ret >= end - pos)
2118 return pos - buf;
2119 pos += ret;
2120 }
2121
2122 ret = os_snprintf(pos, end - pos, "\n");
2123 if (ret < 0 || ret >= end - pos)
2124 return pos - buf;
2125 pos += ret;
2126
2127 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
2128 wpa_ssid_txt(bss->ssid, bss->ssid_len));
2129 if (ret < 0 || ret >= end - pos)
2130 return pos - buf;
2131 pos += ret;
2132
2133#ifdef CONFIG_WPS
2134 ie = (const u8 *) (bss + 1);
2135 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
2136 if (ret < 0 || ret >= end - pos)
2137 return pos - buf;
2138 pos += ret;
2139#endif /* CONFIG_WPS */
2140
2141#ifdef CONFIG_P2P
2142 ie = (const u8 *) (bss + 1);
2143 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
2144 if (ret < 0 || ret >= end - pos)
2145 return pos - buf;
2146 pos += ret;
2147#endif /* CONFIG_P2P */
2148
2149 return pos - buf;
2150}
2151
2152
2153static int wpa_supplicant_ctrl_iface_ap_scan(
2154 struct wpa_supplicant *wpa_s, char *cmd)
2155{
2156 int ap_scan = atoi(cmd);
2157 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
2158}
2159
2160
2161static int wpa_supplicant_ctrl_iface_scan_interval(
2162 struct wpa_supplicant *wpa_s, char *cmd)
2163{
2164 int scan_int = atoi(cmd);
2165 if (scan_int < 0)
2166 return -1;
2167 wpa_s->scan_interval = scan_int;
2168 return 0;
2169}
2170
2171
2172static int wpa_supplicant_ctrl_iface_bss_expire_age(
2173 struct wpa_supplicant *wpa_s, char *cmd)
2174{
2175 int expire_age = atoi(cmd);
2176 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
2177}
2178
2179
2180static int wpa_supplicant_ctrl_iface_bss_expire_count(
2181 struct wpa_supplicant *wpa_s, char *cmd)
2182{
2183 int expire_count = atoi(cmd);
2184 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
2185}
2186
2187
2188static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
2189{
2190 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
2191 /* MLME-DELETEKEYS.request */
2192 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
2193 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
2194 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
2195 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
2196#ifdef CONFIG_IEEE80211W
2197 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
2198 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
2199#endif /* CONFIG_IEEE80211W */
2200
2201 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
2202 0);
2203 /* MLME-SETPROTECTION.request(None) */
2204 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
2205 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
2206 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2207 wpa_sm_drop_sa(wpa_s->wpa);
2208}
2209
2210
2211static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
2212 char *addr)
2213{
2214 u8 bssid[ETH_ALEN];
2215 struct wpa_bss *bss;
2216 struct wpa_ssid *ssid = wpa_s->current_ssid;
2217
2218 if (hwaddr_aton(addr, bssid)) {
2219 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
2220 "address '%s'", addr);
2221 return -1;
2222 }
2223
2224 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
2225
2226 bss = wpa_bss_get_bssid(wpa_s, bssid);
2227 if (!bss) {
2228 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
2229 "from BSS table");
2230 return -1;
2231 }
2232
2233 /*
2234 * TODO: Find best network configuration block from configuration to
2235 * allow roaming to other networks
2236 */
2237
2238 if (!ssid) {
2239 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
2240 "configuration known for the target AP");
2241 return -1;
2242 }
2243
2244 wpa_s->reassociate = 1;
2245 wpa_supplicant_connect(wpa_s, bss, ssid);
2246
2247 return 0;
2248}
2249
2250
2251#ifdef CONFIG_P2P
2252static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
2253{
2254 unsigned int timeout = atoi(cmd);
2255 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
2256
2257 if (os_strstr(cmd, "type=social"))
2258 type = P2P_FIND_ONLY_SOCIAL;
2259 else if (os_strstr(cmd, "type=progressive"))
2260 type = P2P_FIND_PROGRESSIVE;
2261
2262 return wpas_p2p_find(wpa_s, timeout, type, 0, NULL);
2263}
2264
2265
2266static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
2267 char *buf, size_t buflen)
2268{
2269 u8 addr[ETH_ALEN];
2270 char *pos, *pos2;
2271 char *pin = NULL;
2272 enum p2p_wps_method wps_method;
2273 int new_pin;
2274 int ret;
2275 int persistent_group;
2276 int join;
2277 int auth;
2278 int go_intent = -1;
2279 int freq = 0;
2280
2281 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
2282 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
2283
2284 if (hwaddr_aton(cmd, addr))
2285 return -1;
2286
2287 pos = cmd + 17;
2288 if (*pos != ' ')
2289 return -1;
2290 pos++;
2291
2292 persistent_group = os_strstr(pos, " persistent") != NULL;
2293 join = os_strstr(pos, " join") != NULL;
2294 auth = os_strstr(pos, " auth") != NULL;
2295
2296 pos2 = os_strstr(pos, " go_intent=");
2297 if (pos2) {
2298 pos2 += 11;
2299 go_intent = atoi(pos2);
2300 if (go_intent < 0 || go_intent > 15)
2301 return -1;
2302 }
2303
2304 pos2 = os_strstr(pos, " freq=");
2305 if (pos2) {
2306 pos2 += 6;
2307 freq = atoi(pos2);
2308 if (freq <= 0)
2309 return -1;
2310 }
2311
2312 if (os_strncmp(pos, "pin", 3) == 0) {
2313 /* Request random PIN (to be displayed) and enable the PIN */
2314 wps_method = WPS_PIN_DISPLAY;
2315 } else if (os_strncmp(pos, "pbc", 3) == 0) {
2316 wps_method = WPS_PBC;
2317 } else {
2318 pin = pos;
2319 pos = os_strchr(pin, ' ');
2320 wps_method = WPS_PIN_KEYPAD;
2321 if (pos) {
2322 *pos++ = '\0';
2323 if (os_strncmp(pos, "label", 5) == 0)
2324 wps_method = WPS_PIN_LABEL;
2325 else if (os_strncmp(pos, "display", 7) == 0)
2326 wps_method = WPS_PIN_DISPLAY;
2327 }
2328 }
2329
2330 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
2331 persistent_group, join, auth, go_intent,
2332 freq);
2333 if (new_pin == -2) {
2334 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
2335 return 25;
2336 }
2337 if (new_pin == -3) {
2338 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
2339 return 25;
2340 }
2341 if (new_pin < 0)
2342 return -1;
2343 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
2344 ret = os_snprintf(buf, buflen, "%08d", new_pin);
2345 if (ret < 0 || (size_t) ret >= buflen)
2346 return -1;
2347 return ret;
2348 }
2349
2350 os_memcpy(buf, "OK\n", 3);
2351 return 3;
2352}
2353
2354
2355static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
2356{
2357 unsigned int timeout = atoi(cmd);
2358 return wpas_p2p_listen(wpa_s, timeout);
2359}
2360
2361
2362static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
2363{
2364 u8 addr[ETH_ALEN];
2365 char *pos;
2366
2367 /* <addr> <config method> */
2368
2369 if (hwaddr_aton(cmd, addr))
2370 return -1;
2371
2372 pos = cmd + 17;
2373 if (*pos != ' ')
2374 return -1;
2375 pos++;
2376
2377 return wpas_p2p_prov_disc(wpa_s, addr, pos);
2378}
2379
2380
2381static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
2382 size_t buflen)
2383{
2384 struct wpa_ssid *ssid = wpa_s->current_ssid;
2385
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07002386#ifdef ANDROID_BRCM_P2P_PATCH
2387 struct wpa_supplicant *ifs = NULL;
2388
2389 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
2390 if((ifs->ap_iface) &&
2391 (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO)) {
2392 ssid = ifs->current_ssid;
2393 }
2394 }
2395#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2397 ssid->passphrase == NULL)
2398 return -1;
2399
2400 os_strlcpy(buf, ssid->passphrase, buflen);
2401 return os_strlen(buf);
2402}
2403
2404
2405static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
2406 char *buf, size_t buflen)
2407{
2408 u64 ref;
2409 int res;
2410 u8 dst_buf[ETH_ALEN], *dst;
2411 struct wpabuf *tlvs;
2412 char *pos;
2413 size_t len;
2414
2415 if (hwaddr_aton(cmd, dst_buf))
2416 return -1;
2417 dst = dst_buf;
2418 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2419 dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2420 dst = NULL;
2421 pos = cmd + 17;
2422 if (*pos != ' ')
2423 return -1;
2424 pos++;
2425
2426 if (os_strncmp(pos, "upnp ", 5) == 0) {
2427 u8 version;
2428 pos += 5;
2429 if (hexstr2bin(pos, &version, 1) < 0)
2430 return -1;
2431 pos += 2;
2432 if (*pos != ' ')
2433 return -1;
2434 pos++;
2435 ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst,
2436 version, pos);
2437 } else {
2438 len = os_strlen(pos);
2439 if (len & 1)
2440 return -1;
2441 len /= 2;
2442 tlvs = wpabuf_alloc(len);
2443 if (tlvs == NULL)
2444 return -1;
2445 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
2446 wpabuf_free(tlvs);
2447 return -1;
2448 }
2449
2450 ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs);
2451 wpabuf_free(tlvs);
2452 }
2453 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
2454 if (res < 0 || (unsigned) res >= buflen)
2455 return -1;
2456 return res;
2457}
2458
2459
2460static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
2461 char *cmd)
2462{
2463 long long unsigned val;
2464 u64 req;
2465 if (sscanf(cmd, "%llx", &val) != 1)
2466 return -1;
2467 req = val;
2468 return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req);
2469}
2470
2471
2472static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
2473{
2474 int freq;
2475 u8 dst[ETH_ALEN];
2476 u8 dialog_token;
2477 struct wpabuf *resp_tlvs;
2478 char *pos, *pos2;
2479 size_t len;
2480
2481 pos = os_strchr(cmd, ' ');
2482 if (pos == NULL)
2483 return -1;
2484 *pos++ = '\0';
2485 freq = atoi(cmd);
2486 if (freq == 0)
2487 return -1;
2488
2489 if (hwaddr_aton(pos, dst))
2490 return -1;
2491 pos += 17;
2492 if (*pos != ' ')
2493 return -1;
2494 pos++;
2495
2496 pos2 = os_strchr(pos, ' ');
2497 if (pos2 == NULL)
2498 return -1;
2499 *pos2++ = '\0';
2500 dialog_token = atoi(pos);
2501
2502 len = os_strlen(pos2);
2503 if (len & 1)
2504 return -1;
2505 len /= 2;
2506 resp_tlvs = wpabuf_alloc(len);
2507 if (resp_tlvs == NULL)
2508 return -1;
2509 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
2510 wpabuf_free(resp_tlvs);
2511 return -1;
2512 }
2513
2514 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
2515 wpabuf_free(resp_tlvs);
2516 return 0;
2517}
2518
2519
2520static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
2521 char *cmd)
2522{
2523 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
2524 return 0;
2525}
2526
2527
2528static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
2529 char *cmd)
2530{
2531 char *pos;
2532 size_t len;
2533 struct wpabuf *query, *resp;
2534
2535 pos = os_strchr(cmd, ' ');
2536 if (pos == NULL)
2537 return -1;
2538 *pos++ = '\0';
2539
2540 len = os_strlen(cmd);
2541 if (len & 1)
2542 return -1;
2543 len /= 2;
2544 query = wpabuf_alloc(len);
2545 if (query == NULL)
2546 return -1;
2547 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2548 wpabuf_free(query);
2549 return -1;
2550 }
2551
2552 len = os_strlen(pos);
2553 if (len & 1) {
2554 wpabuf_free(query);
2555 return -1;
2556 }
2557 len /= 2;
2558 resp = wpabuf_alloc(len);
2559 if (resp == NULL) {
2560 wpabuf_free(query);
2561 return -1;
2562 }
2563 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
2564 wpabuf_free(query);
2565 wpabuf_free(resp);
2566 return -1;
2567 }
2568
2569 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
2570 wpabuf_free(query);
2571 wpabuf_free(resp);
2572 return -1;
2573 }
2574 return 0;
2575}
2576
2577
2578static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2579{
2580 char *pos;
2581 u8 version;
2582
2583 pos = os_strchr(cmd, ' ');
2584 if (pos == NULL)
2585 return -1;
2586 *pos++ = '\0';
2587
2588 if (hexstr2bin(cmd, &version, 1) < 0)
2589 return -1;
2590
2591 return wpas_p2p_service_add_upnp(wpa_s, version, pos);
2592}
2593
2594
2595static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
2596{
2597 char *pos;
2598
2599 pos = os_strchr(cmd, ' ');
2600 if (pos == NULL)
2601 return -1;
2602 *pos++ = '\0';
2603
2604 if (os_strcmp(cmd, "bonjour") == 0)
2605 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
2606 if (os_strcmp(cmd, "upnp") == 0)
2607 return p2p_ctrl_service_add_upnp(wpa_s, pos);
2608 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2609 return -1;
2610}
2611
2612
2613static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
2614 char *cmd)
2615{
2616 size_t len;
2617 struct wpabuf *query;
2618 int ret;
2619
2620 len = os_strlen(cmd);
2621 if (len & 1)
2622 return -1;
2623 len /= 2;
2624 query = wpabuf_alloc(len);
2625 if (query == NULL)
2626 return -1;
2627 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2628 wpabuf_free(query);
2629 return -1;
2630 }
2631
2632 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2633 wpabuf_free(query);
2634 return ret;
2635}
2636
2637
2638static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2639{
2640 char *pos;
2641 u8 version;
2642
2643 pos = os_strchr(cmd, ' ');
2644 if (pos == NULL)
2645 return -1;
2646 *pos++ = '\0';
2647
2648 if (hexstr2bin(cmd, &version, 1) < 0)
2649 return -1;
2650
2651 return wpas_p2p_service_del_upnp(wpa_s, version, pos);
2652}
2653
2654
2655static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
2656{
2657 char *pos;
2658
2659 pos = os_strchr(cmd, ' ');
2660 if (pos == NULL)
2661 return -1;
2662 *pos++ = '\0';
2663
2664 if (os_strcmp(cmd, "bonjour") == 0)
2665 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
2666 if (os_strcmp(cmd, "upnp") == 0)
2667 return p2p_ctrl_service_del_upnp(wpa_s, pos);
2668 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2669 return -1;
2670}
2671
2672
2673static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
2674{
2675 u8 addr[ETH_ALEN];
2676
2677 /* <addr> */
2678
2679 if (hwaddr_aton(cmd, addr))
2680 return -1;
2681
2682 return wpas_p2p_reject(wpa_s, addr);
2683}
2684
2685
2686static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
2687{
2688 char *pos;
2689 int id;
2690 struct wpa_ssid *ssid;
2691 u8 peer[ETH_ALEN];
2692
2693 id = atoi(cmd);
2694 pos = os_strstr(cmd, " peer=");
2695 if (pos) {
2696 pos += 6;
2697 if (hwaddr_aton(pos, peer))
2698 return -1;
2699 }
2700 ssid = wpa_config_get_network(wpa_s->conf, id);
2701 if (ssid == NULL || ssid->disabled != 2) {
2702 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2703 "for persistent P2P group",
2704 id);
2705 return -1;
2706 }
2707
2708 return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
2709}
2710
2711
2712static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
2713{
2714 char *pos;
2715 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
2716
2717 pos = os_strstr(cmd, " peer=");
2718 if (!pos)
2719 return -1;
2720
2721 *pos = '\0';
2722 pos += 6;
2723 if (hwaddr_aton(pos, peer)) {
2724 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
2725 return -1;
2726 }
2727
2728 pos = os_strstr(pos, " go_dev_addr=");
2729 if (pos) {
2730 pos += 13;
2731 if (hwaddr_aton(pos, go_dev_addr)) {
2732 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
2733 pos);
2734 return -1;
2735 }
2736 go_dev = go_dev_addr;
2737 }
2738
2739 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
2740}
2741
2742
2743static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
2744{
2745 if (os_strncmp(cmd, "persistent=", 11) == 0)
2746 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
2747 if (os_strncmp(cmd, "group=", 6) == 0)
2748 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
2749
2750 return -1;
2751}
2752
2753
2754static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
2755 char *cmd, int freq)
2756{
2757 int id;
2758 struct wpa_ssid *ssid;
2759
2760 id = atoi(cmd);
2761 ssid = wpa_config_get_network(wpa_s->conf, id);
2762 if (ssid == NULL || ssid->disabled != 2) {
2763 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2764 "for persistent P2P group",
2765 id);
2766 return -1;
2767 }
2768
2769 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
2770}
2771
2772
2773static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
2774{
2775 int freq = 0;
2776 char *pos;
2777
2778 pos = os_strstr(cmd, "freq=");
2779 if (pos)
2780 freq = atoi(pos + 5);
2781
2782 if (os_strncmp(cmd, "persistent=", 11) == 0)
2783 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
2784 if (os_strcmp(cmd, "persistent") == 0 ||
2785 os_strncmp(cmd, "persistent ", 11) == 0)
2786 return wpas_p2p_group_add(wpa_s, 1, freq);
2787 if (os_strncmp(cmd, "freq=", 5) == 0)
2788 return wpas_p2p_group_add(wpa_s, 0, freq);
2789
2790 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
2791 cmd);
2792 return -1;
2793}
2794
2795
2796static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
2797 char *buf, size_t buflen)
2798{
2799 u8 addr[ETH_ALEN], *addr_ptr;
2800 int next;
2801
2802 if (!wpa_s->global->p2p)
2803 return -1;
2804
2805 if (os_strcmp(cmd, "FIRST") == 0) {
2806 addr_ptr = NULL;
2807 next = 0;
2808 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2809 if (hwaddr_aton(cmd + 5, addr) < 0)
2810 return -1;
2811 addr_ptr = addr;
2812 next = 1;
2813 } else {
2814 if (hwaddr_aton(cmd, addr) < 0)
2815 return -1;
2816 addr_ptr = addr;
2817 next = 0;
2818 }
2819
2820 return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next,
2821 buf, buflen);
2822}
2823
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002824#ifdef ANDROID_BRCM_P2P_PATCH
2825struct wpa_supplicant* p2p_get_apif(struct wpa_supplicant* wpa_s)
2826{
2827 struct wpa_supplicant* iface;
2828 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
2829 if (iface->ap_iface)
2830 return iface;
2831 return wpa_s;
2832}
2833struct wpa_supplicant* p2p_get_clientif(struct wpa_supplicant* wpa_s)
2834{
2835 struct wpa_supplicant* iface;
2836 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
2837 if (iface->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
2838 return iface;
2839 return wpa_s;
2840}
2841#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842
2843static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
2844{
2845 char *param;
2846
2847 if (wpa_s->global->p2p == NULL)
2848 return -1;
2849
2850 param = os_strchr(cmd, ' ');
2851 if (param == NULL)
2852 return -1;
2853 *param++ = '\0';
2854
2855 if (os_strcmp(cmd, "discoverability") == 0) {
2856 p2p_set_client_discoverability(wpa_s->global->p2p,
2857 atoi(param));
2858 return 0;
2859 }
2860
2861 if (os_strcmp(cmd, "managed") == 0) {
2862 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
2863 return 0;
2864 }
2865
2866 if (os_strcmp(cmd, "listen_channel") == 0) {
2867 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
2868 atoi(param));
2869 }
2870
2871 if (os_strcmp(cmd, "ssid_postfix") == 0) {
2872 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
2873 os_strlen(param));
2874 }
2875
2876 if (os_strcmp(cmd, "noa") == 0) {
2877 char *pos;
2878 int count, start, duration;
2879 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
2880 count = atoi(param);
2881 pos = os_strchr(param, ',');
2882 if (pos == NULL)
2883 return -1;
2884 pos++;
2885 start = atoi(pos);
2886 pos = os_strchr(pos, ',');
2887 if (pos == NULL)
2888 return -1;
2889 pos++;
2890 duration = atoi(pos);
2891 if (count < 0 || count > 255 || start < 0 || duration < 0)
2892 return -1;
2893 if (count == 0 && duration > 0)
2894 return -1;
2895 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
2896 "start=%d duration=%d", count, start, duration);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002897#ifdef ANDROID_BRCM_P2P_PATCH
2898 return wpas_p2p_set_noa(p2p_get_apif(wpa_s), count, start, duration);
2899#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002900 return wpas_p2p_set_noa(wpa_s, count, start, duration);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002901#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002902 }
2903
2904 if (os_strcmp(cmd, "ps") == 0)
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002905#ifdef ANDROID_BRCM_P2P_PATCH
2906 return wpas_drv_set_p2p_powersave(p2p_get_clientif(wpa_s), atoi(param), -1, -1);
2907#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002909#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002910
2911 if (os_strcmp(cmd, "oppps") == 0)
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002912#ifdef ANDROID_BRCM_P2P_PATCH
2913 return wpas_drv_set_p2p_powersave(p2p_get_apif(wpa_s), -1, atoi(param), -1);
2914#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002915 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002916#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002917
2918 if (os_strcmp(cmd, "ctwindow") == 0)
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002919#ifdef ANDROID_BRCM_P2P_PATCH
2920 return wpa_drv_set_p2p_powersave(p2p_get_apif(wpa_s), -1, -1, atoi(param));
2921#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002922 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07002923#endif
2924
2925 if (os_strcmp(cmd, "disabled") == 0) {
2926 wpa_s->global->p2p_disabled = atoi(param);
2927 wpa_printf(MSG_DEBUG, "P2P functionality %s",
2928 wpa_s->global->p2p_disabled ?
2929 "disabled" : "enabled");
2930 if (wpa_s->global->p2p_disabled) {
2931 wpas_p2p_stop_find(wpa_s);
2932 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2933 p2p_flush(wpa_s->global->p2p);
2934 }
2935 return 0;
2936 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002937
2938 if (os_strcmp(cmd, "disabled") == 0) {
2939 wpa_s->global->p2p_disabled = atoi(param);
2940 wpa_printf(MSG_DEBUG, "P2P functionality %s",
2941 wpa_s->global->p2p_disabled ?
2942 "disabled" : "enabled");
2943 if (wpa_s->global->p2p_disabled) {
2944 wpas_p2p_stop_find(wpa_s);
2945 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2946 p2p_flush(wpa_s->global->p2p);
2947 }
2948 return 0;
2949 }
2950
2951 if (os_strcmp(cmd, "force_long_sd") == 0) {
2952 wpa_s->force_long_sd = atoi(param);
2953 return 0;
2954 }
2955
2956 if (os_strcmp(cmd, "peer_filter") == 0) {
2957 u8 addr[ETH_ALEN];
2958 if (hwaddr_aton(param, addr))
2959 return -1;
2960 p2p_set_peer_filter(wpa_s->global->p2p, addr);
2961 return 0;
2962 }
2963
2964 if (os_strcmp(cmd, "cross_connect") == 0)
2965 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
2966
2967 if (os_strcmp(cmd, "go_apsd") == 0) {
2968 if (os_strcmp(param, "disable") == 0)
2969 wpa_s->set_ap_uapsd = 0;
2970 else {
2971 wpa_s->set_ap_uapsd = 1;
2972 wpa_s->ap_uapsd = atoi(param);
2973 }
2974 return 0;
2975 }
2976
2977 if (os_strcmp(cmd, "client_apsd") == 0) {
2978 if (os_strcmp(param, "disable") == 0)
2979 wpa_s->set_sta_uapsd = 0;
2980 else {
2981 int be, bk, vi, vo;
2982 char *pos;
2983 /* format: BE,BK,VI,VO;max SP Length */
2984 be = atoi(param);
2985 pos = os_strchr(param, ',');
2986 if (pos == NULL)
2987 return -1;
2988 pos++;
2989 bk = atoi(pos);
2990 pos = os_strchr(pos, ',');
2991 if (pos == NULL)
2992 return -1;
2993 pos++;
2994 vi = atoi(pos);
2995 pos = os_strchr(pos, ',');
2996 if (pos == NULL)
2997 return -1;
2998 pos++;
2999 vo = atoi(pos);
3000 /* ignore max SP Length for now */
3001
3002 wpa_s->set_sta_uapsd = 1;
3003 wpa_s->sta_uapsd = 0;
3004 if (be)
3005 wpa_s->sta_uapsd |= BIT(0);
3006 if (bk)
3007 wpa_s->sta_uapsd |= BIT(1);
3008 if (vi)
3009 wpa_s->sta_uapsd |= BIT(2);
3010 if (vo)
3011 wpa_s->sta_uapsd |= BIT(3);
3012 }
3013 return 0;
3014 }
3015
3016 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
3017 cmd);
3018
3019 return -1;
3020}
3021
3022
3023static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
3024{
3025 char *pos, *pos2;
3026 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
3027
3028 if (cmd[0]) {
3029 pos = os_strchr(cmd, ' ');
3030 if (pos == NULL)
3031 return -1;
3032 *pos++ = '\0';
3033 dur1 = atoi(cmd);
3034
3035 pos2 = os_strchr(pos, ' ');
3036 if (pos2)
3037 *pos2++ = '\0';
3038 int1 = atoi(pos);
3039 } else
3040 pos2 = NULL;
3041
3042 if (pos2) {
3043 pos = os_strchr(pos2, ' ');
3044 if (pos == NULL)
3045 return -1;
3046 *pos++ = '\0';
3047 dur2 = atoi(pos2);
3048 int2 = atoi(pos);
3049 }
3050
3051 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
3052}
3053
3054
3055static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
3056{
3057 char *pos;
3058 unsigned int period = 0, interval = 0;
3059
3060 if (cmd[0]) {
3061 pos = os_strchr(cmd, ' ');
3062 if (pos == NULL)
3063 return -1;
3064 *pos++ = '\0';
3065 period = atoi(cmd);
3066 interval = atoi(pos);
3067 }
3068
3069 return wpas_p2p_ext_listen(wpa_s, period, interval);
3070}
3071
3072#endif /* CONFIG_P2P */
3073
3074
3075static int wpa_supplicant_ctrl_iface_sta_autoconnect(
3076 struct wpa_supplicant *wpa_s, char *cmd)
3077{
3078 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
3079 return 0;
3080}
3081
3082
3083static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
3084 size_t buflen)
3085{
3086 struct wpa_signal_info si;
3087 int ret;
3088
3089 ret = wpa_drv_signal_poll(wpa_s, &si);
3090 if (ret)
3091 return -1;
3092
3093 ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
3094 "NOISE=%d\nFREQUENCY=%u\n",
3095 si.current_signal, si.current_txrate / 1000,
3096 si.current_noise, si.frequency);
3097 if (ret < 0 || (unsigned int) ret > buflen)
3098 return -1;
3099 return ret;
3100}
3101
3102
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07003103static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
3104 char *buf, size_t buflen)
3105{
3106 int ret;
3107
3108 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
3109 if (ret == 0)
3110 ret = sprintf(buf, "%s\n", "OK");
3111 return ret;
3112}
3113
3114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003115char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
3116 char *buf, size_t *resp_len)
3117{
3118 char *reply;
3119 const int reply_size = 4096;
3120 int ctrl_rsp = 0;
3121 int reply_len;
3122
3123 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
3124 os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3125 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
3126 (const u8 *) buf, os_strlen(buf));
3127 } else {
3128 int level = MSG_DEBUG;
3129 if (os_strcmp(buf, "PING") == 0)
3130 level = MSG_EXCESSIVE;
3131 wpa_hexdump_ascii(level, "RX ctrl_iface",
3132 (const u8 *) buf, os_strlen(buf));
3133 }
3134
3135 reply = os_malloc(reply_size);
3136 if (reply == NULL) {
3137 *resp_len = 1;
3138 return NULL;
3139 }
3140
3141 os_memcpy(reply, "OK\n", 3);
3142 reply_len = 3;
3143
3144 if (os_strcmp(buf, "PING") == 0) {
3145 os_memcpy(reply, "PONG\n", 5);
3146 reply_len = 5;
3147 } else if (os_strncmp(buf, "RELOG", 5) == 0) {
3148 if (wpa_debug_reopen_file() < 0)
3149 reply_len = -1;
3150 } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
3151 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
3152 } else if (os_strcmp(buf, "MIB") == 0) {
3153 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
3154 if (reply_len >= 0) {
3155 int res;
3156 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
3157 reply_size - reply_len);
3158 if (res < 0)
3159 reply_len = -1;
3160 else
3161 reply_len += res;
3162 }
3163 } else if (os_strncmp(buf, "STATUS", 6) == 0) {
3164 reply_len = wpa_supplicant_ctrl_iface_status(
3165 wpa_s, buf + 6, reply, reply_size);
3166 } else if (os_strcmp(buf, "PMKSA") == 0) {
3167 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
3168 reply_size);
3169 } else if (os_strncmp(buf, "SET ", 4) == 0) {
3170 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
3171 reply_len = -1;
3172 } else if (os_strncmp(buf, "GET ", 4) == 0) {
3173 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
3174 reply, reply_size);
3175 } else if (os_strcmp(buf, "LOGON") == 0) {
3176 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
3177 } else if (os_strcmp(buf, "LOGOFF") == 0) {
3178 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
3179 } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
3180 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3181 reply_len = -1;
3182 else {
3183 wpa_s->disconnected = 0;
3184 wpa_s->reassociate = 1;
3185 wpa_supplicant_req_scan(wpa_s, 0, 0);
3186 }
3187 } else if (os_strcmp(buf, "RECONNECT") == 0) {
3188 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3189 reply_len = -1;
3190 else if (wpa_s->disconnected) {
3191 wpa_s->disconnected = 0;
3192 wpa_s->reassociate = 1;
3193 wpa_supplicant_req_scan(wpa_s, 0, 0);
3194 }
3195#ifdef IEEE8021X_EAPOL
3196 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
3197 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
3198 reply_len = -1;
3199#endif /* IEEE8021X_EAPOL */
3200#ifdef CONFIG_PEERKEY
3201 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
3202 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
3203 reply_len = -1;
3204#endif /* CONFIG_PEERKEY */
3205#ifdef CONFIG_IEEE80211R
3206 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
3207 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
3208 reply_len = -1;
3209#endif /* CONFIG_IEEE80211R */
3210#ifdef CONFIG_WPS
3211 } else if (os_strcmp(buf, "WPS_PBC") == 0) {
3212 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
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_PBC ", 8) == 0) {
3219 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
3220 if (res == -2) {
3221 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3222 reply_len = 17;
3223 } else if (res)
3224 reply_len = -1;
3225 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
3226 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
3227 reply,
3228 reply_size);
3229 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
3230 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
3231 wpa_s, buf + 14, reply, reply_size);
3232 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
3233 if (wpas_wps_cancel(wpa_s))
3234 reply_len = -1;
3235#ifdef CONFIG_WPS_OOB
3236 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
3237 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
3238 reply_len = -1;
3239#endif /* CONFIG_WPS_OOB */
3240 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
3241 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
3242 reply_len = -1;
3243#ifdef CONFIG_AP
3244 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
3245 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
3246 wpa_s, buf + 11, reply, reply_size);
3247#endif /* CONFIG_AP */
3248#ifdef CONFIG_WPS_ER
3249 } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
3250 if (wpas_wps_er_start(wpa_s, NULL))
3251 reply_len = -1;
3252 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
3253 if (wpas_wps_er_start(wpa_s, buf + 13))
3254 reply_len = -1;
3255 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
3256 if (wpas_wps_er_stop(wpa_s))
3257 reply_len = -1;
3258 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
3259 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
3260 reply_len = -1;
3261 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
3262 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
3263 if (ret == -2) {
3264 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
3265 reply_len = 17;
3266 } else if (ret == -3) {
3267 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
3268 reply_len = 18;
3269 } else if (ret == -4) {
3270 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
3271 reply_len = 20;
3272 } else if (ret)
3273 reply_len = -1;
3274 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
3275 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
3276 reply_len = -1;
3277 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
3278 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
3279 buf + 18))
3280 reply_len = -1;
3281 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
3282 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
3283 reply_len = -1;
3284#endif /* CONFIG_WPS_ER */
3285#endif /* CONFIG_WPS */
3286#ifdef CONFIG_IBSS_RSN
3287 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
3288 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
3289 reply_len = -1;
3290#endif /* CONFIG_IBSS_RSN */
3291#ifdef CONFIG_P2P
3292 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
3293 if (p2p_ctrl_find(wpa_s, buf + 9))
3294 reply_len = -1;
3295 } else if (os_strcmp(buf, "P2P_FIND") == 0) {
3296 if (p2p_ctrl_find(wpa_s, ""))
3297 reply_len = -1;
3298 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
3299 wpas_p2p_stop_find(wpa_s);
3300 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
3301 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
3302 reply_size);
3303 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
3304 if (p2p_ctrl_listen(wpa_s, buf + 11))
3305 reply_len = -1;
3306 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
3307 if (p2p_ctrl_listen(wpa_s, ""))
3308 reply_len = -1;
3309 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
3310 if (wpas_p2p_group_remove(wpa_s, buf + 17))
3311 reply_len = -1;
3312 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
3313 if (wpas_p2p_group_add(wpa_s, 0, 0))
3314 reply_len = -1;
3315 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
3316 if (p2p_ctrl_group_add(wpa_s, buf + 14))
3317 reply_len = -1;
3318 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
3319 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
3320 reply_len = -1;
3321 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
3322 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
3323 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
3324 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
3325 reply_size);
3326 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
3327 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
3328 reply_len = -1;
3329 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
3330 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
3331 reply_len = -1;
3332 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
3333 wpas_p2p_sd_service_update(wpa_s);
3334 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
3335 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
3336 reply_len = -1;
3337 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
3338 wpas_p2p_service_flush(wpa_s);
3339 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
3340 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
3341 reply_len = -1;
3342 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
3343 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
3344 reply_len = -1;
3345 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
3346 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
3347 reply_len = -1;
3348 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
3349 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
3350 reply_len = -1;
3351 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
3352 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
3353 reply_size);
3354 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
3355 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
3356 reply_len = -1;
3357 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
3358 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
3359 wpa_s->force_long_sd = 0;
3360 if (wpa_s->global->p2p)
3361 p2p_flush(wpa_s->global->p2p);
3362 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
3363 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
3364 reply_len = -1;
3365 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
3366 if (wpas_p2p_cancel(wpa_s))
3367 reply_len = -1;
3368 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
Dmitry Shmidtfc41cad2011-09-28 13:29:53 -07003369 #if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
3370 /* We have to send presence command to p2p interface if p2p_interface is started
3371 * otherwise we can send it to primary interface
3372 */
3373 struct wpa_supplicant* ifs;
3374 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3375 if ( (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO ) ||(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT )) {
3376 wpa_s = ifs;
3377 break;
3378 }
3379 }
3380 #endif /* defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003381 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
3382 reply_len = -1;
3383 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
3384 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
3385 reply_len = -1;
3386 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
3387 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
3388 reply_len = -1;
3389 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
3390 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
3391 reply_len = -1;
3392#endif /* CONFIG_P2P */
3393 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
3394 {
3395 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
3396 wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
3397 reply_len = -1;
3398 else
3399 ctrl_rsp = 1;
3400 } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
3401 if (wpa_supplicant_reload_configuration(wpa_s))
3402 reply_len = -1;
3403 } else if (os_strcmp(buf, "TERMINATE") == 0) {
3404 wpa_supplicant_terminate_proc(wpa_s->global);
3405 } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
3406 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
3407 reply_len = -1;
Dmitry Shmidt657a7042011-03-16 14:57:39 -07003408 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
3409 reply_len = wpa_supplicant_ctrl_iface_log_level(wpa_s, buf + 9,
3410 reply, reply_size);
Dmitry Shmidte19501d2011-03-16 14:32:18 -07003411 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
3412 reply_len = wpa_supplicant_ctrl_iface_blacklist(wpa_s, buf + 9,
3413 reply, reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
3415 reply_len = wpa_supplicant_ctrl_iface_list_networks(
3416 wpa_s, reply, reply_size);
3417 } else if (os_strcmp(buf, "DISCONNECT") == 0) {
3418 wpa_s->reassociate = 0;
3419 wpa_s->disconnected = 1;
3420 wpa_supplicant_deauthenticate(wpa_s,
3421 WLAN_REASON_DEAUTH_LEAVING);
3422 } else if (os_strcmp(buf, "SCAN") == 0) {
3423 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3424 reply_len = -1;
3425 else {
3426 if (!wpa_s->scanning &&
3427 ((wpa_s->wpa_state <= WPA_SCANNING) ||
3428 (wpa_s->wpa_state == WPA_COMPLETED))) {
3429 wpa_s->scan_req = 2;
3430 wpa_supplicant_req_scan(wpa_s, 0, 0);
3431 } else {
3432 wpa_printf(MSG_DEBUG, "Ongoing scan action - "
3433 "reject new request");
3434 reply_len = os_snprintf(reply, reply_size,
3435 "FAIL-BUSY\n");
3436 }
3437 }
3438 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
3439 reply_len = wpa_supplicant_ctrl_iface_scan_results(
3440 wpa_s, reply, reply_size);
3441 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
3442 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
3443 reply_len = -1;
3444 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
3445 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
3446 reply_len = -1;
3447 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
3448 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
3449 reply_len = -1;
3450 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
3451 reply_len = wpa_supplicant_ctrl_iface_add_network(
3452 wpa_s, reply, reply_size);
3453 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
3454 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
3455 reply_len = -1;
3456 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
3457 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
3458 reply_len = -1;
3459 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
3460 reply_len = wpa_supplicant_ctrl_iface_get_network(
3461 wpa_s, buf + 12, reply, reply_size);
3462#ifndef CONFIG_NO_CONFIG_WRITE
3463 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
3464 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
3465 reply_len = -1;
3466#endif /* CONFIG_NO_CONFIG_WRITE */
3467 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
3468 reply_len = wpa_supplicant_ctrl_iface_get_capability(
3469 wpa_s, buf + 15, reply, reply_size);
3470 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
3471 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
3472 reply_len = -1;
3473 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
3474 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
3475 reply_len = -1;
3476 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3477 reply_len = wpa_supplicant_global_iface_list(
3478 wpa_s->global, reply, reply_size);
3479 } else if (os_strcmp(buf, "INTERFACES") == 0) {
3480 reply_len = wpa_supplicant_global_iface_interfaces(
3481 wpa_s->global, reply, reply_size);
3482 } else if (os_strncmp(buf, "BSS ", 4) == 0) {
3483 reply_len = wpa_supplicant_ctrl_iface_bss(
3484 wpa_s, buf + 4, reply, reply_size);
3485#ifdef CONFIG_AP
3486 } else if (os_strcmp(buf, "STA-FIRST") == 0) {
3487 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
3488 } else if (os_strncmp(buf, "STA ", 4) == 0) {
3489 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
3490 reply_size);
3491 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
3492 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
3493 reply_size);
3494#endif /* CONFIG_AP */
3495 } else if (os_strcmp(buf, "SUSPEND") == 0) {
3496 wpas_notify_suspend(wpa_s->global);
3497 } else if (os_strcmp(buf, "RESUME") == 0) {
3498 wpas_notify_resume(wpa_s->global);
3499 } else if (os_strcmp(buf, "DROP_SA") == 0) {
3500 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
3501 } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
3502 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
3503 reply_len = -1;
3504 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
3505 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
3506 reply_len = -1;
3507 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
3508 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
3509 reply_len = -1;
3510 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
3511 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
3512 buf + 17))
3513 reply_len = -1;
3514#ifdef CONFIG_TDLS
3515 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
3516 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
3517 reply_len = -1;
3518 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
3519 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
3520 reply_len = -1;
3521 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
3522 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
3523 reply_len = -1;
3524#endif /* CONFIG_TDLS */
3525 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
3526 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
3527 reply_size);
Dmitry Shmidtbd567ad2011-05-09 14:17:09 -07003528 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
3529 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
3530 reply_size);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003531 } else {
3532 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3533 reply_len = 16;
3534 }
3535
3536 if (reply_len < 0) {
3537 os_memcpy(reply, "FAIL\n", 5);
3538 reply_len = 5;
3539 }
3540
3541 if (ctrl_rsp)
3542 eapol_sm_notify_ctrl_response(wpa_s->eapol);
3543
3544 *resp_len = reply_len;
3545 return reply;
3546}
3547
3548
3549static int wpa_supplicant_global_iface_add(struct wpa_global *global,
3550 char *cmd)
3551{
3552 struct wpa_interface iface;
3553 char *pos;
3554
3555 /*
3556 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
3557 * TAB<bridge_ifname>
3558 */
3559 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
3560
3561 os_memset(&iface, 0, sizeof(iface));
3562
3563 do {
3564 iface.ifname = pos = cmd;
3565 pos = os_strchr(pos, '\t');
3566 if (pos)
3567 *pos++ = '\0';
3568 if (iface.ifname[0] == '\0')
3569 return -1;
3570 if (pos == NULL)
3571 break;
3572
3573 iface.confname = pos;
3574 pos = os_strchr(pos, '\t');
3575 if (pos)
3576 *pos++ = '\0';
3577 if (iface.confname[0] == '\0')
3578 iface.confname = NULL;
3579 if (pos == NULL)
3580 break;
3581
3582 iface.driver = pos;
3583 pos = os_strchr(pos, '\t');
3584 if (pos)
3585 *pos++ = '\0';
3586 if (iface.driver[0] == '\0')
3587 iface.driver = NULL;
3588 if (pos == NULL)
3589 break;
3590
3591 iface.ctrl_interface = pos;
3592 pos = os_strchr(pos, '\t');
3593 if (pos)
3594 *pos++ = '\0';
3595 if (iface.ctrl_interface[0] == '\0')
3596 iface.ctrl_interface = NULL;
3597 if (pos == NULL)
3598 break;
3599
3600 iface.driver_param = pos;
3601 pos = os_strchr(pos, '\t');
3602 if (pos)
3603 *pos++ = '\0';
3604 if (iface.driver_param[0] == '\0')
3605 iface.driver_param = NULL;
3606 if (pos == NULL)
3607 break;
3608
3609 iface.bridge_ifname = pos;
3610 pos = os_strchr(pos, '\t');
3611 if (pos)
3612 *pos++ = '\0';
3613 if (iface.bridge_ifname[0] == '\0')
3614 iface.bridge_ifname = NULL;
3615 if (pos == NULL)
3616 break;
3617 } while (0);
3618
3619 if (wpa_supplicant_get_iface(global, iface.ifname))
3620 return -1;
3621
3622 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
3623}
3624
3625
3626static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
3627 char *cmd)
3628{
3629 struct wpa_supplicant *wpa_s;
3630
3631 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
3632
3633 wpa_s = wpa_supplicant_get_iface(global, cmd);
3634 if (wpa_s == NULL)
3635 return -1;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003636 return wpa_supplicant_remove_iface(global, wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003637}
3638
3639
3640static void wpa_free_iface_info(struct wpa_interface_info *iface)
3641{
3642 struct wpa_interface_info *prev;
3643
3644 while (iface) {
3645 prev = iface;
3646 iface = iface->next;
3647
3648 os_free(prev->ifname);
3649 os_free(prev->desc);
3650 os_free(prev);
3651 }
3652}
3653
3654
3655static int wpa_supplicant_global_iface_list(struct wpa_global *global,
3656 char *buf, int len)
3657{
3658 int i, res;
3659 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
3660 char *pos, *end;
3661
3662 for (i = 0; wpa_drivers[i]; i++) {
3663 struct wpa_driver_ops *drv = wpa_drivers[i];
3664 if (drv->get_interfaces == NULL)
3665 continue;
3666 tmp = drv->get_interfaces(global->drv_priv[i]);
3667 if (tmp == NULL)
3668 continue;
3669
3670 if (last == NULL)
3671 iface = last = tmp;
3672 else
3673 last->next = tmp;
3674 while (last->next)
3675 last = last->next;
3676 }
3677
3678 pos = buf;
3679 end = buf + len;
3680 for (tmp = iface; tmp; tmp = tmp->next) {
3681 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
3682 tmp->drv_name, tmp->ifname,
3683 tmp->desc ? tmp->desc : "");
3684 if (res < 0 || res >= end - pos) {
3685 *pos = '\0';
3686 break;
3687 }
3688 pos += res;
3689 }
3690
3691 wpa_free_iface_info(iface);
3692
3693 return pos - buf;
3694}
3695
3696
3697static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
3698 char *buf, int len)
3699{
3700 int res;
3701 char *pos, *end;
3702 struct wpa_supplicant *wpa_s;
3703
3704 wpa_s = global->ifaces;
3705 pos = buf;
3706 end = buf + len;
3707
3708 while (wpa_s) {
3709 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
3710 if (res < 0 || res >= end - pos) {
3711 *pos = '\0';
3712 break;
3713 }
3714 pos += res;
3715 wpa_s = wpa_s->next;
3716 }
3717 return pos - buf;
3718}
3719
3720
3721char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
3722 char *buf, size_t *resp_len)
3723{
3724 char *reply;
3725 const int reply_size = 2048;
3726 int reply_len;
3727
3728 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
3729 (const u8 *) buf, os_strlen(buf));
3730
3731 reply = os_malloc(reply_size);
3732 if (reply == NULL) {
3733 *resp_len = 1;
3734 return NULL;
3735 }
3736
3737 os_memcpy(reply, "OK\n", 3);
3738 reply_len = 3;
3739
3740 if (os_strcmp(buf, "PING") == 0) {
3741 os_memcpy(reply, "PONG\n", 5);
3742 reply_len = 5;
3743 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
3744 if (wpa_supplicant_global_iface_add(global, buf + 14))
3745 reply_len = -1;
3746 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
3747 if (wpa_supplicant_global_iface_remove(global, buf + 17))
3748 reply_len = -1;
3749 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3750 reply_len = wpa_supplicant_global_iface_list(
3751 global, reply, reply_size);
3752 } else if (os_strcmp(buf, "INTERFACES") == 0) {
3753 reply_len = wpa_supplicant_global_iface_interfaces(
3754 global, reply, reply_size);
3755 } else if (os_strcmp(buf, "TERMINATE") == 0) {
3756 wpa_supplicant_terminate_proc(global);
3757 } else if (os_strcmp(buf, "SUSPEND") == 0) {
3758 wpas_notify_suspend(global);
3759 } else if (os_strcmp(buf, "RESUME") == 0) {
3760 wpas_notify_resume(global);
3761 } else {
3762 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3763 reply_len = 16;
3764 }
3765
3766 if (reply_len < 0) {
3767 os_memcpy(reply, "FAIL\n", 5);
3768 reply_len = 5;
3769 }
3770
3771 *resp_len = reply_len;
3772 return reply;
3773}