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