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