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