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