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