OSDN Git Service

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