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