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