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