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