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