TDLS: Add get_capability tdls command
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2014, 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 "utils/uuid.h"
14 #include "common/version.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/ieee802_11_common.h"
17 #include "common/wpa_ctrl.h"
18 #include "eap_peer/eap.h"
19 #include "eapol_supp/eapol_supp_sm.h"
20 #include "rsn_supp/wpa.h"
21 #include "rsn_supp/preauth.h"
22 #include "rsn_supp/pmksa_cache.h"
23 #include "l2_packet/l2_packet.h"
24 #include "wps/wps.h"
25 #include "config.h"
26 #include "wpa_supplicant_i.h"
27 #include "driver_i.h"
28 #include "wps_supplicant.h"
29 #include "ibss_rsn.h"
30 #include "ap.h"
31 #include "p2p_supplicant.h"
32 #include "p2p/p2p.h"
33 #include "hs20_supplicant.h"
34 #include "wifi_display.h"
35 #include "notify.h"
36 #include "bss.h"
37 #include "scan.h"
38 #include "ctrl_iface.h"
39 #include "interworking.h"
40 #include "blacklist.h"
41 #include "autoscan.h"
42 #include "wnm_sta.h"
43 #include "offchannel.h"
44
45 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
46                                             char *buf, int len);
47 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
48                                                   char *buf, int len);
49
50 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
51 {
52         char *pos;
53         u8 addr[ETH_ALEN], *filter = NULL, *n;
54         size_t count = 0;
55
56         pos = val;
57         while (pos) {
58                 if (*pos == '\0')
59                         break;
60                 if (hwaddr_aton(pos, addr)) {
61                         os_free(filter);
62                         return -1;
63                 }
64                 n = os_realloc_array(filter, count + 1, ETH_ALEN);
65                 if (n == NULL) {
66                         os_free(filter);
67                         return -1;
68                 }
69                 filter = n;
70                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
71                 count++;
72
73                 pos = os_strchr(pos, ' ');
74                 if (pos)
75                         pos++;
76         }
77
78         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
79         os_free(wpa_s->bssid_filter);
80         wpa_s->bssid_filter = filter;
81         wpa_s->bssid_filter_count = count;
82
83         return 0;
84 }
85
86
87 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
88 {
89         char *pos;
90         u8 addr[ETH_ALEN], *bssid = NULL, *n;
91         struct wpa_ssid_value *ssid = NULL, *ns;
92         size_t count = 0, ssid_count = 0;
93         struct wpa_ssid *c;
94
95         /*
96          * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
97          * SSID_SPEC ::= ssid <SSID_HEX>
98          * BSSID_SPEC ::= bssid <BSSID_HEX>
99          */
100
101         pos = val;
102         while (pos) {
103                 if (*pos == '\0')
104                         break;
105                 if (os_strncmp(pos, "bssid ", 6) == 0) {
106                         int res;
107                         pos += 6;
108                         res = hwaddr_aton2(pos, addr);
109                         if (res < 0) {
110                                 os_free(ssid);
111                                 os_free(bssid);
112                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
113                                            "BSSID value '%s'", pos);
114                                 return -1;
115                         }
116                         pos += res;
117                         n = os_realloc_array(bssid, count + 1, ETH_ALEN);
118                         if (n == NULL) {
119                                 os_free(ssid);
120                                 os_free(bssid);
121                                 return -1;
122                         }
123                         bssid = n;
124                         os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
125                         count++;
126                 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
127                         char *end;
128                         pos += 5;
129
130                         end = pos;
131                         while (*end) {
132                                 if (*end == '\0' || *end == ' ')
133                                         break;
134                                 end++;
135                         }
136
137                         ns = os_realloc_array(ssid, ssid_count + 1,
138                                               sizeof(struct wpa_ssid_value));
139                         if (ns == NULL) {
140                                 os_free(ssid);
141                                 os_free(bssid);
142                                 return -1;
143                         }
144                         ssid = ns;
145
146                         if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
147                             hexstr2bin(pos, ssid[ssid_count].ssid,
148                                        (end - pos) / 2) < 0) {
149                                 os_free(ssid);
150                                 os_free(bssid);
151                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
152                                            "SSID value '%s'", pos);
153                                 return -1;
154                         }
155                         ssid[ssid_count].ssid_len = (end - pos) / 2;
156                         wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
157                                           ssid[ssid_count].ssid,
158                                           ssid[ssid_count].ssid_len);
159                         ssid_count++;
160                         pos = end;
161                 } else {
162                         wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
163                                    "'%s'", pos);
164                         os_free(ssid);
165                         os_free(bssid);
166                         return -1;
167                 }
168
169                 pos = os_strchr(pos, ' ');
170                 if (pos)
171                         pos++;
172         }
173
174         wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
175         os_free(wpa_s->disallow_aps_bssid);
176         wpa_s->disallow_aps_bssid = bssid;
177         wpa_s->disallow_aps_bssid_count = count;
178
179         wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
180         os_free(wpa_s->disallow_aps_ssid);
181         wpa_s->disallow_aps_ssid = ssid;
182         wpa_s->disallow_aps_ssid_count = ssid_count;
183
184         if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
185                 return 0;
186
187         c = wpa_s->current_ssid;
188         if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
189                 return 0;
190
191         if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
192             !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
193                 return 0;
194
195         wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
196                    "because current AP was marked disallowed");
197
198 #ifdef CONFIG_SME
199         wpa_s->sme.prev_bssid_set = 0;
200 #endif /* CONFIG_SME */
201         wpa_s->reassociate = 1;
202         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
203         wpa_supplicant_req_scan(wpa_s, 0, 0);
204
205         return 0;
206 }
207
208
209 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
210                                          char *cmd)
211 {
212         char *value;
213         int ret = 0;
214
215         value = os_strchr(cmd, ' ');
216         if (value == NULL)
217                 return -1;
218         *value++ = '\0';
219
220         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
221         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
222                 eapol_sm_configure(wpa_s->eapol,
223                                    atoi(value), -1, -1, -1);
224         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
225                 eapol_sm_configure(wpa_s->eapol,
226                                    -1, atoi(value), -1, -1);
227         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
228                 eapol_sm_configure(wpa_s->eapol,
229                                    -1, -1, atoi(value), -1);
230         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
231                 eapol_sm_configure(wpa_s->eapol,
232                                    -1, -1, -1, atoi(value));
233         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
234                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
235                                      atoi(value)))
236                         ret = -1;
237         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
238                    0) {
239                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
240                                      atoi(value)))
241                         ret = -1;
242         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
243                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
244                         ret = -1;
245         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
246                 wpa_s->wps_fragment_size = atoi(value);
247 #ifdef CONFIG_WPS_TESTING
248         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
249                 long int val;
250                 val = strtol(value, NULL, 0);
251                 if (val < 0 || val > 0xff) {
252                         ret = -1;
253                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
254                                    "wps_version_number %ld", val);
255                 } else {
256                         wps_version_number = val;
257                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
258                                    "version %u.%u",
259                                    (wps_version_number & 0xf0) >> 4,
260                                    wps_version_number & 0x0f);
261                 }
262         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
263                 wps_testing_dummy_cred = atoi(value);
264                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
265                            wps_testing_dummy_cred);
266         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
267                 wps_corrupt_pkhash = atoi(value);
268                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
269                            wps_corrupt_pkhash);
270 #endif /* CONFIG_WPS_TESTING */
271         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
272                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
273                         ret = -1;
274 #ifdef CONFIG_TDLS
275 #ifdef CONFIG_TDLS_TESTING
276         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
277                 extern unsigned int tdls_testing;
278                 tdls_testing = strtol(value, NULL, 0);
279                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
280 #endif /* CONFIG_TDLS_TESTING */
281         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
282                 int disabled = atoi(value);
283                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
284                 if (disabled) {
285                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
286                                 ret = -1;
287                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
288                         ret = -1;
289                 wpa_tdls_enable(wpa_s->wpa, !disabled);
290 #endif /* CONFIG_TDLS */
291         } else if (os_strcasecmp(cmd, "pno") == 0) {
292                 if (atoi(value))
293                         ret = wpas_start_pno(wpa_s);
294                 else
295                         ret = wpas_stop_pno(wpa_s);
296         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
297                 int disabled = atoi(value);
298                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
299                         ret = -1;
300                 else if (disabled)
301                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
302         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
303                 if (os_strcmp(value, "disable") == 0)
304                         wpa_s->set_sta_uapsd = 0;
305                 else {
306                         int be, bk, vi, vo;
307                         char *pos;
308                         /* format: BE,BK,VI,VO;max SP Length */
309                         be = atoi(value);
310                         pos = os_strchr(value, ',');
311                         if (pos == NULL)
312                                 return -1;
313                         pos++;
314                         bk = atoi(pos);
315                         pos = os_strchr(pos, ',');
316                         if (pos == NULL)
317                                 return -1;
318                         pos++;
319                         vi = atoi(pos);
320                         pos = os_strchr(pos, ',');
321                         if (pos == NULL)
322                                 return -1;
323                         pos++;
324                         vo = atoi(pos);
325                         /* ignore max SP Length for now */
326
327                         wpa_s->set_sta_uapsd = 1;
328                         wpa_s->sta_uapsd = 0;
329                         if (be)
330                                 wpa_s->sta_uapsd |= BIT(0);
331                         if (bk)
332                                 wpa_s->sta_uapsd |= BIT(1);
333                         if (vi)
334                                 wpa_s->sta_uapsd |= BIT(2);
335                         if (vo)
336                                 wpa_s->sta_uapsd |= BIT(3);
337                 }
338         } else if (os_strcasecmp(cmd, "ps") == 0) {
339                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
340 #ifdef CONFIG_WIFI_DISPLAY
341         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
342                 int enabled = !!atoi(value);
343                 if (enabled && !wpa_s->global->p2p)
344                         ret = -1;
345                 else
346                         wifi_display_enable(wpa_s->global, enabled);
347 #endif /* CONFIG_WIFI_DISPLAY */
348         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
349                 ret = set_bssid_filter(wpa_s, value);
350         } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
351                 ret = set_disallow_aps(wpa_s, value);
352         } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
353                 wpa_s->no_keep_alive = !!atoi(value);
354 #ifdef CONFIG_TESTING_OPTIONS
355         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
356                 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
357 #endif /* CONFIG_TESTING_OPTIONS */
358         } else {
359                 value[-1] = '=';
360                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
361                 if (ret == 0)
362                         wpa_supplicant_update_config(wpa_s);
363         }
364
365         return ret;
366 }
367
368
369 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
370                                          char *cmd, char *buf, size_t buflen)
371 {
372         int res = -1;
373
374         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
375
376         if (os_strcmp(cmd, "version") == 0) {
377                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
378         } else if (os_strcasecmp(cmd, "country") == 0) {
379                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
380                         res = os_snprintf(buf, buflen, "%c%c",
381                                           wpa_s->conf->country[0],
382                                           wpa_s->conf->country[1]);
383 #ifdef CONFIG_WIFI_DISPLAY
384         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
385                 int enabled;
386                 if (wpa_s->global->p2p == NULL ||
387                     wpa_s->global->p2p_disabled)
388                         enabled = 0;
389                 else
390                         enabled = wpa_s->global->wifi_display;
391                 res = os_snprintf(buf, buflen, "%d", enabled);
392                 if (res < 0 || (unsigned int) res >= buflen)
393                         return -1;
394                 return res;
395 #endif /* CONFIG_WIFI_DISPLAY */
396 #ifdef CONFIG_TESTING_GET_GTK
397         } else if (os_strcmp(cmd, "gtk") == 0) {
398                 if (wpa_s->last_gtk_len == 0)
399                         return -1;
400                 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
401                                        wpa_s->last_gtk_len);
402                 return res;
403 #endif /* CONFIG_TESTING_GET_GTK */
404         }
405
406         if (res < 0 || (unsigned int) res >= buflen)
407                 return -1;
408         return res;
409 }
410
411
412 #ifdef IEEE8021X_EAPOL
413 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
414                                              char *addr)
415 {
416         u8 bssid[ETH_ALEN];
417         struct wpa_ssid *ssid = wpa_s->current_ssid;
418
419         if (hwaddr_aton(addr, bssid)) {
420                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
421                            "'%s'", addr);
422                 return -1;
423         }
424
425         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
426         rsn_preauth_deinit(wpa_s->wpa);
427         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
428                 return -1;
429
430         return 0;
431 }
432 #endif /* IEEE8021X_EAPOL */
433
434
435 #ifdef CONFIG_PEERKEY
436 /* MLME-STKSTART.request(peer) */
437 static int wpa_supplicant_ctrl_iface_stkstart(
438         struct wpa_supplicant *wpa_s, char *addr)
439 {
440         u8 peer[ETH_ALEN];
441
442         if (hwaddr_aton(addr, peer)) {
443                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
444                            "address '%s'", addr);
445                 return -1;
446         }
447
448         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
449                    MAC2STR(peer));
450
451         return wpa_sm_stkstart(wpa_s->wpa, peer);
452 }
453 #endif /* CONFIG_PEERKEY */
454
455
456 #ifdef CONFIG_TDLS
457
458 static int wpa_supplicant_ctrl_iface_tdls_discover(
459         struct wpa_supplicant *wpa_s, char *addr)
460 {
461         u8 peer[ETH_ALEN];
462         int ret;
463
464         if (hwaddr_aton(addr, peer)) {
465                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
466                            "address '%s'", addr);
467                 return -1;
468         }
469
470         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
471                    MAC2STR(peer));
472
473         if (wpa_tdls_is_external_setup(wpa_s->wpa))
474                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
475         else
476                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
477
478         return ret;
479 }
480
481
482 static int wpa_supplicant_ctrl_iface_tdls_setup(
483         struct wpa_supplicant *wpa_s, char *addr)
484 {
485         u8 peer[ETH_ALEN];
486         int ret;
487
488         if (hwaddr_aton(addr, peer)) {
489                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
490                            "address '%s'", addr);
491                 return -1;
492         }
493
494         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
495                    MAC2STR(peer));
496
497         if ((wpa_s->conf->tdls_external_control) &&
498             wpa_tdls_is_external_setup(wpa_s->wpa))
499                 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
500
501         wpa_tdls_remove(wpa_s->wpa, peer);
502
503         if (wpa_tdls_is_external_setup(wpa_s->wpa))
504                 ret = wpa_tdls_start(wpa_s->wpa, peer);
505         else
506                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
507
508         return ret;
509 }
510
511
512 static int wpa_supplicant_ctrl_iface_tdls_teardown(
513         struct wpa_supplicant *wpa_s, char *addr)
514 {
515         u8 peer[ETH_ALEN];
516         int ret;
517
518         if (hwaddr_aton(addr, peer)) {
519                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
520                            "address '%s'", addr);
521                 return -1;
522         }
523
524         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
525                    MAC2STR(peer));
526
527         if ((wpa_s->conf->tdls_external_control) &&
528             wpa_tdls_is_external_setup(wpa_s->wpa))
529                 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
530
531         if (wpa_tdls_is_external_setup(wpa_s->wpa))
532                 ret = wpa_tdls_teardown_link(
533                         wpa_s->wpa, peer,
534                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
535         else
536                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
537
538         return ret;
539 }
540
541
542 static int ctrl_iface_get_capability_tdls(
543         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
544 {
545         int ret;
546
547         ret = os_snprintf(buf, buflen, "%s\n",
548                           wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
549                           (wpa_s->drv_flags &
550                            WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
551                            "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
552         if (ret < 0 || (size_t) ret > buflen)
553                 return -1;
554         return ret;
555 }
556
557 #endif /* CONFIG_TDLS */
558
559
560 #ifdef CONFIG_IEEE80211R
561 static int wpa_supplicant_ctrl_iface_ft_ds(
562         struct wpa_supplicant *wpa_s, char *addr)
563 {
564         u8 target_ap[ETH_ALEN];
565         struct wpa_bss *bss;
566         const u8 *mdie;
567
568         if (hwaddr_aton(addr, target_ap)) {
569                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
570                            "address '%s'", addr);
571                 return -1;
572         }
573
574         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
575
576         bss = wpa_bss_get_bssid(wpa_s, target_ap);
577         if (bss)
578                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
579         else
580                 mdie = NULL;
581
582         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
583 }
584 #endif /* CONFIG_IEEE80211R */
585
586
587 #ifdef CONFIG_WPS
588 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
589                                              char *cmd)
590 {
591         u8 bssid[ETH_ALEN], *_bssid = bssid;
592 #ifdef CONFIG_P2P
593         u8 p2p_dev_addr[ETH_ALEN];
594 #endif /* CONFIG_P2P */
595 #ifdef CONFIG_AP
596         u8 *_p2p_dev_addr = NULL;
597 #endif /* CONFIG_AP */
598
599         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
600                 _bssid = NULL;
601 #ifdef CONFIG_P2P
602         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
603                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
604                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
605                                    "P2P Device Address '%s'",
606                                    cmd + 13);
607                         return -1;
608                 }
609                 _p2p_dev_addr = p2p_dev_addr;
610 #endif /* CONFIG_P2P */
611         } else if (hwaddr_aton(cmd, bssid)) {
612                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
613                            cmd);
614                 return -1;
615         }
616
617 #ifdef CONFIG_AP
618         if (wpa_s->ap_iface)
619                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
620 #endif /* CONFIG_AP */
621
622         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
623 }
624
625
626 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
627                                              char *cmd, char *buf,
628                                              size_t buflen)
629 {
630         u8 bssid[ETH_ALEN], *_bssid = bssid;
631         char *pin;
632         int ret;
633
634         pin = os_strchr(cmd, ' ');
635         if (pin)
636                 *pin++ = '\0';
637
638         if (os_strcmp(cmd, "any") == 0)
639                 _bssid = NULL;
640         else if (os_strcmp(cmd, "get") == 0) {
641                 ret = wps_generate_pin();
642                 goto done;
643         } else if (hwaddr_aton(cmd, bssid)) {
644                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
645                            cmd);
646                 return -1;
647         }
648
649 #ifdef CONFIG_AP
650         if (wpa_s->ap_iface) {
651                 int timeout = 0;
652                 char *pos;
653
654                 if (pin) {
655                         pos = os_strchr(pin, ' ');
656                         if (pos) {
657                                 *pos++ = '\0';
658                                 timeout = atoi(pos);
659                         }
660                 }
661
662                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
663                                                  buf, buflen, timeout);
664         }
665 #endif /* CONFIG_AP */
666
667         if (pin) {
668                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
669                                          DEV_PW_DEFAULT);
670                 if (ret < 0)
671                         return -1;
672                 ret = os_snprintf(buf, buflen, "%s", pin);
673                 if (ret < 0 || (size_t) ret >= buflen)
674                         return -1;
675                 return ret;
676         }
677
678         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
679         if (ret < 0)
680                 return -1;
681
682 done:
683         /* Return the generated PIN */
684         ret = os_snprintf(buf, buflen, "%08d", ret);
685         if (ret < 0 || (size_t) ret >= buflen)
686                 return -1;
687         return ret;
688 }
689
690
691 static int wpa_supplicant_ctrl_iface_wps_check_pin(
692         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
693 {
694         char pin[9];
695         size_t len;
696         char *pos;
697         int ret;
698
699         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
700                               (u8 *) cmd, os_strlen(cmd));
701         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
702                 if (*pos < '0' || *pos > '9')
703                         continue;
704                 pin[len++] = *pos;
705                 if (len == 9) {
706                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
707                         return -1;
708                 }
709         }
710         if (len != 4 && len != 8) {
711                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
712                 return -1;
713         }
714         pin[len] = '\0';
715
716         if (len == 8) {
717                 unsigned int pin_val;
718                 pin_val = atoi(pin);
719                 if (!wps_pin_valid(pin_val)) {
720                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
721                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
722                         if (ret < 0 || (size_t) ret >= buflen)
723                                 return -1;
724                         return ret;
725                 }
726         }
727
728         ret = os_snprintf(buf, buflen, "%s", pin);
729         if (ret < 0 || (size_t) ret >= buflen)
730                 return -1;
731
732         return ret;
733 }
734
735
736 #ifdef CONFIG_WPS_NFC
737
738 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
739                                              char *cmd)
740 {
741         u8 bssid[ETH_ALEN], *_bssid = bssid;
742
743         if (cmd == NULL || cmd[0] == '\0')
744                 _bssid = NULL;
745         else if (hwaddr_aton(cmd, bssid))
746                 return -1;
747
748         return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
749                                   0, 0);
750 }
751
752
753 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
754         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
755 {
756         int ndef;
757         struct wpabuf *buf;
758         int res;
759         char *pos;
760
761         pos = os_strchr(cmd, ' ');
762         if (pos)
763                 *pos++ = '\0';
764         if (os_strcmp(cmd, "WPS") == 0)
765                 ndef = 0;
766         else if (os_strcmp(cmd, "NDEF") == 0)
767                 ndef = 1;
768         else
769                 return -1;
770
771         buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
772         if (buf == NULL)
773                 return -1;
774
775         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
776                                          wpabuf_len(buf));
777         reply[res++] = '\n';
778         reply[res] = '\0';
779
780         wpabuf_free(buf);
781
782         return res;
783 }
784
785
786 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
787         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
788 {
789         int ndef;
790         struct wpabuf *buf;
791         int res;
792
793         if (os_strcmp(cmd, "WPS") == 0)
794                 ndef = 0;
795         else if (os_strcmp(cmd, "NDEF") == 0)
796                 ndef = 1;
797         else
798                 return -1;
799
800         buf = wpas_wps_nfc_token(wpa_s, ndef);
801         if (buf == NULL)
802                 return -1;
803
804         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
805                                          wpabuf_len(buf));
806         reply[res++] = '\n';
807         reply[res] = '\0';
808
809         wpabuf_free(buf);
810
811         return res;
812 }
813
814
815 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
816         struct wpa_supplicant *wpa_s, char *pos)
817 {
818         size_t len;
819         struct wpabuf *buf;
820         int ret;
821         char *freq;
822         int forced_freq = 0;
823
824         freq = strstr(pos, " freq=");
825         if (freq) {
826                 *freq = '\0';
827                 freq += 6;
828                 forced_freq = atoi(freq);
829         }
830
831         len = os_strlen(pos);
832         if (len & 0x01)
833                 return -1;
834         len /= 2;
835
836         buf = wpabuf_alloc(len);
837         if (buf == NULL)
838                 return -1;
839         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
840                 wpabuf_free(buf);
841                 return -1;
842         }
843
844         ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
845         wpabuf_free(buf);
846
847         return ret;
848 }
849
850
851 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
852                                               char *reply, size_t max_len,
853                                               int ndef)
854 {
855         struct wpabuf *buf;
856         int res;
857
858         buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
859         if (buf == NULL)
860                 return -1;
861
862         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
863                                          wpabuf_len(buf));
864         reply[res++] = '\n';
865         reply[res] = '\0';
866
867         wpabuf_free(buf);
868
869         return res;
870 }
871
872
873 #ifdef CONFIG_P2P
874 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
875                                               char *reply, size_t max_len,
876                                               int ndef)
877 {
878         struct wpabuf *buf;
879         int res;
880
881         buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
882         if (buf == NULL) {
883                 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
884                 return -1;
885         }
886
887         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
888                                          wpabuf_len(buf));
889         reply[res++] = '\n';
890         reply[res] = '\0';
891
892         wpabuf_free(buf);
893
894         return res;
895 }
896 #endif /* CONFIG_P2P */
897
898
899 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
900                                           char *cmd, char *reply,
901                                           size_t max_len)
902 {
903         char *pos;
904         int ndef;
905
906         pos = os_strchr(cmd, ' ');
907         if (pos == NULL)
908                 return -1;
909         *pos++ = '\0';
910
911         if (os_strcmp(cmd, "WPS") == 0)
912                 ndef = 0;
913         else if (os_strcmp(cmd, "NDEF") == 0)
914                 ndef = 1;
915         else
916                 return -1;
917
918         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
919                 if (!ndef)
920                         return -1;
921                 return wpas_ctrl_nfc_get_handover_req_wps(
922                         wpa_s, reply, max_len, ndef);
923         }
924
925 #ifdef CONFIG_P2P
926         if (os_strcmp(pos, "P2P-CR") == 0) {
927                 return wpas_ctrl_nfc_get_handover_req_p2p(
928                         wpa_s, reply, max_len, ndef);
929         }
930 #endif /* CONFIG_P2P */
931
932         return -1;
933 }
934
935
936 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
937                                               char *reply, size_t max_len,
938                                               int ndef, int cr, char *uuid)
939 {
940         struct wpabuf *buf;
941         int res;
942
943         buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
944         if (buf == NULL)
945                 return -1;
946
947         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
948                                          wpabuf_len(buf));
949         reply[res++] = '\n';
950         reply[res] = '\0';
951
952         wpabuf_free(buf);
953
954         return res;
955 }
956
957
958 #ifdef CONFIG_P2P
959 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
960                                               char *reply, size_t max_len,
961                                               int ndef, int tag)
962 {
963         struct wpabuf *buf;
964         int res;
965
966         buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
967         if (buf == NULL)
968                 return -1;
969
970         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
971                                          wpabuf_len(buf));
972         reply[res++] = '\n';
973         reply[res] = '\0';
974
975         wpabuf_free(buf);
976
977         return res;
978 }
979 #endif /* CONFIG_P2P */
980
981
982 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
983                                           char *cmd, char *reply,
984                                           size_t max_len)
985 {
986         char *pos, *pos2;
987         int ndef;
988
989         pos = os_strchr(cmd, ' ');
990         if (pos == NULL)
991                 return -1;
992         *pos++ = '\0';
993
994         if (os_strcmp(cmd, "WPS") == 0)
995                 ndef = 0;
996         else if (os_strcmp(cmd, "NDEF") == 0)
997                 ndef = 1;
998         else
999                 return -1;
1000
1001         pos2 = os_strchr(pos, ' ');
1002         if (pos2)
1003                 *pos2++ = '\0';
1004         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1005                 if (!ndef)
1006                         return -1;
1007                 return wpas_ctrl_nfc_get_handover_sel_wps(
1008                         wpa_s, reply, max_len, ndef,
1009                         os_strcmp(pos, "WPS-CR") == 0, pos2);
1010         }
1011
1012 #ifdef CONFIG_P2P
1013         if (os_strcmp(pos, "P2P-CR") == 0) {
1014                 return wpas_ctrl_nfc_get_handover_sel_p2p(
1015                         wpa_s, reply, max_len, ndef, 0);
1016         }
1017
1018         if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1019                 return wpas_ctrl_nfc_get_handover_sel_p2p(
1020                         wpa_s, reply, max_len, ndef, 1);
1021         }
1022 #endif /* CONFIG_P2P */
1023
1024         return -1;
1025 }
1026
1027
1028 static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
1029                                          char *cmd)
1030 {
1031         size_t len;
1032         struct wpabuf *buf;
1033         int ret;
1034
1035         len = os_strlen(cmd);
1036         if (len & 0x01)
1037                 return -1;
1038         len /= 2;
1039
1040         buf = wpabuf_alloc(len);
1041         if (buf == NULL)
1042                 return -1;
1043         if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
1044                 wpabuf_free(buf);
1045                 return -1;
1046         }
1047
1048         ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf);
1049         wpabuf_free(buf);
1050
1051         return ret;
1052 }
1053
1054
1055 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1056                                          char *cmd)
1057 {
1058         size_t len;
1059         struct wpabuf *req, *sel;
1060         int ret;
1061         char *pos, *role, *type, *pos2;
1062 #ifdef CONFIG_P2P
1063         char *freq;
1064         int forced_freq = 0;
1065
1066         freq = strstr(cmd, " freq=");
1067         if (freq) {
1068                 *freq = '\0';
1069                 freq += 6;
1070                 forced_freq = atoi(freq);
1071         }
1072 #endif /* CONFIG_P2P */
1073
1074         role = cmd;
1075         pos = os_strchr(role, ' ');
1076         if (pos == NULL) {
1077                 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1078                 return -1;
1079         }
1080         *pos++ = '\0';
1081
1082         type = pos;
1083         pos = os_strchr(type, ' ');
1084         if (pos == NULL) {
1085                 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1086                 return -1;
1087         }
1088         *pos++ = '\0';
1089
1090         pos2 = os_strchr(pos, ' ');
1091         if (pos2 == NULL) {
1092                 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1093                 return -1;
1094         }
1095         *pos2++ = '\0';
1096
1097         len = os_strlen(pos);
1098         if (len & 0x01) {
1099                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1100                 return -1;
1101         }
1102         len /= 2;
1103
1104         req = wpabuf_alloc(len);
1105         if (req == NULL) {
1106                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1107                 return -1;
1108         }
1109         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1110                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1111                 wpabuf_free(req);
1112                 return -1;
1113         }
1114
1115         len = os_strlen(pos2);
1116         if (len & 0x01) {
1117                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1118                 wpabuf_free(req);
1119                 return -1;
1120         }
1121         len /= 2;
1122
1123         sel = wpabuf_alloc(len);
1124         if (sel == NULL) {
1125                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1126                 wpabuf_free(req);
1127                 return -1;
1128         }
1129         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1130                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1131                 wpabuf_free(req);
1132                 wpabuf_free(sel);
1133                 return -1;
1134         }
1135
1136         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1137                    role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1138
1139         if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1140                 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1141 #ifdef CONFIG_AP
1142         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1143         {
1144                 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1145                 if (ret < 0)
1146                         ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1147 #endif /* CONFIG_AP */
1148 #ifdef CONFIG_P2P
1149         } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1150         {
1151                 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1152         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1153         {
1154                 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1155                                                    forced_freq);
1156 #endif /* CONFIG_P2P */
1157         } else {
1158                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1159                            "reported: role=%s type=%s", role, type);
1160                 ret = -1;
1161         }
1162         wpabuf_free(req);
1163         wpabuf_free(sel);
1164
1165         if (ret)
1166                 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1167
1168         return ret;
1169 }
1170
1171 #endif /* CONFIG_WPS_NFC */
1172
1173
1174 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1175                                              char *cmd)
1176 {
1177         u8 bssid[ETH_ALEN];
1178         char *pin;
1179         char *new_ssid;
1180         char *new_auth;
1181         char *new_encr;
1182         char *new_key;
1183         struct wps_new_ap_settings ap;
1184
1185         pin = os_strchr(cmd, ' ');
1186         if (pin == NULL)
1187                 return -1;
1188         *pin++ = '\0';
1189
1190         if (hwaddr_aton(cmd, bssid)) {
1191                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1192                            cmd);
1193                 return -1;
1194         }
1195
1196         new_ssid = os_strchr(pin, ' ');
1197         if (new_ssid == NULL)
1198                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1199         *new_ssid++ = '\0';
1200
1201         new_auth = os_strchr(new_ssid, ' ');
1202         if (new_auth == NULL)
1203                 return -1;
1204         *new_auth++ = '\0';
1205
1206         new_encr = os_strchr(new_auth, ' ');
1207         if (new_encr == NULL)
1208                 return -1;
1209         *new_encr++ = '\0';
1210
1211         new_key = os_strchr(new_encr, ' ');
1212         if (new_key == NULL)
1213                 return -1;
1214         *new_key++ = '\0';
1215
1216         os_memset(&ap, 0, sizeof(ap));
1217         ap.ssid_hex = new_ssid;
1218         ap.auth = new_auth;
1219         ap.encr = new_encr;
1220         ap.key_hex = new_key;
1221         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1222 }
1223
1224
1225 #ifdef CONFIG_AP
1226 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1227                                                 char *cmd, char *buf,
1228                                                 size_t buflen)
1229 {
1230         int timeout = 300;
1231         char *pos;
1232         const char *pin_txt;
1233
1234         if (!wpa_s->ap_iface)
1235                 return -1;
1236
1237         pos = os_strchr(cmd, ' ');
1238         if (pos)
1239                 *pos++ = '\0';
1240
1241         if (os_strcmp(cmd, "disable") == 0) {
1242                 wpas_wps_ap_pin_disable(wpa_s);
1243                 return os_snprintf(buf, buflen, "OK\n");
1244         }
1245
1246         if (os_strcmp(cmd, "random") == 0) {
1247                 if (pos)
1248                         timeout = atoi(pos);
1249                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1250                 if (pin_txt == NULL)
1251                         return -1;
1252                 return os_snprintf(buf, buflen, "%s", pin_txt);
1253         }
1254
1255         if (os_strcmp(cmd, "get") == 0) {
1256                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
1257                 if (pin_txt == NULL)
1258                         return -1;
1259                 return os_snprintf(buf, buflen, "%s", pin_txt);
1260         }
1261
1262         if (os_strcmp(cmd, "set") == 0) {
1263                 char *pin;
1264                 if (pos == NULL)
1265                         return -1;
1266                 pin = pos;
1267                 pos = os_strchr(pos, ' ');
1268                 if (pos) {
1269                         *pos++ = '\0';
1270                         timeout = atoi(pos);
1271                 }
1272                 if (os_strlen(pin) > buflen)
1273                         return -1;
1274                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1275                         return -1;
1276                 return os_snprintf(buf, buflen, "%s", pin);
1277         }
1278
1279         return -1;
1280 }
1281 #endif /* CONFIG_AP */
1282
1283
1284 #ifdef CONFIG_WPS_ER
1285 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1286                                                 char *cmd)
1287 {
1288         char *uuid = cmd, *pin, *pos;
1289         u8 addr_buf[ETH_ALEN], *addr = NULL;
1290         pin = os_strchr(uuid, ' ');
1291         if (pin == NULL)
1292                 return -1;
1293         *pin++ = '\0';
1294         pos = os_strchr(pin, ' ');
1295         if (pos) {
1296                 *pos++ = '\0';
1297                 if (hwaddr_aton(pos, addr_buf) == 0)
1298                         addr = addr_buf;
1299         }
1300         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1301 }
1302
1303
1304 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1305                                                   char *cmd)
1306 {
1307         char *uuid = cmd, *pin;
1308         pin = os_strchr(uuid, ' ');
1309         if (pin == NULL)
1310                 return -1;
1311         *pin++ = '\0';
1312         return wpas_wps_er_learn(wpa_s, uuid, pin);
1313 }
1314
1315
1316 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1317         struct wpa_supplicant *wpa_s, char *cmd)
1318 {
1319         char *uuid = cmd, *id;
1320         id = os_strchr(uuid, ' ');
1321         if (id == NULL)
1322                 return -1;
1323         *id++ = '\0';
1324         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1325 }
1326
1327
1328 static int wpa_supplicant_ctrl_iface_wps_er_config(
1329         struct wpa_supplicant *wpa_s, char *cmd)
1330 {
1331         char *pin;
1332         char *new_ssid;
1333         char *new_auth;
1334         char *new_encr;
1335         char *new_key;
1336         struct wps_new_ap_settings ap;
1337
1338         pin = os_strchr(cmd, ' ');
1339         if (pin == NULL)
1340                 return -1;
1341         *pin++ = '\0';
1342
1343         new_ssid = os_strchr(pin, ' ');
1344         if (new_ssid == NULL)
1345                 return -1;
1346         *new_ssid++ = '\0';
1347
1348         new_auth = os_strchr(new_ssid, ' ');
1349         if (new_auth == NULL)
1350                 return -1;
1351         *new_auth++ = '\0';
1352
1353         new_encr = os_strchr(new_auth, ' ');
1354         if (new_encr == NULL)
1355                 return -1;
1356         *new_encr++ = '\0';
1357
1358         new_key = os_strchr(new_encr, ' ');
1359         if (new_key == NULL)
1360                 return -1;
1361         *new_key++ = '\0';
1362
1363         os_memset(&ap, 0, sizeof(ap));
1364         ap.ssid_hex = new_ssid;
1365         ap.auth = new_auth;
1366         ap.encr = new_encr;
1367         ap.key_hex = new_key;
1368         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1369 }
1370
1371
1372 #ifdef CONFIG_WPS_NFC
1373 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1374         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1375 {
1376         int ndef;
1377         struct wpabuf *buf;
1378         int res;
1379         char *uuid;
1380
1381         uuid = os_strchr(cmd, ' ');
1382         if (uuid == NULL)
1383                 return -1;
1384         *uuid++ = '\0';
1385
1386         if (os_strcmp(cmd, "WPS") == 0)
1387                 ndef = 0;
1388         else if (os_strcmp(cmd, "NDEF") == 0)
1389                 ndef = 1;
1390         else
1391                 return -1;
1392
1393         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1394         if (buf == NULL)
1395                 return -1;
1396
1397         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1398                                          wpabuf_len(buf));
1399         reply[res++] = '\n';
1400         reply[res] = '\0';
1401
1402         wpabuf_free(buf);
1403
1404         return res;
1405 }
1406 #endif /* CONFIG_WPS_NFC */
1407 #endif /* CONFIG_WPS_ER */
1408
1409 #endif /* CONFIG_WPS */
1410
1411
1412 #ifdef CONFIG_IBSS_RSN
1413 static int wpa_supplicant_ctrl_iface_ibss_rsn(
1414         struct wpa_supplicant *wpa_s, char *addr)
1415 {
1416         u8 peer[ETH_ALEN];
1417
1418         if (hwaddr_aton(addr, peer)) {
1419                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1420                            "address '%s'", addr);
1421                 return -1;
1422         }
1423
1424         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1425                    MAC2STR(peer));
1426
1427         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1428 }
1429 #endif /* CONFIG_IBSS_RSN */
1430
1431
1432 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1433                                               char *rsp)
1434 {
1435 #ifdef IEEE8021X_EAPOL
1436         char *pos, *id_pos;
1437         int id;
1438         struct wpa_ssid *ssid;
1439
1440         pos = os_strchr(rsp, '-');
1441         if (pos == NULL)
1442                 return -1;
1443         *pos++ = '\0';
1444         id_pos = pos;
1445         pos = os_strchr(pos, ':');
1446         if (pos == NULL)
1447                 return -1;
1448         *pos++ = '\0';
1449         id = atoi(id_pos);
1450         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
1451         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1452                               (u8 *) pos, os_strlen(pos));
1453
1454         ssid = wpa_config_get_network(wpa_s->conf, id);
1455         if (ssid == NULL) {
1456                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1457                            "to update", id);
1458                 return -1;
1459         }
1460
1461         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
1462                                                          pos);
1463 #else /* IEEE8021X_EAPOL */
1464         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1465         return -1;
1466 #endif /* IEEE8021X_EAPOL */
1467 }
1468
1469
1470 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
1471                                             const char *params,
1472                                             char *buf, size_t buflen)
1473 {
1474         char *pos, *end, tmp[30];
1475         int res, verbose, wps, ret;
1476 #ifdef CONFIG_HS20
1477         const u8 *hs20;
1478 #endif /* CONFIG_HS20 */
1479
1480         if (os_strcmp(params, "-DRIVER") == 0)
1481                 return wpa_drv_status(wpa_s, buf, buflen);
1482         verbose = os_strcmp(params, "-VERBOSE") == 0;
1483         wps = os_strcmp(params, "-WPS") == 0;
1484         pos = buf;
1485         end = buf + buflen;
1486         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1487                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1488                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1489                                   MAC2STR(wpa_s->bssid));
1490                 if (ret < 0 || ret >= end - pos)
1491                         return pos - buf;
1492                 pos += ret;
1493                 if (ssid) {
1494                         u8 *_ssid = ssid->ssid;
1495                         size_t ssid_len = ssid->ssid_len;
1496                         u8 ssid_buf[MAX_SSID_LEN];
1497                         if (ssid_len == 0) {
1498                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1499                                 if (_res < 0)
1500                                         ssid_len = 0;
1501                                 else
1502                                         ssid_len = _res;
1503                                 _ssid = ssid_buf;
1504                         }
1505                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1506                                           wpa_ssid_txt(_ssid, ssid_len),
1507                                           ssid->id);
1508                         if (ret < 0 || ret >= end - pos)
1509                                 return pos - buf;
1510                         pos += ret;
1511
1512                         if (wps && ssid->passphrase &&
1513                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1514                             (ssid->mode == WPAS_MODE_AP ||
1515                              ssid->mode == WPAS_MODE_P2P_GO)) {
1516                                 ret = os_snprintf(pos, end - pos,
1517                                                   "passphrase=%s\n",
1518                                                   ssid->passphrase);
1519                                 if (ret < 0 || ret >= end - pos)
1520                                         return pos - buf;
1521                                 pos += ret;
1522                         }
1523                         if (ssid->id_str) {
1524                                 ret = os_snprintf(pos, end - pos,
1525                                                   "id_str=%s\n",
1526                                                   ssid->id_str);
1527                                 if (ret < 0 || ret >= end - pos)
1528                                         return pos - buf;
1529                                 pos += ret;
1530                         }
1531
1532                         switch (ssid->mode) {
1533                         case WPAS_MODE_INFRA:
1534                                 ret = os_snprintf(pos, end - pos,
1535                                                   "mode=station\n");
1536                                 break;
1537                         case WPAS_MODE_IBSS:
1538                                 ret = os_snprintf(pos, end - pos,
1539                                                   "mode=IBSS\n");
1540                                 break;
1541                         case WPAS_MODE_AP:
1542                                 ret = os_snprintf(pos, end - pos,
1543                                                   "mode=AP\n");
1544                                 break;
1545                         case WPAS_MODE_P2P_GO:
1546                                 ret = os_snprintf(pos, end - pos,
1547                                                   "mode=P2P GO\n");
1548                                 break;
1549                         case WPAS_MODE_P2P_GROUP_FORMATION:
1550                                 ret = os_snprintf(pos, end - pos,
1551                                                   "mode=P2P GO - group "
1552                                                   "formation\n");
1553                                 break;
1554                         default:
1555                                 ret = 0;
1556                                 break;
1557                         }
1558                         if (ret < 0 || ret >= end - pos)
1559                                 return pos - buf;
1560                         pos += ret;
1561                 }
1562
1563 #ifdef CONFIG_AP
1564                 if (wpa_s->ap_iface) {
1565                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1566                                                             end - pos,
1567                                                             verbose);
1568                 } else
1569 #endif /* CONFIG_AP */
1570                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1571         }
1572 #ifdef CONFIG_SAE
1573         if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
1574 #ifdef CONFIG_AP
1575             !wpa_s->ap_iface &&
1576 #endif /* CONFIG_AP */
1577             wpa_s->sme.sae.state == SAE_ACCEPTED) {
1578                 ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
1579                                   wpa_s->sme.sae.group);
1580                 if (ret < 0 || ret >= end - pos)
1581                         return pos - buf;
1582                 pos += ret;
1583         }
1584 #endif /* CONFIG_SAE */
1585         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1586                           wpa_supplicant_state_txt(wpa_s->wpa_state));
1587         if (ret < 0 || ret >= end - pos)
1588                 return pos - buf;
1589         pos += ret;
1590
1591         if (wpa_s->l2 &&
1592             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1593                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1594                 if (ret < 0 || ret >= end - pos)
1595                         return pos - buf;
1596                 pos += ret;
1597         }
1598
1599 #ifdef CONFIG_P2P
1600         if (wpa_s->global->p2p) {
1601                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1602                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1603                 if (ret < 0 || ret >= end - pos)
1604                         return pos - buf;
1605                 pos += ret;
1606         }
1607 #endif /* CONFIG_P2P */
1608
1609         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1610                           MAC2STR(wpa_s->own_addr));
1611         if (ret < 0 || ret >= end - pos)
1612                 return pos - buf;
1613         pos += ret;
1614
1615 #ifdef CONFIG_HS20
1616         if (wpa_s->current_bss &&
1617             (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
1618                                           HS20_IE_VENDOR_TYPE)) &&
1619             wpa_s->wpa_proto == WPA_PROTO_RSN &&
1620             wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1621                 int release = 1;
1622                 if (hs20[1] >= 5) {
1623                         u8 rel_num = (hs20[6] & 0xf0) >> 4;
1624                         release = rel_num + 1;
1625                 }
1626                 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
1627                 if (ret < 0 || ret >= end - pos)
1628                         return pos - buf;
1629                 pos += ret;
1630         }
1631
1632         if (wpa_s->current_ssid) {
1633                 struct wpa_cred *cred;
1634                 char *type;
1635
1636                 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1637                         size_t i;
1638
1639                         if (wpa_s->current_ssid->parent_cred != cred)
1640                                 continue;
1641
1642                         if (cred->provisioning_sp) {
1643                                 ret = os_snprintf(pos, end - pos,
1644                                                   "provisioning_sp=%s\n",
1645                                                   cred->provisioning_sp);
1646                                 if (ret < 0 || ret >= end - pos)
1647                                         return pos - buf;
1648                                 pos += ret;
1649                         }
1650
1651                         if (!cred->domain)
1652                                 goto no_domain;
1653
1654                         i = 0;
1655                         if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
1656                                 struct wpabuf *names =
1657                                         wpa_s->current_bss->anqp->domain_name;
1658                                 for (i = 0; names && i < cred->num_domain; i++)
1659                                 {
1660                                         if (domain_name_list_contains(
1661                                                     names, cred->domain[i], 1))
1662                                                 break;
1663                                 }
1664                                 if (i == cred->num_domain)
1665                                         i = 0; /* show first entry by default */
1666                         }
1667                         ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
1668                                           cred->domain[i]);
1669                         if (ret < 0 || ret >= end - pos)
1670                                 return pos - buf;
1671                         pos += ret;
1672
1673                 no_domain:
1674                         if (wpa_s->current_bss == NULL ||
1675                             wpa_s->current_bss->anqp == NULL)
1676                                 res = -1;
1677                         else
1678                                 res = interworking_home_sp_cred(
1679                                         wpa_s, cred,
1680                                         wpa_s->current_bss->anqp->domain_name);
1681                         if (res > 0)
1682                                 type = "home";
1683                         else if (res == 0)
1684                                 type = "roaming";
1685                         else
1686                                 type = "unknown";
1687
1688                         ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
1689                         if (ret < 0 || ret >= end - pos)
1690                                 return pos - buf;
1691                         pos += ret;
1692
1693                         break;
1694                 }
1695         }
1696 #endif /* CONFIG_HS20 */
1697
1698         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1699             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1700                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1701                                           verbose);
1702                 if (res >= 0)
1703                         pos += res;
1704         }
1705
1706         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1707         if (res >= 0)
1708                 pos += res;
1709
1710 #ifdef CONFIG_WPS
1711         {
1712                 char uuid_str[100];
1713                 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
1714                 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
1715                 if (ret < 0 || ret >= end - pos)
1716                         return pos - buf;
1717                 pos += ret;
1718         }
1719 #endif /* CONFIG_WPS */
1720
1721 #ifdef ANDROID
1722         wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1723                      "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1724                      wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1725                      wpa_s->wpa_state,
1726                      MAC2STR(wpa_s->bssid),
1727                      wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1728                      wpa_ssid_txt(wpa_s->current_ssid->ssid,
1729                                   wpa_s->current_ssid->ssid_len) : "");
1730         if (wpa_s->wpa_state == WPA_COMPLETED) {
1731                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1732                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
1733                              "- connection to " MACSTR
1734                              " completed %s [id=%d id_str=%s]",
1735                              MAC2STR(wpa_s->bssid), "(auth)",
1736                              ssid ? ssid->id : -1,
1737                              ssid && ssid->id_str ? ssid->id_str : "");
1738         }
1739 #endif /* ANDROID */
1740
1741         return pos - buf;
1742 }
1743
1744
1745 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
1746                                            char *cmd)
1747 {
1748         char *pos;
1749         int id;
1750         struct wpa_ssid *ssid;
1751         u8 bssid[ETH_ALEN];
1752
1753         /* cmd: "<network id> <BSSID>" */
1754         pos = os_strchr(cmd, ' ');
1755         if (pos == NULL)
1756                 return -1;
1757         *pos++ = '\0';
1758         id = atoi(cmd);
1759         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
1760         if (hwaddr_aton(pos, bssid)) {
1761                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
1762                 return -1;
1763         }
1764
1765         ssid = wpa_config_get_network(wpa_s->conf, id);
1766         if (ssid == NULL) {
1767                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1768                            "to update", id);
1769                 return -1;
1770         }
1771
1772         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
1773         ssid->bssid_set = !is_zero_ether_addr(bssid);
1774
1775         return 0;
1776 }
1777
1778
1779 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1780                                                char *cmd, char *buf,
1781                                                size_t buflen)
1782 {
1783         u8 bssid[ETH_ALEN];
1784         struct wpa_blacklist *e;
1785         char *pos, *end;
1786         int ret;
1787
1788         /* cmd: "BLACKLIST [<BSSID>]" */
1789         if (*cmd == '\0') {
1790                 pos = buf;
1791                 end = buf + buflen;
1792                 e = wpa_s->blacklist;
1793                 while (e) {
1794                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
1795                                           MAC2STR(e->bssid));
1796                         if (ret < 0 || ret >= end - pos)
1797                                 return pos - buf;
1798                         pos += ret;
1799                         e = e->next;
1800                 }
1801                 return pos - buf;
1802         }
1803
1804         cmd++;
1805         if (os_strncmp(cmd, "clear", 5) == 0) {
1806                 wpa_blacklist_clear(wpa_s);
1807                 os_memcpy(buf, "OK\n", 3);
1808                 return 3;
1809         }
1810
1811         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1812         if (hwaddr_aton(cmd, bssid)) {
1813                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
1814                 return -1;
1815         }
1816
1817         /*
1818          * Add the BSSID twice, so its count will be 2, causing it to be
1819          * skipped when processing scan results.
1820          */
1821         ret = wpa_blacklist_add(wpa_s, bssid);
1822         if (ret != 0)
1823                 return -1;
1824         ret = wpa_blacklist_add(wpa_s, bssid);
1825         if (ret != 0)
1826                 return -1;
1827         os_memcpy(buf, "OK\n", 3);
1828         return 3;
1829 }
1830
1831
1832 static const char * debug_level_str(int level)
1833 {
1834         switch (level) {
1835         case MSG_EXCESSIVE:
1836                 return "EXCESSIVE";
1837         case MSG_MSGDUMP:
1838                 return "MSGDUMP";
1839         case MSG_DEBUG:
1840                 return "DEBUG";
1841         case MSG_INFO:
1842                 return "INFO";
1843         case MSG_WARNING:
1844                 return "WARNING";
1845         case MSG_ERROR:
1846                 return "ERROR";
1847         default:
1848                 return "?";
1849         }
1850 }
1851
1852
1853 static int str_to_debug_level(const char *s)
1854 {
1855         if (os_strcasecmp(s, "EXCESSIVE") == 0)
1856                 return MSG_EXCESSIVE;
1857         if (os_strcasecmp(s, "MSGDUMP") == 0)
1858                 return MSG_MSGDUMP;
1859         if (os_strcasecmp(s, "DEBUG") == 0)
1860                 return MSG_DEBUG;
1861         if (os_strcasecmp(s, "INFO") == 0)
1862                 return MSG_INFO;
1863         if (os_strcasecmp(s, "WARNING") == 0)
1864                 return MSG_WARNING;
1865         if (os_strcasecmp(s, "ERROR") == 0)
1866                 return MSG_ERROR;
1867         return -1;
1868 }
1869
1870
1871 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
1872                                                char *cmd, char *buf,
1873                                                size_t buflen)
1874 {
1875         char *pos, *end, *stamp;
1876         int ret;
1877
1878         if (cmd == NULL) {
1879                 return -1;
1880         }
1881
1882         /* cmd: "LOG_LEVEL [<level>]" */
1883         if (*cmd == '\0') {
1884                 pos = buf;
1885                 end = buf + buflen;
1886                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1887                                   "Timestamp: %d\n",
1888                                   debug_level_str(wpa_debug_level),
1889                                   wpa_debug_timestamp);
1890                 if (ret < 0 || ret >= end - pos)
1891                         ret = 0;
1892
1893                 return ret;
1894         }
1895
1896         while (*cmd == ' ')
1897                 cmd++;
1898
1899         stamp = os_strchr(cmd, ' ');
1900         if (stamp) {
1901                 *stamp++ = '\0';
1902                 while (*stamp == ' ') {
1903                         stamp++;
1904                 }
1905         }
1906
1907         if (cmd && os_strlen(cmd)) {
1908                 int level = str_to_debug_level(cmd);
1909                 if (level < 0)
1910                         return -1;
1911                 wpa_debug_level = level;
1912         }
1913
1914         if (stamp && os_strlen(stamp))
1915                 wpa_debug_timestamp = atoi(stamp);
1916
1917         os_memcpy(buf, "OK\n", 3);
1918         return 3;
1919 }
1920
1921
1922 static int wpa_supplicant_ctrl_iface_list_networks(
1923         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1924 {
1925         char *pos, *end;
1926         struct wpa_ssid *ssid;
1927         int ret;
1928
1929         pos = buf;
1930         end = buf + buflen;
1931         ret = os_snprintf(pos, end - pos,
1932                           "network id / ssid / bssid / flags\n");
1933         if (ret < 0 || ret >= end - pos)
1934                 return pos - buf;
1935         pos += ret;
1936
1937         ssid = wpa_s->conf->ssid;
1938         while (ssid) {
1939                 ret = os_snprintf(pos, end - pos, "%d\t%s",
1940                                   ssid->id,
1941                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1942                 if (ret < 0 || ret >= end - pos)
1943                         return pos - buf;
1944                 pos += ret;
1945                 if (ssid->bssid_set) {
1946                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1947                                           MAC2STR(ssid->bssid));
1948                 } else {
1949                         ret = os_snprintf(pos, end - pos, "\tany");
1950                 }
1951                 if (ret < 0 || ret >= end - pos)
1952                         return pos - buf;
1953                 pos += ret;
1954                 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
1955                                   ssid == wpa_s->current_ssid ?
1956                                   "[CURRENT]" : "",
1957                                   ssid->disabled ? "[DISABLED]" : "",
1958                                   ssid->disabled_until.sec ?
1959                                   "[TEMP-DISABLED]" : "",
1960                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1961                                   "");
1962                 if (ret < 0 || ret >= end - pos)
1963                         return pos - buf;
1964                 pos += ret;
1965                 ret = os_snprintf(pos, end - pos, "\n");
1966                 if (ret < 0 || ret >= end - pos)
1967                         return pos - buf;
1968                 pos += ret;
1969
1970                 ssid = ssid->next;
1971         }
1972
1973         return pos - buf;
1974 }
1975
1976
1977 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1978 {
1979         int ret;
1980         ret = os_snprintf(pos, end - pos, "-");
1981         if (ret < 0 || ret >= end - pos)
1982                 return pos;
1983         pos += ret;
1984         ret = wpa_write_ciphers(pos, end, cipher, "+");
1985         if (ret < 0)
1986                 return pos;
1987         pos += ret;
1988         return pos;
1989 }
1990
1991
1992 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1993                                     const u8 *ie, size_t ie_len)
1994 {
1995         struct wpa_ie_data data;
1996         char *start;
1997         int ret;
1998
1999         ret = os_snprintf(pos, end - pos, "[%s-", proto);
2000         if (ret < 0 || ret >= end - pos)
2001                 return pos;
2002         pos += ret;
2003
2004         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2005                 ret = os_snprintf(pos, end - pos, "?]");
2006                 if (ret < 0 || ret >= end - pos)
2007                         return pos;
2008                 pos += ret;
2009                 return pos;
2010         }
2011
2012         start = pos;
2013         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2014                 ret = os_snprintf(pos, end - pos, "%sEAP",
2015                                   pos == start ? "" : "+");
2016                 if (ret < 0 || ret >= end - pos)
2017                         return pos;
2018                 pos += ret;
2019         }
2020         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2021                 ret = os_snprintf(pos, end - pos, "%sPSK",
2022                                   pos == start ? "" : "+");
2023                 if (ret < 0 || ret >= end - pos)
2024                         return pos;
2025                 pos += ret;
2026         }
2027         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2028                 ret = os_snprintf(pos, end - pos, "%sNone",
2029                                   pos == start ? "" : "+");
2030                 if (ret < 0 || ret >= end - pos)
2031                         return pos;
2032                 pos += ret;
2033         }
2034 #ifdef CONFIG_IEEE80211R
2035         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2036                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2037                                   pos == start ? "" : "+");
2038                 if (ret < 0 || ret >= end - pos)
2039                         return pos;
2040                 pos += ret;
2041         }
2042         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2043                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2044                                   pos == start ? "" : "+");
2045                 if (ret < 0 || ret >= end - pos)
2046                         return pos;
2047                 pos += ret;
2048         }
2049 #endif /* CONFIG_IEEE80211R */
2050 #ifdef CONFIG_IEEE80211W
2051         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2052                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2053                                   pos == start ? "" : "+");
2054                 if (ret < 0 || ret >= end - pos)
2055                         return pos;
2056                 pos += ret;
2057         }
2058         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2059                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2060                                   pos == start ? "" : "+");
2061                 if (ret < 0 || ret >= end - pos)
2062                         return pos;
2063                 pos += ret;
2064         }
2065 #endif /* CONFIG_IEEE80211W */
2066
2067         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2068
2069         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2070                 ret = os_snprintf(pos, end - pos, "-preauth");
2071                 if (ret < 0 || ret >= end - pos)
2072                         return pos;
2073                 pos += ret;
2074         }
2075
2076         ret = os_snprintf(pos, end - pos, "]");
2077         if (ret < 0 || ret >= end - pos)
2078                 return pos;
2079         pos += ret;
2080
2081         return pos;
2082 }
2083
2084
2085 #ifdef CONFIG_WPS
2086 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2087                                             char *pos, char *end,
2088                                             struct wpabuf *wps_ie)
2089 {
2090         int ret;
2091         const char *txt;
2092
2093         if (wps_ie == NULL)
2094                 return pos;
2095         if (wps_is_selected_pbc_registrar(wps_ie))
2096                 txt = "[WPS-PBC]";
2097 #ifdef CONFIG_WPS2
2098         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2099                 txt = "[WPS-AUTH]";
2100 #endif /* CONFIG_WPS2 */
2101         else if (wps_is_selected_pin_registrar(wps_ie))
2102                 txt = "[WPS-PIN]";
2103         else
2104                 txt = "[WPS]";
2105
2106         ret = os_snprintf(pos, end - pos, "%s", txt);
2107         if (ret >= 0 && ret < end - pos)
2108                 pos += ret;
2109         wpabuf_free(wps_ie);
2110         return pos;
2111 }
2112 #endif /* CONFIG_WPS */
2113
2114
2115 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2116                                         char *pos, char *end,
2117                                         const struct wpa_bss *bss)
2118 {
2119 #ifdef CONFIG_WPS
2120         struct wpabuf *wps_ie;
2121         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2122         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2123 #else /* CONFIG_WPS */
2124         return pos;
2125 #endif /* CONFIG_WPS */
2126 }
2127
2128
2129 /* Format one result on one text line into a buffer. */
2130 static int wpa_supplicant_ctrl_iface_scan_result(
2131         struct wpa_supplicant *wpa_s,
2132         const struct wpa_bss *bss, char *buf, size_t buflen)
2133 {
2134         char *pos, *end;
2135         int ret;
2136         const u8 *ie, *ie2, *p2p;
2137
2138         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2139         if (!p2p)
2140                 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2141         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2142             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2143             0)
2144                 return 0; /* Do not show P2P listen discovery results here */
2145
2146         pos = buf;
2147         end = buf + buflen;
2148
2149         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2150                           MAC2STR(bss->bssid), bss->freq, bss->level);
2151         if (ret < 0 || ret >= end - pos)
2152                 return -1;
2153         pos += ret;
2154         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2155         if (ie)
2156                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2157         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2158         if (ie2)
2159                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2160         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2161         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2162                 ret = os_snprintf(pos, end - pos, "[WEP]");
2163                 if (ret < 0 || ret >= end - pos)
2164                         return -1;
2165                 pos += ret;
2166         }
2167         if (bss->caps & IEEE80211_CAP_IBSS) {
2168                 ret = os_snprintf(pos, end - pos, "[IBSS]");
2169                 if (ret < 0 || ret >= end - pos)
2170                         return -1;
2171                 pos += ret;
2172         }
2173         if (bss->caps & IEEE80211_CAP_ESS) {
2174                 ret = os_snprintf(pos, end - pos, "[ESS]");
2175                 if (ret < 0 || ret >= end - pos)
2176                         return -1;
2177                 pos += ret;
2178         }
2179         if (p2p) {
2180                 ret = os_snprintf(pos, end - pos, "[P2P]");
2181                 if (ret < 0 || ret >= end - pos)
2182                         return -1;
2183                 pos += ret;
2184         }
2185 #ifdef CONFIG_HS20
2186         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2187                 ret = os_snprintf(pos, end - pos, "[HS20]");
2188                 if (ret < 0 || ret >= end - pos)
2189                         return -1;
2190                 pos += ret;
2191         }
2192 #endif /* CONFIG_HS20 */
2193
2194         ret = os_snprintf(pos, end - pos, "\t%s",
2195                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
2196         if (ret < 0 || ret >= end - pos)
2197                 return -1;
2198         pos += ret;
2199
2200         ret = os_snprintf(pos, end - pos, "\n");
2201         if (ret < 0 || ret >= end - pos)
2202                 return -1;
2203         pos += ret;
2204
2205         return pos - buf;
2206 }
2207
2208
2209 static int wpa_supplicant_ctrl_iface_scan_results(
2210         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2211 {
2212         char *pos, *end;
2213         struct wpa_bss *bss;
2214         int ret;
2215
2216         pos = buf;
2217         end = buf + buflen;
2218         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2219                           "flags / ssid\n");
2220         if (ret < 0 || ret >= end - pos)
2221                 return pos - buf;
2222         pos += ret;
2223
2224         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2225                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2226                                                             end - pos);
2227                 if (ret < 0 || ret >= end - pos)
2228                         return pos - buf;
2229                 pos += ret;
2230         }
2231
2232         return pos - buf;
2233 }
2234
2235
2236 static int wpa_supplicant_ctrl_iface_select_network(
2237         struct wpa_supplicant *wpa_s, char *cmd)
2238 {
2239         int id;
2240         struct wpa_ssid *ssid;
2241
2242         /* cmd: "<network id>" or "any" */
2243         if (os_strcmp(cmd, "any") == 0) {
2244                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2245                 ssid = NULL;
2246         } else {
2247                 id = atoi(cmd);
2248                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2249
2250                 ssid = wpa_config_get_network(wpa_s->conf, id);
2251                 if (ssid == NULL) {
2252                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2253                                    "network id=%d", id);
2254                         return -1;
2255                 }
2256                 if (ssid->disabled == 2) {
2257                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2258                                    "SELECT_NETWORK with persistent P2P group");
2259                         return -1;
2260                 }
2261         }
2262
2263         wpa_supplicant_select_network(wpa_s, ssid);
2264
2265         return 0;
2266 }
2267
2268
2269 static int wpa_supplicant_ctrl_iface_enable_network(
2270         struct wpa_supplicant *wpa_s, char *cmd)
2271 {
2272         int id;
2273         struct wpa_ssid *ssid;
2274
2275         /* cmd: "<network id>" or "all" */
2276         if (os_strcmp(cmd, "all") == 0) {
2277                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2278                 ssid = NULL;
2279         } else {
2280                 id = atoi(cmd);
2281                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2282
2283                 ssid = wpa_config_get_network(wpa_s->conf, id);
2284                 if (ssid == NULL) {
2285                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2286                                    "network id=%d", id);
2287                         return -1;
2288                 }
2289                 if (ssid->disabled == 2) {
2290                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2291                                    "ENABLE_NETWORK with persistent P2P group");
2292                         return -1;
2293                 }
2294
2295                 if (os_strstr(cmd, " no-connect")) {
2296                         ssid->disabled = 0;
2297                         return 0;
2298                 }
2299         }
2300         wpa_supplicant_enable_network(wpa_s, ssid);
2301
2302         return 0;
2303 }
2304
2305
2306 static int wpa_supplicant_ctrl_iface_disable_network(
2307         struct wpa_supplicant *wpa_s, char *cmd)
2308 {
2309         int id;
2310         struct wpa_ssid *ssid;
2311
2312         /* cmd: "<network id>" or "all" */
2313         if (os_strcmp(cmd, "all") == 0) {
2314                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2315                 ssid = NULL;
2316         } else {
2317                 id = atoi(cmd);
2318                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2319
2320                 ssid = wpa_config_get_network(wpa_s->conf, id);
2321                 if (ssid == NULL) {
2322                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2323                                    "network id=%d", id);
2324                         return -1;
2325                 }
2326                 if (ssid->disabled == 2) {
2327                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2328                                    "DISABLE_NETWORK with persistent P2P "
2329                                    "group");
2330                         return -1;
2331                 }
2332         }
2333         wpa_supplicant_disable_network(wpa_s, ssid);
2334
2335         return 0;
2336 }
2337
2338
2339 static int wpa_supplicant_ctrl_iface_add_network(
2340         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2341 {
2342         struct wpa_ssid *ssid;
2343         int ret;
2344
2345         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2346
2347         ssid = wpa_config_add_network(wpa_s->conf);
2348         if (ssid == NULL)
2349                 return -1;
2350
2351         wpas_notify_network_added(wpa_s, ssid);
2352
2353         ssid->disabled = 1;
2354         wpa_config_set_network_defaults(ssid);
2355
2356         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2357         if (ret < 0 || (size_t) ret >= buflen)
2358                 return -1;
2359         return ret;
2360 }
2361
2362
2363 static int wpa_supplicant_ctrl_iface_remove_network(
2364         struct wpa_supplicant *wpa_s, char *cmd)
2365 {
2366         int id;
2367         struct wpa_ssid *ssid;
2368         int was_disabled;
2369
2370         /* cmd: "<network id>" or "all" */
2371         if (os_strcmp(cmd, "all") == 0) {
2372                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2373                 if (wpa_s->sched_scanning)
2374                         wpa_supplicant_cancel_sched_scan(wpa_s);
2375
2376                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2377                 if (wpa_s->current_ssid) {
2378 #ifdef CONFIG_SME
2379                         wpa_s->sme.prev_bssid_set = 0;
2380 #endif /* CONFIG_SME */
2381                         wpa_sm_set_config(wpa_s->wpa, NULL);
2382                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2383                         wpa_supplicant_deauthenticate(
2384                                 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2385                 }
2386                 ssid = wpa_s->conf->ssid;
2387                 while (ssid) {
2388                         struct wpa_ssid *remove_ssid = ssid;
2389                         id = ssid->id;
2390                         ssid = ssid->next;
2391                         wpas_notify_network_removed(wpa_s, remove_ssid);
2392                         wpa_config_remove_network(wpa_s->conf, id);
2393                 }
2394                 return 0;
2395         }
2396
2397         id = atoi(cmd);
2398         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2399
2400         ssid = wpa_config_get_network(wpa_s->conf, id);
2401         if (ssid)
2402                 wpas_notify_network_removed(wpa_s, ssid);
2403         if (ssid == NULL) {
2404                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2405                            "id=%d", id);
2406                 return -1;
2407         }
2408
2409         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2410 #ifdef CONFIG_SME
2411                 wpa_s->sme.prev_bssid_set = 0;
2412 #endif /* CONFIG_SME */
2413                 /*
2414                  * Invalidate the EAP session cache if the current or
2415                  * previously used network is removed.
2416                  */
2417                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2418         }
2419
2420         if (ssid == wpa_s->current_ssid) {
2421                 wpa_sm_set_config(wpa_s->wpa, NULL);
2422                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2423
2424                 wpa_supplicant_deauthenticate(wpa_s,
2425                                               WLAN_REASON_DEAUTH_LEAVING);
2426         }
2427
2428         was_disabled = ssid->disabled;
2429
2430         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2431                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2432                            "network id=%d", id);
2433                 return -1;
2434         }
2435
2436         if (!was_disabled && wpa_s->sched_scanning) {
2437                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2438                            "network from filters");
2439                 wpa_supplicant_cancel_sched_scan(wpa_s);
2440                 wpa_supplicant_req_scan(wpa_s, 0, 0);
2441         }
2442
2443         return 0;
2444 }
2445
2446
2447 static int wpa_supplicant_ctrl_iface_set_network(
2448         struct wpa_supplicant *wpa_s, char *cmd)
2449 {
2450         int id;
2451         struct wpa_ssid *ssid;
2452         char *name, *value;
2453
2454         /* cmd: "<network id> <variable name> <value>" */
2455         name = os_strchr(cmd, ' ');
2456         if (name == NULL)
2457                 return -1;
2458         *name++ = '\0';
2459
2460         value = os_strchr(name, ' ');
2461         if (value == NULL)
2462                 return -1;
2463         *value++ = '\0';
2464
2465         id = atoi(cmd);
2466         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2467                    id, name);
2468         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2469                               (u8 *) value, os_strlen(value));
2470
2471         ssid = wpa_config_get_network(wpa_s->conf, id);
2472         if (ssid == NULL) {
2473                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2474                            "id=%d", id);
2475                 return -1;
2476         }
2477
2478         if (wpa_config_set(ssid, name, value, 0) < 0) {
2479                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2480                            "variable '%s'", name);
2481                 return -1;
2482         }
2483
2484         if (os_strcmp(name, "bssid") != 0 &&
2485             os_strcmp(name, "priority") != 0)
2486                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2487
2488         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2489                 /*
2490                  * Invalidate the EAP session cache if anything in the current
2491                  * or previously used configuration changes.
2492                  */
2493                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2494         }
2495
2496         if ((os_strcmp(name, "psk") == 0 &&
2497              value[0] == '"' && ssid->ssid_len) ||
2498             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2499                 wpa_config_update_psk(ssid);
2500         else if (os_strcmp(name, "priority") == 0)
2501                 wpa_config_update_prio_list(wpa_s->conf);
2502
2503         return 0;
2504 }
2505
2506
2507 static int wpa_supplicant_ctrl_iface_get_network(
2508         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2509 {
2510         int id;
2511         size_t res;
2512         struct wpa_ssid *ssid;
2513         char *name, *value;
2514
2515         /* cmd: "<network id> <variable name>" */
2516         name = os_strchr(cmd, ' ');
2517         if (name == NULL || buflen == 0)
2518                 return -1;
2519         *name++ = '\0';
2520
2521         id = atoi(cmd);
2522         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
2523                    id, name);
2524
2525         ssid = wpa_config_get_network(wpa_s->conf, id);
2526         if (ssid == NULL) {
2527                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2528                            "id=%d", id);
2529                 return -1;
2530         }
2531
2532         value = wpa_config_get_no_key(ssid, name);
2533         if (value == NULL) {
2534                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
2535                            "variable '%s'", name);
2536                 return -1;
2537         }
2538
2539         res = os_strlcpy(buf, value, buflen);
2540         if (res >= buflen) {
2541                 os_free(value);
2542                 return -1;
2543         }
2544
2545         os_free(value);
2546
2547         return res;
2548 }
2549
2550
2551 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
2552                                                 char *buf, size_t buflen)
2553 {
2554         char *pos, *end;
2555         struct wpa_cred *cred;
2556         int ret;
2557
2558         pos = buf;
2559         end = buf + buflen;
2560         ret = os_snprintf(pos, end - pos,
2561                           "cred id / realm / username / domain / imsi\n");
2562         if (ret < 0 || ret >= end - pos)
2563                 return pos - buf;
2564         pos += ret;
2565
2566         cred = wpa_s->conf->cred;
2567         while (cred) {
2568                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
2569                                   cred->id, cred->realm ? cred->realm : "",
2570                                   cred->username ? cred->username : "",
2571                                   cred->domain ? cred->domain[0] : "",
2572                                   cred->imsi ? cred->imsi : "");
2573                 if (ret < 0 || ret >= end - pos)
2574                         return pos - buf;
2575                 pos += ret;
2576
2577                 cred = cred->next;
2578         }
2579
2580         return pos - buf;
2581 }
2582
2583
2584 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2585                                               char *buf, size_t buflen)
2586 {
2587         struct wpa_cred *cred;
2588         int ret;
2589
2590         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2591
2592         cred = wpa_config_add_cred(wpa_s->conf);
2593         if (cred == NULL)
2594                 return -1;
2595
2596         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2597         if (ret < 0 || (size_t) ret >= buflen)
2598                 return -1;
2599         return ret;
2600 }
2601
2602
2603 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
2604                                  struct wpa_cred *cred)
2605 {
2606         struct wpa_ssid *ssid;
2607         char str[20];
2608
2609         if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) {
2610                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
2611                 return -1;
2612         }
2613
2614         /* Remove any network entry created based on the removed credential */
2615         ssid = wpa_s->conf->ssid;
2616         while (ssid) {
2617                 if (ssid->parent_cred == cred) {
2618                         wpa_printf(MSG_DEBUG, "Remove network id %d since it "
2619                                    "used the removed credential", ssid->id);
2620                         os_snprintf(str, sizeof(str), "%d", ssid->id);
2621                         ssid = ssid->next;
2622                         wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
2623                 } else
2624                         ssid = ssid->next;
2625         }
2626
2627         return 0;
2628 }
2629
2630
2631 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2632                                                  char *cmd)
2633 {
2634         int id;
2635         struct wpa_cred *cred, *prev;
2636
2637         /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
2638          * "provisioning_sp=<FQDN> */
2639         if (os_strcmp(cmd, "all") == 0) {
2640                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2641                 cred = wpa_s->conf->cred;
2642                 while (cred) {
2643                         prev = cred;
2644                         cred = cred->next;
2645                         wpas_ctrl_remove_cred(wpa_s, prev);
2646                 }
2647                 return 0;
2648         }
2649
2650         if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
2651                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
2652                            cmd + 8);
2653                 cred = wpa_s->conf->cred;
2654                 while (cred) {
2655                         prev = cred;
2656                         cred = cred->next;
2657                         if (prev->domain) {
2658                                 size_t i;
2659                                 for (i = 0; i < prev->num_domain; i++) {
2660                                         if (os_strcmp(prev->domain[i], cmd + 8)
2661                                             != 0)
2662                                                 continue;
2663                                         wpas_ctrl_remove_cred(wpa_s, prev);
2664                                         break;
2665                                 }
2666                         }
2667                 }
2668                 return 0;
2669         }
2670
2671         if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
2672                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
2673                            cmd + 16);
2674                 cred = wpa_s->conf->cred;
2675                 while (cred) {
2676                         prev = cred;
2677                         cred = cred->next;
2678                         if (prev->provisioning_sp &&
2679                             os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
2680                                 wpas_ctrl_remove_cred(wpa_s, prev);
2681                 }
2682                 return 0;
2683         }
2684
2685         id = atoi(cmd);
2686         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2687
2688         cred = wpa_config_get_cred(wpa_s->conf, id);
2689         return wpas_ctrl_remove_cred(wpa_s, cred);
2690 }
2691
2692
2693 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2694                                               char *cmd)
2695 {
2696         int id;
2697         struct wpa_cred *cred;
2698         char *name, *value;
2699
2700         /* cmd: "<cred id> <variable name> <value>" */
2701         name = os_strchr(cmd, ' ');
2702         if (name == NULL)
2703                 return -1;
2704         *name++ = '\0';
2705
2706         value = os_strchr(name, ' ');
2707         if (value == NULL)
2708                 return -1;
2709         *value++ = '\0';
2710
2711         id = atoi(cmd);
2712         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2713                    id, name);
2714         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2715                               (u8 *) value, os_strlen(value));
2716
2717         cred = wpa_config_get_cred(wpa_s->conf, id);
2718         if (cred == NULL) {
2719                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2720                            id);
2721                 return -1;
2722         }
2723
2724         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2725                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2726                            "variable '%s'", name);
2727                 return -1;
2728         }
2729
2730         return 0;
2731 }
2732
2733
2734 #ifndef CONFIG_NO_CONFIG_WRITE
2735 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2736 {
2737         int ret;
2738
2739         if (!wpa_s->conf->update_config) {
2740                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2741                            "to update configuration (update_config=0)");
2742                 return -1;
2743         }
2744
2745         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2746         if (ret) {
2747                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2748                            "update configuration");
2749         } else {
2750                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2751                            " updated");
2752         }
2753
2754         return ret;
2755 }
2756 #endif /* CONFIG_NO_CONFIG_WRITE */
2757
2758
2759 struct cipher_info {
2760         unsigned int capa;
2761         const char *name;
2762         int group_only;
2763 };
2764
2765 static const struct cipher_info ciphers[] = {
2766         { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
2767         { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
2768         { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
2769         { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
2770         { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
2771         { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
2772         { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
2773         { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
2774 };
2775
2776
2777 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2778                                               struct wpa_driver_capa *capa,
2779                                               char *buf, size_t buflen)
2780 {
2781         int ret;
2782         char *pos, *end;
2783         size_t len;
2784         unsigned int i;
2785
2786         pos = buf;
2787         end = pos + buflen;
2788
2789         if (res < 0) {
2790                 if (strict)
2791                         return 0;
2792                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2793                 if (len >= buflen)
2794                         return -1;
2795                 return len;
2796         }
2797
2798         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
2799                 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
2800                         ret = os_snprintf(pos, end - pos, "%s%s",
2801                                           pos == buf ? "" : " ",
2802                                           ciphers[i].name);
2803                         if (ret < 0 || ret >= end - pos)
2804                                 return pos - buf;
2805                         pos += ret;
2806                 }
2807         }
2808
2809         return pos - buf;
2810 }
2811
2812
2813 static int ctrl_iface_get_capability_group(int res, char *strict,
2814                                            struct wpa_driver_capa *capa,
2815                                            char *buf, size_t buflen)
2816 {
2817         int ret;
2818         char *pos, *end;
2819         size_t len;
2820         unsigned int i;
2821
2822         pos = buf;
2823         end = pos + buflen;
2824
2825         if (res < 0) {
2826                 if (strict)
2827                         return 0;
2828                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2829                 if (len >= buflen)
2830                         return -1;
2831                 return len;
2832         }
2833
2834         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
2835                 if (capa->enc & ciphers[i].capa) {
2836                         ret = os_snprintf(pos, end - pos, "%s%s",
2837                                           pos == buf ? "" : " ",
2838                                           ciphers[i].name);
2839                         if (ret < 0 || ret >= end - pos)
2840                                 return pos - buf;
2841                         pos += ret;
2842                 }
2843         }
2844
2845         return pos - buf;
2846 }
2847
2848
2849 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2850                                               struct wpa_driver_capa *capa,
2851                                               char *buf, size_t buflen)
2852 {
2853         int ret;
2854         char *pos, *end;
2855         size_t len;
2856
2857         pos = buf;
2858         end = pos + buflen;
2859
2860         if (res < 0) {
2861                 if (strict)
2862                         return 0;
2863                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
2864                                  "NONE", buflen);
2865                 if (len >= buflen)
2866                         return -1;
2867                 return len;
2868         }
2869
2870         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
2871         if (ret < 0 || ret >= end - pos)
2872                 return pos - buf;
2873         pos += ret;
2874
2875         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2876                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2877                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
2878                 if (ret < 0 || ret >= end - pos)
2879                         return pos - buf;
2880                 pos += ret;
2881         }
2882
2883         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2884                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2885                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
2886                 if (ret < 0 || ret >= end - pos)
2887                         return pos - buf;
2888                 pos += ret;
2889         }
2890
2891         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2892                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
2893                 if (ret < 0 || ret >= end - pos)
2894                         return pos - buf;
2895                 pos += ret;
2896         }
2897
2898         return pos - buf;
2899 }
2900
2901
2902 static int ctrl_iface_get_capability_proto(int res, char *strict,
2903                                            struct wpa_driver_capa *capa,
2904                                            char *buf, size_t buflen)
2905 {
2906         int ret;
2907         char *pos, *end;
2908         size_t len;
2909
2910         pos = buf;
2911         end = pos + buflen;
2912
2913         if (res < 0) {
2914                 if (strict)
2915                         return 0;
2916                 len = os_strlcpy(buf, "RSN WPA", buflen);
2917                 if (len >= buflen)
2918                         return -1;
2919                 return len;
2920         }
2921
2922         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2923                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2924                 ret = os_snprintf(pos, end - pos, "%sRSN",
2925                                   pos == buf ? "" : " ");
2926                 if (ret < 0 || ret >= end - pos)
2927                         return pos - buf;
2928                 pos += ret;
2929         }
2930
2931         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2932                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2933                 ret = os_snprintf(pos, end - pos, "%sWPA",
2934                                   pos == buf ? "" : " ");
2935                 if (ret < 0 || ret >= end - pos)
2936                         return pos - buf;
2937                 pos += ret;
2938         }
2939
2940         return pos - buf;
2941 }
2942
2943
2944 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
2945                                               struct wpa_driver_capa *capa,
2946                                               char *buf, size_t buflen)
2947 {
2948         int ret;
2949         char *pos, *end;
2950         size_t len;
2951
2952         pos = buf;
2953         end = pos + buflen;
2954
2955         if (res < 0) {
2956                 if (strict)
2957                         return 0;
2958                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
2959                 if (len >= buflen)
2960                         return -1;
2961                 return len;
2962         }
2963
2964         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
2965                 ret = os_snprintf(pos, end - pos, "%sOPEN",
2966                                   pos == buf ? "" : " ");
2967                 if (ret < 0 || ret >= end - pos)
2968                         return pos - buf;
2969                 pos += ret;
2970         }
2971
2972         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
2973                 ret = os_snprintf(pos, end - pos, "%sSHARED",
2974                                   pos == buf ? "" : " ");
2975                 if (ret < 0 || ret >= end - pos)
2976                         return pos - buf;
2977                 pos += ret;
2978         }
2979
2980         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
2981                 ret = os_snprintf(pos, end - pos, "%sLEAP",
2982                                   pos == buf ? "" : " ");
2983                 if (ret < 0 || ret >= end - pos)
2984                         return pos - buf;
2985                 pos += ret;
2986         }
2987
2988         return pos - buf;
2989 }
2990
2991
2992 static int ctrl_iface_get_capability_modes(int res, char *strict,
2993                                            struct wpa_driver_capa *capa,
2994                                            char *buf, size_t buflen)
2995 {
2996         int ret;
2997         char *pos, *end;
2998         size_t len;
2999
3000         pos = buf;
3001         end = pos + buflen;
3002
3003         if (res < 0) {
3004                 if (strict)
3005                         return 0;
3006                 len = os_strlcpy(buf, "IBSS AP", buflen);
3007                 if (len >= buflen)
3008                         return -1;
3009                 return len;
3010         }
3011
3012         if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
3013                 ret = os_snprintf(pos, end - pos, "%sIBSS",
3014                                   pos == buf ? "" : " ");
3015                 if (ret < 0 || ret >= end - pos)
3016                         return pos - buf;
3017                 pos += ret;
3018         }
3019
3020         if (capa->flags & WPA_DRIVER_FLAGS_AP) {
3021                 ret = os_snprintf(pos, end - pos, "%sAP",
3022                                   pos == buf ? "" : " ");
3023                 if (ret < 0 || ret >= end - pos)
3024                         return pos - buf;
3025                 pos += ret;
3026         }
3027
3028         return pos - buf;
3029 }
3030
3031
3032 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
3033                                               char *buf, size_t buflen)
3034 {
3035         struct hostapd_channel_data *chnl;
3036         int ret, i, j;
3037         char *pos, *end, *hmode;
3038
3039         pos = buf;
3040         end = pos + buflen;
3041
3042         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3043                 switch (wpa_s->hw.modes[j].mode) {
3044                 case HOSTAPD_MODE_IEEE80211B:
3045                         hmode = "B";
3046                         break;
3047                 case HOSTAPD_MODE_IEEE80211G:
3048                         hmode = "G";
3049                         break;
3050                 case HOSTAPD_MODE_IEEE80211A:
3051                         hmode = "A";
3052                         break;
3053                 case HOSTAPD_MODE_IEEE80211AD:
3054                         hmode = "AD";
3055                         break;
3056                 default:
3057                         continue;
3058                 }
3059                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
3060                 if (ret < 0 || ret >= end - pos)
3061                         return pos - buf;
3062                 pos += ret;
3063                 chnl = wpa_s->hw.modes[j].channels;
3064                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3065                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3066                                 continue;
3067                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
3068                         if (ret < 0 || ret >= end - pos)
3069                                 return pos - buf;
3070                         pos += ret;
3071                 }
3072                 ret = os_snprintf(pos, end - pos, "\n");
3073                 if (ret < 0 || ret >= end - pos)
3074                         return pos - buf;
3075                 pos += ret;
3076         }
3077
3078         return pos - buf;
3079 }
3080
3081
3082 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
3083                                           char *buf, size_t buflen)
3084 {
3085         struct hostapd_channel_data *chnl;
3086         int ret, i, j;
3087         char *pos, *end, *hmode;
3088
3089         pos = buf;
3090         end = pos + buflen;
3091
3092         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3093                 switch (wpa_s->hw.modes[j].mode) {
3094                 case HOSTAPD_MODE_IEEE80211B:
3095                         hmode = "B";
3096                         break;
3097                 case HOSTAPD_MODE_IEEE80211G:
3098                         hmode = "G";
3099                         break;
3100                 case HOSTAPD_MODE_IEEE80211A:
3101                         hmode = "A";
3102                         break;
3103                 case HOSTAPD_MODE_IEEE80211AD:
3104                         hmode = "AD";
3105                         break;
3106                 default:
3107                         continue;
3108                 }
3109                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
3110                                   hmode);
3111                 if (ret < 0 || ret >= end - pos)
3112                         return pos - buf;
3113                 pos += ret;
3114                 chnl = wpa_s->hw.modes[j].channels;
3115                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3116                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3117                                 continue;
3118                         ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
3119                                           chnl[i].chan, chnl[i].freq,
3120                                           chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
3121                                           " (NO_IBSS)" : "",
3122                                           chnl[i].flag & HOSTAPD_CHAN_RADAR ?
3123                                           " (DFS)" : "");
3124
3125                         if (ret < 0 || ret >= end - pos)
3126                                 return pos - buf;
3127                         pos += ret;
3128                 }
3129                 ret = os_snprintf(pos, end - pos, "\n");
3130                 if (ret < 0 || ret >= end - pos)
3131                         return pos - buf;
3132                 pos += ret;
3133         }
3134
3135         return pos - buf;
3136 }
3137
3138
3139 static int wpa_supplicant_ctrl_iface_get_capability(
3140         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
3141         size_t buflen)
3142 {
3143         struct wpa_driver_capa capa;
3144         int res;
3145         char *strict;
3146         char field[30];
3147         size_t len;
3148
3149         /* Determine whether or not strict checking was requested */
3150         len = os_strlcpy(field, _field, sizeof(field));
3151         if (len >= sizeof(field))
3152                 return -1;
3153         strict = os_strchr(field, ' ');
3154         if (strict != NULL) {
3155                 *strict++ = '\0';
3156                 if (os_strcmp(strict, "strict") != 0)
3157                         return -1;
3158         }
3159
3160         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
3161                 field, strict ? strict : "");
3162
3163         if (os_strcmp(field, "eap") == 0) {
3164                 return eap_get_names(buf, buflen);
3165         }
3166
3167         res = wpa_drv_get_capa(wpa_s, &capa);
3168
3169         if (os_strcmp(field, "pairwise") == 0)
3170                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
3171                                                           buf, buflen);
3172
3173         if (os_strcmp(field, "group") == 0)
3174                 return ctrl_iface_get_capability_group(res, strict, &capa,
3175                                                        buf, buflen);
3176
3177         if (os_strcmp(field, "key_mgmt") == 0)
3178                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3179                                                           buf, buflen);
3180
3181         if (os_strcmp(field, "proto") == 0)
3182                 return ctrl_iface_get_capability_proto(res, strict, &capa,
3183                                                        buf, buflen);
3184
3185         if (os_strcmp(field, "auth_alg") == 0)
3186                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
3187                                                           buf, buflen);
3188
3189         if (os_strcmp(field, "modes") == 0)
3190                 return ctrl_iface_get_capability_modes(res, strict, &capa,
3191                                                        buf, buflen);
3192
3193         if (os_strcmp(field, "channels") == 0)
3194                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3195
3196         if (os_strcmp(field, "freq") == 0)
3197                 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
3198
3199 #ifdef CONFIG_TDLS
3200         if (os_strcmp(field, "tdls") == 0)
3201                 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
3202 #endif /* CONFIG_TDLS */
3203
3204         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3205                    field);
3206
3207         return -1;
3208 }
3209
3210
3211 #ifdef CONFIG_INTERWORKING
3212 static char * anqp_add_hex(char *pos, char *end, const char *title,
3213                            struct wpabuf *data)
3214 {
3215         char *start = pos;
3216         size_t i;
3217         int ret;
3218         const u8 *d;
3219
3220         if (data == NULL)
3221                 return start;
3222
3223         ret = os_snprintf(pos, end - pos, "%s=", title);
3224         if (ret < 0 || ret >= end - pos)
3225                 return start;
3226         pos += ret;
3227
3228         d = wpabuf_head_u8(data);
3229         for (i = 0; i < wpabuf_len(data); i++) {
3230                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
3231                 if (ret < 0 || ret >= end - pos)
3232                         return start;
3233                 pos += ret;
3234         }
3235
3236         ret = os_snprintf(pos, end - pos, "\n");
3237         if (ret < 0 || ret >= end - pos)
3238                 return start;
3239         pos += ret;
3240
3241         return pos;
3242 }
3243 #endif /* CONFIG_INTERWORKING */
3244
3245
3246 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3247                           unsigned long mask, char *buf, size_t buflen)
3248 {
3249         size_t i;
3250         int ret;
3251         char *pos, *end;
3252         const u8 *ie, *ie2;
3253
3254         pos = buf;
3255         end = buf + buflen;
3256
3257         if (mask & WPA_BSS_MASK_ID) {
3258                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3259                 if (ret < 0 || ret >= end - pos)
3260                         return 0;
3261                 pos += ret;
3262         }
3263
3264         if (mask & WPA_BSS_MASK_BSSID) {
3265                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3266                                   MAC2STR(bss->bssid));
3267                 if (ret < 0 || ret >= end - pos)
3268                         return 0;
3269                 pos += ret;
3270         }
3271
3272         if (mask & WPA_BSS_MASK_FREQ) {
3273                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3274                 if (ret < 0 || ret >= end - pos)
3275                         return 0;
3276                 pos += ret;
3277         }
3278
3279         if (mask & WPA_BSS_MASK_BEACON_INT) {
3280                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3281                                   bss->beacon_int);
3282                 if (ret < 0 || ret >= end - pos)
3283                         return 0;
3284                 pos += ret;
3285         }
3286
3287         if (mask & WPA_BSS_MASK_CAPABILITIES) {
3288                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3289                                   bss->caps);
3290                 if (ret < 0 || ret >= end - pos)
3291                         return 0;
3292                 pos += ret;
3293         }
3294
3295         if (mask & WPA_BSS_MASK_QUAL) {
3296                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3297                 if (ret < 0 || ret >= end - pos)
3298                         return 0;
3299                 pos += ret;
3300         }
3301
3302         if (mask & WPA_BSS_MASK_NOISE) {
3303                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
3304                 if (ret < 0 || ret >= end - pos)
3305                         return 0;
3306                 pos += ret;
3307         }
3308
3309         if (mask & WPA_BSS_MASK_LEVEL) {
3310                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
3311                 if (ret < 0 || ret >= end - pos)
3312                         return 0;
3313                 pos += ret;
3314         }
3315
3316         if (mask & WPA_BSS_MASK_TSF) {
3317                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
3318                                   (unsigned long long) bss->tsf);
3319                 if (ret < 0 || ret >= end - pos)
3320                         return 0;
3321                 pos += ret;
3322         }
3323
3324         if (mask & WPA_BSS_MASK_AGE) {
3325                 struct os_reltime now;
3326
3327                 os_get_reltime(&now);
3328                 ret = os_snprintf(pos, end - pos, "age=%d\n",
3329                                   (int) (now.sec - bss->last_update.sec));
3330                 if (ret < 0 || ret >= end - pos)
3331                         return 0;
3332                 pos += ret;
3333         }
3334
3335         if (mask & WPA_BSS_MASK_IE) {
3336                 ret = os_snprintf(pos, end - pos, "ie=");
3337                 if (ret < 0 || ret >= end - pos)
3338                         return 0;
3339                 pos += ret;
3340
3341                 ie = (const u8 *) (bss + 1);
3342                 for (i = 0; i < bss->ie_len; i++) {
3343                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
3344                         if (ret < 0 || ret >= end - pos)
3345                                 return 0;
3346                         pos += ret;
3347                 }
3348
3349                 ret = os_snprintf(pos, end - pos, "\n");
3350                 if (ret < 0 || ret >= end - pos)
3351                         return 0;
3352                 pos += ret;
3353         }
3354
3355         if (mask & WPA_BSS_MASK_FLAGS) {
3356                 ret = os_snprintf(pos, end - pos, "flags=");
3357                 if (ret < 0 || ret >= end - pos)
3358                         return 0;
3359                 pos += ret;
3360
3361                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3362                 if (ie)
3363                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
3364                                                     2 + ie[1]);
3365                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3366                 if (ie2)
3367                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
3368                                                     2 + ie2[1]);
3369                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3370                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
3371                         ret = os_snprintf(pos, end - pos, "[WEP]");
3372                         if (ret < 0 || ret >= end - pos)
3373                                 return 0;
3374                         pos += ret;
3375                 }
3376                 if (bss->caps & IEEE80211_CAP_IBSS) {
3377                         ret = os_snprintf(pos, end - pos, "[IBSS]");
3378                         if (ret < 0 || ret >= end - pos)
3379                                 return 0;
3380                         pos += ret;
3381                 }
3382                 if (bss->caps & IEEE80211_CAP_ESS) {
3383                         ret = os_snprintf(pos, end - pos, "[ESS]");
3384                         if (ret < 0 || ret >= end - pos)
3385                                 return 0;
3386                         pos += ret;
3387                 }
3388                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
3389                     wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
3390                         ret = os_snprintf(pos, end - pos, "[P2P]");
3391                         if (ret < 0 || ret >= end - pos)
3392                                 return 0;
3393                         pos += ret;
3394                 }
3395 #ifdef CONFIG_HS20
3396                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
3397                         ret = os_snprintf(pos, end - pos, "[HS20]");
3398                         if (ret < 0 || ret >= end - pos)
3399                                 return 0;
3400                         pos += ret;
3401                 }
3402 #endif /* CONFIG_HS20 */
3403
3404                 ret = os_snprintf(pos, end - pos, "\n");
3405                 if (ret < 0 || ret >= end - pos)
3406                         return 0;
3407                 pos += ret;
3408         }
3409
3410         if (mask & WPA_BSS_MASK_SSID) {
3411                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
3412                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
3413                 if (ret < 0 || ret >= end - pos)
3414                         return 0;
3415                 pos += ret;
3416         }
3417
3418 #ifdef CONFIG_WPS
3419         if (mask & WPA_BSS_MASK_WPS_SCAN) {
3420                 ie = (const u8 *) (bss + 1);
3421                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
3422                 if (ret < 0 || ret >= end - pos)
3423                         return 0;
3424                 pos += ret;
3425         }
3426 #endif /* CONFIG_WPS */
3427
3428 #ifdef CONFIG_P2P
3429         if (mask & WPA_BSS_MASK_P2P_SCAN) {
3430                 ie = (const u8 *) (bss + 1);
3431                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
3432                 if (ret < 0 || ret >= end - pos)
3433                         return 0;
3434                 pos += ret;
3435         }
3436 #endif /* CONFIG_P2P */
3437
3438 #ifdef CONFIG_WIFI_DISPLAY
3439         if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
3440                 struct wpabuf *wfd;
3441                 ie = (const u8 *) (bss + 1);
3442                 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
3443                                                   WFD_IE_VENDOR_TYPE);
3444                 if (wfd) {
3445                         ret = os_snprintf(pos, end - pos, "wfd_subelems=");
3446                         if (ret < 0 || ret >= end - pos) {
3447                                 wpabuf_free(wfd);
3448                                 return 0;
3449                         }
3450                         pos += ret;
3451
3452                         pos += wpa_snprintf_hex(pos, end - pos,
3453                                                 wpabuf_head(wfd),
3454                                                 wpabuf_len(wfd));
3455                         wpabuf_free(wfd);
3456
3457                         ret = os_snprintf(pos, end - pos, "\n");
3458                         if (ret < 0 || ret >= end - pos)
3459                                 return 0;
3460                         pos += ret;
3461                 }
3462         }
3463 #endif /* CONFIG_WIFI_DISPLAY */
3464
3465 #ifdef CONFIG_INTERWORKING
3466         if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
3467                 struct wpa_bss_anqp *anqp = bss->anqp;
3468                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
3469                                    anqp->venue_name);
3470                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
3471                                    anqp->network_auth_type);
3472                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
3473                                    anqp->roaming_consortium);
3474                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
3475                                    anqp->ip_addr_type_availability);
3476                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
3477                                    anqp->nai_realm);
3478                 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
3479                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
3480                                    anqp->domain_name);
3481 #ifdef CONFIG_HS20
3482                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
3483                                    anqp->hs20_operator_friendly_name);
3484                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
3485                                    anqp->hs20_wan_metrics);
3486                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
3487                                    anqp->hs20_connection_capability);
3488                 pos = anqp_add_hex(pos, end, "hs20_operating_class",
3489                                    anqp->hs20_operating_class);
3490                 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
3491                                    anqp->hs20_osu_providers_list);
3492 #endif /* CONFIG_HS20 */
3493         }
3494 #endif /* CONFIG_INTERWORKING */
3495
3496         if (mask & WPA_BSS_MASK_DELIM) {
3497                 ret = os_snprintf(pos, end - pos, "====\n");
3498                 if (ret < 0 || ret >= end - pos)
3499                         return 0;
3500                 pos += ret;
3501         }
3502
3503         return pos - buf;
3504 }
3505
3506
3507 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
3508                                          const char *cmd, char *buf,
3509                                          size_t buflen)
3510 {
3511         u8 bssid[ETH_ALEN];
3512         size_t i;
3513         struct wpa_bss *bss;
3514         struct wpa_bss *bsslast = NULL;
3515         struct dl_list *next;
3516         int ret = 0;
3517         int len;
3518         char *ctmp;
3519         unsigned long mask = WPA_BSS_MASK_ALL;
3520
3521         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
3522                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
3523                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
3524                                             list_id);
3525                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
3526                                                list_id);
3527                 } else { /* N1-N2 */
3528                         unsigned int id1, id2;
3529
3530                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
3531                                 wpa_printf(MSG_INFO, "Wrong BSS range "
3532                                            "format");
3533                                 return 0;
3534                         }
3535
3536                         if (*(cmd + 6) == '-')
3537                                 id1 = 0;
3538                         else
3539                                 id1 = atoi(cmd + 6);
3540                         ctmp++;
3541                         if (*ctmp >= '0' && *ctmp <= '9')
3542                                 id2 = atoi(ctmp);
3543                         else
3544                                 id2 = (unsigned int) -1;
3545                         bss = wpa_bss_get_id_range(wpa_s, id1, id2);
3546                         if (id2 == (unsigned int) -1)
3547                                 bsslast = dl_list_last(&wpa_s->bss_id,
3548                                                        struct wpa_bss,
3549                                                        list_id);
3550                         else {
3551                                 bsslast = wpa_bss_get_id(wpa_s, id2);
3552                                 if (bsslast == NULL && bss && id2 > id1) {
3553                                         struct wpa_bss *tmp = bss;
3554                                         for (;;) {
3555                                                 next = tmp->list_id.next;
3556                                                 if (next == &wpa_s->bss_id)
3557                                                         break;
3558                                                 tmp = dl_list_entry(
3559                                                         next, struct wpa_bss,
3560                                                         list_id);
3561                                                 if (tmp->id > id2)
3562                                                         break;
3563                                                 bsslast = tmp;
3564                                         }
3565                                 }
3566                         }
3567                 }
3568         } else if (os_strncmp(cmd, "FIRST", 5) == 0)
3569                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
3570         else if (os_strncmp(cmd, "LAST", 4) == 0)
3571                 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
3572         else if (os_strncmp(cmd, "ID-", 3) == 0) {
3573                 i = atoi(cmd + 3);
3574                 bss = wpa_bss_get_id(wpa_s, i);
3575         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3576                 i = atoi(cmd + 5);
3577                 bss = wpa_bss_get_id(wpa_s, i);
3578                 if (bss) {
3579                         next = bss->list_id.next;
3580                         if (next == &wpa_s->bss_id)
3581                                 bss = NULL;
3582                         else
3583                                 bss = dl_list_entry(next, struct wpa_bss,
3584                                                     list_id);
3585                 }
3586 #ifdef CONFIG_P2P
3587         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
3588                 if (hwaddr_aton(cmd + 13, bssid) == 0)
3589                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
3590                 else
3591                         bss = NULL;
3592 #endif /* CONFIG_P2P */
3593         } else if (hwaddr_aton(cmd, bssid) == 0)
3594                 bss = wpa_bss_get_bssid(wpa_s, bssid);
3595         else {
3596                 struct wpa_bss *tmp;
3597                 i = atoi(cmd);
3598                 bss = NULL;
3599                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
3600                 {
3601                         if (i-- == 0) {
3602                                 bss = tmp;
3603                                 break;
3604                         }
3605                 }
3606         }
3607
3608         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
3609                 mask = strtoul(ctmp + 5, NULL, 0x10);
3610                 if (mask == 0)
3611                         mask = WPA_BSS_MASK_ALL;
3612         }
3613
3614         if (bss == NULL)
3615                 return 0;
3616
3617         if (bsslast == NULL)
3618                 bsslast = bss;
3619         do {
3620                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
3621                 ret += len;
3622                 buf += len;
3623                 buflen -= len;
3624                 if (bss == bsslast) {
3625                         if ((mask & WPA_BSS_MASK_DELIM) && len &&
3626                             (bss == dl_list_last(&wpa_s->bss_id,
3627                                                  struct wpa_bss, list_id)))
3628                                 os_snprintf(buf - 5, 5, "####\n");
3629                         break;
3630                 }
3631                 next = bss->list_id.next;
3632                 if (next == &wpa_s->bss_id)
3633                         break;
3634                 bss = dl_list_entry(next, struct wpa_bss, list_id);
3635         } while (bss && len);
3636
3637         return ret;
3638 }
3639
3640
3641 static int wpa_supplicant_ctrl_iface_ap_scan(
3642         struct wpa_supplicant *wpa_s, char *cmd)
3643 {
3644         int ap_scan = atoi(cmd);
3645         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
3646 }
3647
3648
3649 static int wpa_supplicant_ctrl_iface_scan_interval(
3650         struct wpa_supplicant *wpa_s, char *cmd)
3651 {
3652         int scan_int = atoi(cmd);
3653         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
3654 }
3655
3656
3657 static int wpa_supplicant_ctrl_iface_bss_expire_age(
3658         struct wpa_supplicant *wpa_s, char *cmd)
3659 {
3660         int expire_age = atoi(cmd);
3661         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
3662 }
3663
3664
3665 static int wpa_supplicant_ctrl_iface_bss_expire_count(
3666         struct wpa_supplicant *wpa_s, char *cmd)
3667 {
3668         int expire_count = atoi(cmd);
3669         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
3670 }
3671
3672
3673 static int wpa_supplicant_ctrl_iface_bss_flush(
3674         struct wpa_supplicant *wpa_s, char *cmd)
3675 {
3676         int flush_age = atoi(cmd);
3677
3678         if (flush_age == 0)
3679                 wpa_bss_flush(wpa_s);
3680         else
3681                 wpa_bss_flush_by_age(wpa_s, flush_age);
3682         return 0;
3683 }
3684
3685
3686 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
3687 {
3688         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
3689         /* MLME-DELETEKEYS.request */
3690         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
3691         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
3692         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
3693         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
3694 #ifdef CONFIG_IEEE80211W
3695         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
3696         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
3697 #endif /* CONFIG_IEEE80211W */
3698
3699         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
3700                         0);
3701         /* MLME-SETPROTECTION.request(None) */
3702         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
3703                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
3704                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
3705         wpa_sm_drop_sa(wpa_s->wpa);
3706 }
3707
3708
3709 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
3710                                           char *addr)
3711 {
3712 #ifdef CONFIG_NO_SCAN_PROCESSING
3713         return -1;
3714 #else /* CONFIG_NO_SCAN_PROCESSING */
3715         u8 bssid[ETH_ALEN];
3716         struct wpa_bss *bss;
3717         struct wpa_ssid *ssid = wpa_s->current_ssid;
3718
3719         if (hwaddr_aton(addr, bssid)) {
3720                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
3721                            "address '%s'", addr);
3722                 return -1;
3723         }
3724
3725         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
3726
3727         if (!ssid) {
3728                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
3729                            "configuration known for the target AP");
3730                 return -1;
3731         }
3732
3733         bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
3734         if (!bss) {
3735                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
3736                            "from BSS table");
3737                 return -1;
3738         }
3739
3740         /*
3741          * TODO: Find best network configuration block from configuration to
3742          * allow roaming to other networks
3743          */
3744
3745         wpa_s->reassociate = 1;
3746         wpa_supplicant_connect(wpa_s, bss, ssid);
3747
3748         return 0;
3749 #endif /* CONFIG_NO_SCAN_PROCESSING */
3750 }
3751
3752
3753 #ifdef CONFIG_P2P
3754 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
3755 {
3756         unsigned int timeout = atoi(cmd);
3757         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
3758         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
3759         u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
3760         char *pos;
3761         unsigned int search_delay;
3762
3763         if (os_strstr(cmd, "type=social"))
3764                 type = P2P_FIND_ONLY_SOCIAL;
3765         else if (os_strstr(cmd, "type=progressive"))
3766                 type = P2P_FIND_PROGRESSIVE;
3767
3768         pos = os_strstr(cmd, "dev_id=");
3769         if (pos) {
3770                 pos += 7;
3771                 if (hwaddr_aton(pos, dev_id))
3772                         return -1;
3773                 _dev_id = dev_id;
3774         }
3775
3776         pos = os_strstr(cmd, "dev_type=");
3777         if (pos) {
3778                 pos += 9;
3779                 if (wps_dev_type_str2bin(pos, dev_type) < 0)
3780                         return -1;
3781                 _dev_type = dev_type;
3782         }
3783
3784         pos = os_strstr(cmd, "delay=");
3785         if (pos) {
3786                 pos += 6;
3787                 search_delay = atoi(pos);
3788         } else
3789                 search_delay = wpas_p2p_search_delay(wpa_s);
3790
3791         return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
3792                              _dev_id, search_delay);
3793 }
3794
3795
3796 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
3797                             char *buf, size_t buflen)
3798 {
3799         u8 addr[ETH_ALEN];
3800         char *pos, *pos2;
3801         char *pin = NULL;
3802         enum p2p_wps_method wps_method;
3803         int new_pin;
3804         int ret;
3805         int persistent_group, persistent_id = -1;
3806         int join;
3807         int auth;
3808         int automatic;
3809         int go_intent = -1;
3810         int freq = 0;
3811         int pd;
3812         int ht40, vht;
3813
3814         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
3815          * [persistent|persistent=<network id>]
3816          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
3817          * [ht40] [vht] */
3818
3819         if (hwaddr_aton(cmd, addr))
3820                 return -1;
3821
3822         pos = cmd + 17;
3823         if (*pos != ' ')
3824                 return -1;
3825         pos++;
3826
3827         persistent_group = os_strstr(pos, " persistent") != NULL;
3828         pos2 = os_strstr(pos, " persistent=");
3829         if (pos2) {
3830                 struct wpa_ssid *ssid;
3831                 persistent_id = atoi(pos2 + 12);
3832                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3833                 if (ssid == NULL || ssid->disabled != 2 ||
3834                     ssid->mode != WPAS_MODE_P2P_GO) {
3835                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3836                                    "SSID id=%d for persistent P2P group (GO)",
3837                                    persistent_id);
3838                         return -1;
3839                 }
3840         }
3841         join = os_strstr(pos, " join") != NULL;
3842         auth = os_strstr(pos, " auth") != NULL;
3843         automatic = os_strstr(pos, " auto") != NULL;
3844         pd = os_strstr(pos, " provdisc") != NULL;
3845         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
3846         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
3847                 vht;
3848
3849         pos2 = os_strstr(pos, " go_intent=");
3850         if (pos2) {
3851                 pos2 += 11;
3852                 go_intent = atoi(pos2);
3853                 if (go_intent < 0 || go_intent > 15)
3854                         return -1;
3855         }
3856
3857         pos2 = os_strstr(pos, " freq=");
3858         if (pos2) {
3859                 pos2 += 6;
3860                 freq = atoi(pos2);
3861                 if (freq <= 0)
3862                         return -1;
3863         }
3864
3865         if (os_strncmp(pos, "pin", 3) == 0) {
3866                 /* Request random PIN (to be displayed) and enable the PIN */
3867                 wps_method = WPS_PIN_DISPLAY;
3868         } else if (os_strncmp(pos, "pbc", 3) == 0) {
3869                 wps_method = WPS_PBC;
3870         } else {
3871                 pin = pos;
3872                 pos = os_strchr(pin, ' ');
3873                 wps_method = WPS_PIN_KEYPAD;
3874                 if (pos) {
3875                         *pos++ = '\0';
3876                         if (os_strncmp(pos, "display", 7) == 0)
3877                                 wps_method = WPS_PIN_DISPLAY;
3878                 }
3879                 if (!wps_pin_str_valid(pin)) {
3880                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
3881                         return 17;
3882                 }
3883         }
3884
3885         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
3886                                    persistent_group, automatic, join,
3887                                    auth, go_intent, freq, persistent_id, pd,
3888                                    ht40, vht);
3889         if (new_pin == -2) {
3890                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
3891                 return 25;
3892         }
3893         if (new_pin == -3) {
3894                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
3895                 return 25;
3896         }
3897         if (new_pin < 0)
3898                 return -1;
3899         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
3900                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
3901                 if (ret < 0 || (size_t) ret >= buflen)
3902                         return -1;
3903                 return ret;
3904         }
3905
3906         os_memcpy(buf, "OK\n", 3);
3907         return 3;
3908 }
3909
3910
3911 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
3912 {
3913         unsigned int timeout = atoi(cmd);
3914         return wpas_p2p_listen(wpa_s, timeout);
3915 }
3916
3917
3918 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
3919 {
3920         u8 addr[ETH_ALEN];
3921         char *pos;
3922         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
3923
3924         /* <addr> <config method> [join|auto] */
3925
3926         if (hwaddr_aton(cmd, addr))
3927                 return -1;
3928
3929         pos = cmd + 17;
3930         if (*pos != ' ')
3931                 return -1;
3932         pos++;
3933
3934         if (os_strstr(pos, " join") != NULL)
3935                 use = WPAS_P2P_PD_FOR_JOIN;
3936         else if (os_strstr(pos, " auto") != NULL)
3937                 use = WPAS_P2P_PD_AUTO;
3938
3939         return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
3940 }
3941
3942
3943 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
3944                               size_t buflen)
3945 {
3946         struct wpa_ssid *ssid = wpa_s->current_ssid;
3947
3948         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
3949             ssid->passphrase == NULL)
3950                 return -1;
3951
3952         os_strlcpy(buf, ssid->passphrase, buflen);
3953         return os_strlen(buf);
3954 }
3955
3956
3957 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
3958                                   char *buf, size_t buflen)
3959 {
3960         u64 ref;
3961         int res;
3962         u8 dst_buf[ETH_ALEN], *dst;
3963         struct wpabuf *tlvs;
3964         char *pos;
3965         size_t len;
3966
3967         if (hwaddr_aton(cmd, dst_buf))
3968                 return -1;
3969         dst = dst_buf;
3970         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
3971             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
3972                 dst = NULL;
3973         pos = cmd + 17;
3974         if (*pos != ' ')
3975                 return -1;
3976         pos++;
3977
3978         if (os_strncmp(pos, "upnp ", 5) == 0) {
3979                 u8 version;
3980                 pos += 5;
3981                 if (hexstr2bin(pos, &version, 1) < 0)
3982                         return -1;
3983                 pos += 2;
3984                 if (*pos != ' ')
3985                         return -1;
3986                 pos++;
3987                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
3988 #ifdef CONFIG_WIFI_DISPLAY
3989         } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
3990                 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
3991 #endif /* CONFIG_WIFI_DISPLAY */
3992         } else {
3993                 len = os_strlen(pos);
3994                 if (len & 1)
3995                         return -1;
3996                 len /= 2;
3997                 tlvs = wpabuf_alloc(len);
3998                 if (tlvs == NULL)
3999                         return -1;
4000                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
4001                         wpabuf_free(tlvs);
4002                         return -1;
4003                 }
4004
4005                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
4006                 wpabuf_free(tlvs);
4007         }
4008         if (ref == 0)
4009                 return -1;
4010         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
4011         if (res < 0 || (unsigned) res >= buflen)
4012                 return -1;
4013         return res;
4014 }
4015
4016
4017 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
4018                                          char *cmd)
4019 {
4020         long long unsigned val;
4021         u64 req;
4022         if (sscanf(cmd, "%llx", &val) != 1)
4023                 return -1;
4024         req = val;
4025         return wpas_p2p_sd_cancel_request(wpa_s, req);
4026 }
4027
4028
4029 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
4030 {
4031         int freq;
4032         u8 dst[ETH_ALEN];
4033         u8 dialog_token;
4034         struct wpabuf *resp_tlvs;
4035         char *pos, *pos2;
4036         size_t len;
4037
4038         pos = os_strchr(cmd, ' ');
4039         if (pos == NULL)
4040                 return -1;
4041         *pos++ = '\0';
4042         freq = atoi(cmd);
4043         if (freq == 0)
4044                 return -1;
4045
4046         if (hwaddr_aton(pos, dst))
4047                 return -1;
4048         pos += 17;
4049         if (*pos != ' ')
4050                 return -1;
4051         pos++;
4052
4053         pos2 = os_strchr(pos, ' ');
4054         if (pos2 == NULL)
4055                 return -1;
4056         *pos2++ = '\0';
4057         dialog_token = atoi(pos);
4058
4059         len = os_strlen(pos2);
4060         if (len & 1)
4061                 return -1;
4062         len /= 2;
4063         resp_tlvs = wpabuf_alloc(len);
4064         if (resp_tlvs == NULL)
4065                 return -1;
4066         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
4067                 wpabuf_free(resp_tlvs);
4068                 return -1;
4069         }
4070
4071         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
4072         wpabuf_free(resp_tlvs);
4073         return 0;
4074 }
4075
4076
4077 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
4078                                        char *cmd)
4079 {
4080         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
4081                 return -1;
4082         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
4083         return 0;
4084 }
4085
4086
4087 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
4088                                         char *cmd)
4089 {
4090         char *pos;
4091         size_t len;
4092         struct wpabuf *query, *resp;
4093
4094         pos = os_strchr(cmd, ' ');
4095         if (pos == NULL)
4096                 return -1;
4097         *pos++ = '\0';
4098
4099         len = os_strlen(cmd);
4100         if (len & 1)
4101                 return -1;
4102         len /= 2;
4103         query = wpabuf_alloc(len);
4104         if (query == NULL)
4105                 return -1;
4106         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4107                 wpabuf_free(query);
4108                 return -1;
4109         }
4110
4111         len = os_strlen(pos);
4112         if (len & 1) {
4113                 wpabuf_free(query);
4114                 return -1;
4115         }
4116         len /= 2;
4117         resp = wpabuf_alloc(len);
4118         if (resp == NULL) {
4119                 wpabuf_free(query);
4120                 return -1;
4121         }
4122         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
4123                 wpabuf_free(query);
4124                 wpabuf_free(resp);
4125                 return -1;
4126         }
4127
4128         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
4129                 wpabuf_free(query);
4130                 wpabuf_free(resp);
4131                 return -1;
4132         }
4133         return 0;
4134 }
4135
4136
4137 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4138 {
4139         char *pos;
4140         u8 version;
4141
4142         pos = os_strchr(cmd, ' ');
4143         if (pos == NULL)
4144                 return -1;
4145         *pos++ = '\0';
4146
4147         if (hexstr2bin(cmd, &version, 1) < 0)
4148                 return -1;
4149
4150         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
4151 }
4152
4153
4154 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
4155 {
4156         char *pos;
4157
4158         pos = os_strchr(cmd, ' ');
4159         if (pos == NULL)
4160                 return -1;
4161         *pos++ = '\0';
4162
4163         if (os_strcmp(cmd, "bonjour") == 0)
4164                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
4165         if (os_strcmp(cmd, "upnp") == 0)
4166                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
4167         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4168         return -1;
4169 }
4170
4171
4172 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
4173                                         char *cmd)
4174 {
4175         size_t len;
4176         struct wpabuf *query;
4177         int ret;
4178
4179         len = os_strlen(cmd);
4180         if (len & 1)
4181                 return -1;
4182         len /= 2;
4183         query = wpabuf_alloc(len);
4184         if (query == NULL)
4185                 return -1;
4186         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4187                 wpabuf_free(query);
4188                 return -1;
4189         }
4190
4191         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
4192         wpabuf_free(query);
4193         return ret;
4194 }
4195
4196
4197 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4198 {
4199         char *pos;
4200         u8 version;
4201
4202         pos = os_strchr(cmd, ' ');
4203         if (pos == NULL)
4204                 return -1;
4205         *pos++ = '\0';
4206
4207         if (hexstr2bin(cmd, &version, 1) < 0)
4208                 return -1;
4209
4210         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
4211 }
4212
4213
4214 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
4215 {
4216         char *pos;
4217
4218         pos = os_strchr(cmd, ' ');
4219         if (pos == NULL)
4220                 return -1;
4221         *pos++ = '\0';
4222
4223         if (os_strcmp(cmd, "bonjour") == 0)
4224                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
4225         if (os_strcmp(cmd, "upnp") == 0)
4226                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
4227         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4228         return -1;
4229 }
4230
4231
4232 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
4233 {
4234         u8 addr[ETH_ALEN];
4235
4236         /* <addr> */
4237
4238         if (hwaddr_aton(cmd, addr))
4239                 return -1;
4240
4241         return wpas_p2p_reject(wpa_s, addr);
4242 }
4243
4244
4245 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
4246 {
4247         char *pos;
4248         int id;
4249         struct wpa_ssid *ssid;
4250         u8 *_peer = NULL, peer[ETH_ALEN];
4251         int freq = 0, pref_freq = 0;
4252         int ht40, vht;
4253
4254         id = atoi(cmd);
4255         pos = os_strstr(cmd, " peer=");
4256         if (pos) {
4257                 pos += 6;
4258                 if (hwaddr_aton(pos, peer))
4259                         return -1;
4260                 _peer = peer;
4261         }
4262         ssid = wpa_config_get_network(wpa_s->conf, id);
4263         if (ssid == NULL || ssid->disabled != 2) {
4264                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4265                            "for persistent P2P group",
4266                            id);
4267                 return -1;
4268         }
4269
4270         pos = os_strstr(cmd, " freq=");
4271         if (pos) {
4272                 pos += 6;
4273                 freq = atoi(pos);
4274                 if (freq <= 0)
4275                         return -1;
4276         }
4277
4278         pos = os_strstr(cmd, " pref=");
4279         if (pos) {
4280                 pos += 6;
4281                 pref_freq = atoi(pos);
4282                 if (pref_freq <= 0)
4283                         return -1;
4284         }
4285
4286         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
4287         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4288                 vht;
4289
4290         return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
4291                                pref_freq);
4292 }
4293
4294
4295 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
4296 {
4297         char *pos;
4298         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
4299
4300         pos = os_strstr(cmd, " peer=");
4301         if (!pos)
4302                 return -1;
4303
4304         *pos = '\0';
4305         pos += 6;
4306         if (hwaddr_aton(pos, peer)) {
4307                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
4308                 return -1;
4309         }
4310
4311         pos = os_strstr(pos, " go_dev_addr=");
4312         if (pos) {
4313                 pos += 13;
4314                 if (hwaddr_aton(pos, go_dev_addr)) {
4315                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
4316                                    pos);
4317                         return -1;
4318                 }
4319                 go_dev = go_dev_addr;
4320         }
4321
4322         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
4323 }
4324
4325
4326 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
4327 {
4328         if (os_strncmp(cmd, "persistent=", 11) == 0)
4329                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
4330         if (os_strncmp(cmd, "group=", 6) == 0)
4331                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
4332
4333         return -1;
4334 }
4335
4336
4337 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
4338                                          char *cmd, int freq, int ht40,
4339                                          int vht)
4340 {
4341         int id;
4342         struct wpa_ssid *ssid;
4343
4344         id = atoi(cmd);
4345         ssid = wpa_config_get_network(wpa_s->conf, id);
4346         if (ssid == NULL || ssid->disabled != 2) {
4347                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4348                            "for persistent P2P group",
4349                            id);
4350                 return -1;
4351         }
4352
4353         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
4354                                              NULL, 0);
4355 }
4356
4357
4358 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
4359 {
4360         int freq = 0, ht40, vht;
4361         char *pos;
4362
4363         pos = os_strstr(cmd, "freq=");
4364         if (pos)
4365                 freq = atoi(pos + 5);
4366
4367         vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
4368         ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4369                 vht;
4370
4371         if (os_strncmp(cmd, "persistent=", 11) == 0)
4372                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
4373                                                      ht40, vht);
4374         if (os_strcmp(cmd, "persistent") == 0 ||
4375             os_strncmp(cmd, "persistent ", 11) == 0)
4376                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
4377         if (os_strncmp(cmd, "freq=", 5) == 0)
4378                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
4379         if (ht40)
4380                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
4381
4382         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
4383                    cmd);
4384         return -1;
4385 }
4386
4387
4388 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
4389                          char *buf, size_t buflen)
4390 {
4391         u8 addr[ETH_ALEN], *addr_ptr;
4392         int next, res;
4393         const struct p2p_peer_info *info;
4394         char *pos, *end;
4395         char devtype[WPS_DEV_TYPE_BUFSIZE];
4396         struct wpa_ssid *ssid;
4397         size_t i;
4398
4399         if (!wpa_s->global->p2p)
4400                 return -1;
4401
4402         if (os_strcmp(cmd, "FIRST") == 0) {
4403                 addr_ptr = NULL;
4404                 next = 0;
4405         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4406                 if (hwaddr_aton(cmd + 5, addr) < 0)
4407                         return -1;
4408                 addr_ptr = addr;
4409                 next = 1;
4410         } else {
4411                 if (hwaddr_aton(cmd, addr) < 0)
4412                         return -1;
4413                 addr_ptr = addr;
4414                 next = 0;
4415         }
4416
4417         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
4418         if (info == NULL)
4419                 return -1;
4420
4421         pos = buf;
4422         end = buf + buflen;
4423
4424         res = os_snprintf(pos, end - pos, MACSTR "\n"
4425                           "pri_dev_type=%s\n"
4426                           "device_name=%s\n"
4427                           "manufacturer=%s\n"
4428                           "model_name=%s\n"
4429                           "model_number=%s\n"
4430                           "serial_number=%s\n"
4431                           "config_methods=0x%x\n"
4432                           "dev_capab=0x%x\n"
4433                           "group_capab=0x%x\n"
4434                           "level=%d\n",
4435                           MAC2STR(info->p2p_device_addr),
4436                           wps_dev_type_bin2str(info->pri_dev_type,
4437                                                devtype, sizeof(devtype)),
4438                           info->device_name,
4439                           info->manufacturer,
4440                           info->model_name,
4441                           info->model_number,
4442                           info->serial_number,
4443                           info->config_methods,
4444                           info->dev_capab,
4445                           info->group_capab,
4446                           info->level);
4447         if (res < 0 || res >= end - pos)
4448                 return pos - buf;
4449         pos += res;
4450
4451         for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
4452         {
4453                 const u8 *t;
4454                 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
4455                 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
4456                                   wps_dev_type_bin2str(t, devtype,
4457                                                        sizeof(devtype)));
4458                 if (res < 0 || res >= end - pos)
4459                         return pos - buf;
4460                 pos += res;
4461         }
4462
4463         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
4464         if (ssid) {
4465                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
4466                 if (res < 0 || res >= end - pos)
4467                         return pos - buf;
4468                 pos += res;
4469         }
4470
4471         res = p2p_get_peer_info_txt(info, pos, end - pos);
4472         if (res < 0)
4473                 return pos - buf;
4474         pos += res;
4475
4476         return pos - buf;
4477 }
4478
4479
4480 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
4481                                   const char *param)
4482 {
4483         unsigned int i;
4484
4485         if (wpa_s->global->p2p == NULL)
4486                 return -1;
4487
4488         if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
4489                 return -1;
4490
4491         for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
4492                 struct wpa_freq_range *freq;
4493                 freq = &wpa_s->global->p2p_disallow_freq.range[i];
4494                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
4495                            freq->min, freq->max);
4496         }
4497
4498         wpas_p2p_update_channel_list(wpa_s);
4499         return 0;
4500 }
4501
4502
4503 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
4504 {
4505         char *param;
4506
4507         if (wpa_s->global->p2p == NULL)
4508                 return -1;
4509
4510         param = os_strchr(cmd, ' ');
4511         if (param == NULL)
4512                 return -1;
4513         *param++ = '\0';
4514
4515         if (os_strcmp(cmd, "discoverability") == 0) {
4516                 p2p_set_client_discoverability(wpa_s->global->p2p,
4517                                                atoi(param));
4518                 return 0;
4519         }
4520
4521         if (os_strcmp(cmd, "managed") == 0) {
4522                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
4523                 return 0;
4524         }
4525
4526         if (os_strcmp(cmd, "listen_channel") == 0) {
4527                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
4528                                               atoi(param));
4529         }
4530
4531         if (os_strcmp(cmd, "ssid_postfix") == 0) {
4532                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
4533                                             os_strlen(param));
4534         }
4535
4536         if (os_strcmp(cmd, "noa") == 0) {
4537                 char *pos;
4538                 int count, start, duration;
4539                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
4540                 count = atoi(param);
4541                 pos = os_strchr(param, ',');
4542                 if (pos == NULL)
4543                         return -1;
4544                 pos++;
4545                 start = atoi(pos);
4546                 pos = os_strchr(pos, ',');
4547                 if (pos == NULL)
4548                         return -1;
4549                 pos++;
4550                 duration = atoi(pos);
4551                 if (count < 0 || count > 255 || start < 0 || duration < 0)
4552                         return -1;
4553                 if (count == 0 && duration > 0)
4554                         return -1;
4555                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
4556                            "start=%d duration=%d", count, start, duration);
4557                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
4558         }
4559
4560         if (os_strcmp(cmd, "ps") == 0)
4561                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
4562
4563         if (os_strcmp(cmd, "oppps") == 0)
4564                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
4565
4566         if (os_strcmp(cmd, "ctwindow") == 0)
4567                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
4568
4569         if (os_strcmp(cmd, "disabled") == 0) {
4570                 wpa_s->global->p2p_disabled = atoi(param);
4571                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
4572                            wpa_s->global->p2p_disabled ?
4573                            "disabled" : "enabled");
4574                 if (wpa_s->global->p2p_disabled) {
4575                         wpas_p2p_stop_find(wpa_s);
4576                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4577                         p2p_flush(wpa_s->global->p2p);
4578                 }
4579                 return 0;
4580         }
4581
4582         if (os_strcmp(cmd, "conc_pref") == 0) {
4583                 if (os_strcmp(param, "sta") == 0)
4584                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
4585                 else if (os_strcmp(param, "p2p") == 0)
4586                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
4587                 else {
4588                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
4589                         return -1;
4590                 }
4591                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
4592                            "%s", param);
4593                 return 0;
4594         }
4595
4596         if (os_strcmp(cmd, "force_long_sd") == 0) {
4597                 wpa_s->force_long_sd = atoi(param);
4598                 return 0;
4599         }
4600
4601         if (os_strcmp(cmd, "peer_filter") == 0) {
4602                 u8 addr[ETH_ALEN];
4603                 if (hwaddr_aton(param, addr))
4604                         return -1;
4605                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
4606                 return 0;
4607         }
4608
4609         if (os_strcmp(cmd, "cross_connect") == 0)
4610                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
4611
4612         if (os_strcmp(cmd, "go_apsd") == 0) {
4613                 if (os_strcmp(param, "disable") == 0)
4614                         wpa_s->set_ap_uapsd = 0;
4615                 else {
4616                         wpa_s->set_ap_uapsd = 1;
4617                         wpa_s->ap_uapsd = atoi(param);
4618                 }
4619                 return 0;
4620         }
4621
4622         if (os_strcmp(cmd, "client_apsd") == 0) {
4623                 if (os_strcmp(param, "disable") == 0)
4624                         wpa_s->set_sta_uapsd = 0;
4625                 else {
4626                         int be, bk, vi, vo;
4627                         char *pos;
4628                         /* format: BE,BK,VI,VO;max SP Length */
4629                         be = atoi(param);
4630                         pos = os_strchr(param, ',');
4631                         if (pos == NULL)
4632                                 return -1;
4633                         pos++;
4634                         bk = atoi(pos);
4635                         pos = os_strchr(pos, ',');
4636                         if (pos == NULL)
4637                                 return -1;
4638                         pos++;
4639                         vi = atoi(pos);
4640                         pos = os_strchr(pos, ',');
4641                         if (pos == NULL)
4642                                 return -1;
4643                         pos++;
4644                         vo = atoi(pos);
4645                         /* ignore max SP Length for now */
4646
4647                         wpa_s->set_sta_uapsd = 1;
4648                         wpa_s->sta_uapsd = 0;
4649                         if (be)
4650                                 wpa_s->sta_uapsd |= BIT(0);
4651                         if (bk)
4652                                 wpa_s->sta_uapsd |= BIT(1);
4653                         if (vi)
4654                                 wpa_s->sta_uapsd |= BIT(2);
4655                         if (vo)
4656                                 wpa_s->sta_uapsd |= BIT(3);
4657                 }
4658                 return 0;
4659         }
4660
4661         if (os_strcmp(cmd, "disallow_freq") == 0)
4662                 return p2p_ctrl_disallow_freq(wpa_s, param);
4663
4664         if (os_strcmp(cmd, "disc_int") == 0) {
4665                 int min_disc_int, max_disc_int, max_disc_tu;
4666                 char *pos;
4667
4668                 pos = param;
4669
4670                 min_disc_int = atoi(pos);
4671                 pos = os_strchr(pos, ' ');
4672                 if (pos == NULL)
4673                         return -1;
4674                 *pos++ = '\0';
4675
4676                 max_disc_int = atoi(pos);
4677                 pos = os_strchr(pos, ' ');
4678                 if (pos == NULL)
4679                         return -1;
4680                 *pos++ = '\0';
4681
4682                 max_disc_tu = atoi(pos);
4683
4684                 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
4685                                         max_disc_int, max_disc_tu);
4686         }
4687
4688         if (os_strcmp(cmd, "per_sta_psk") == 0) {
4689                 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
4690                 return 0;
4691         }
4692
4693 #ifdef CONFIG_WPS_NFC
4694         if (os_strcmp(cmd, "nfc_tag") == 0)
4695                 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
4696 #endif /* CONFIG_WPS_NFC */
4697
4698         if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
4699                 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
4700                 return 0;
4701         }
4702
4703         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
4704                    cmd);
4705
4706         return -1;
4707 }
4708
4709
4710 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
4711 {
4712         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4713         wpa_s->force_long_sd = 0;
4714         if (wpa_s->global->p2p)
4715                 p2p_flush(wpa_s->global->p2p);
4716 }
4717
4718
4719 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
4720 {
4721         char *pos, *pos2;
4722         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
4723
4724         if (cmd[0]) {
4725                 pos = os_strchr(cmd, ' ');
4726                 if (pos == NULL)
4727                         return -1;
4728                 *pos++ = '\0';
4729                 dur1 = atoi(cmd);
4730
4731                 pos2 = os_strchr(pos, ' ');
4732                 if (pos2)
4733                         *pos2++ = '\0';
4734                 int1 = atoi(pos);
4735         } else
4736                 pos2 = NULL;
4737
4738         if (pos2) {
4739                 pos = os_strchr(pos2, ' ');
4740                 if (pos == NULL)
4741                         return -1;
4742                 *pos++ = '\0';
4743                 dur2 = atoi(pos2);
4744                 int2 = atoi(pos);
4745         }
4746
4747         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
4748 }
4749
4750
4751 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
4752 {
4753         char *pos;
4754         unsigned int period = 0, interval = 0;
4755
4756         if (cmd[0]) {
4757                 pos = os_strchr(cmd, ' ');
4758                 if (pos == NULL)
4759                         return -1;
4760                 *pos++ = '\0';
4761                 period = atoi(cmd);
4762                 interval = atoi(pos);
4763         }
4764
4765         return wpas_p2p_ext_listen(wpa_s, period, interval);
4766 }
4767
4768
4769 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
4770 {
4771         const char *pos;
4772         u8 peer[ETH_ALEN];
4773         int iface_addr = 0;
4774
4775         pos = cmd;
4776         if (os_strncmp(pos, "iface=", 6) == 0) {
4777                 iface_addr = 1;
4778                 pos += 6;
4779         }
4780         if (hwaddr_aton(pos, peer))
4781                 return -1;
4782
4783         wpas_p2p_remove_client(wpa_s, peer, iface_addr);
4784         return 0;
4785 }
4786
4787 #endif /* CONFIG_P2P */
4788
4789
4790 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
4791 {
4792         struct wpa_freq_range_list ranges;
4793         int *freqs = NULL;
4794         struct hostapd_hw_modes *mode;
4795         u16 i;
4796
4797         if (wpa_s->hw.modes == NULL)
4798                 return NULL;
4799
4800         os_memset(&ranges, 0, sizeof(ranges));
4801         if (freq_range_list_parse(&ranges, val) < 0)
4802                 return NULL;
4803
4804         for (i = 0; i < wpa_s->hw.num_modes; i++) {
4805                 int j;
4806
4807                 mode = &wpa_s->hw.modes[i];
4808                 for (j = 0; j < mode->num_channels; j++) {
4809                         unsigned int freq;
4810
4811                         if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
4812                                 continue;
4813
4814                         freq = mode->channels[j].freq;
4815                         if (!freq_range_list_includes(&ranges, freq))
4816                                 continue;
4817
4818                         int_array_add_unique(&freqs, freq);
4819                 }
4820         }
4821
4822         os_free(ranges.range);
4823         return freqs;
4824 }
4825
4826
4827 #ifdef CONFIG_INTERWORKING
4828
4829 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
4830 {
4831         int auto_sel = 0;
4832         int *freqs = NULL;
4833
4834         if (param) {
4835                 char *pos;
4836
4837                 auto_sel = os_strstr(param, "auto") != NULL;
4838
4839                 pos = os_strstr(param, "freq=");
4840                 if (pos) {
4841                         freqs = freq_range_to_channel_list(wpa_s, pos + 5);
4842                         if (freqs == NULL)
4843                                 return -1;
4844                 }
4845
4846         }
4847
4848         return interworking_select(wpa_s, auto_sel, freqs);
4849 }
4850
4851
4852 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
4853 {
4854         u8 bssid[ETH_ALEN];
4855         struct wpa_bss *bss;
4856
4857         if (hwaddr_aton(dst, bssid)) {
4858                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
4859                 return -1;
4860         }
4861
4862         bss = wpa_bss_get_bssid(wpa_s, bssid);
4863         if (bss == NULL) {
4864                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
4865                            MAC2STR(bssid));
4866                 return -1;
4867         }
4868
4869         return interworking_connect(wpa_s, bss);
4870 }
4871
4872
4873 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
4874 {
4875         u8 dst_addr[ETH_ALEN];
4876         int used;
4877         char *pos;
4878 #define MAX_ANQP_INFO_ID 100
4879         u16 id[MAX_ANQP_INFO_ID];
4880         size_t num_id = 0;
4881
4882         used = hwaddr_aton2(dst, dst_addr);
4883         if (used < 0)
4884                 return -1;
4885         pos = dst + used;
4886         while (num_id < MAX_ANQP_INFO_ID) {
4887                 id[num_id] = atoi(pos);
4888                 if (id[num_id])
4889                         num_id++;
4890                 pos = os_strchr(pos + 1, ',');
4891                 if (pos == NULL)
4892                         break;
4893                 pos++;
4894         }
4895
4896         if (num_id == 0)
4897                 return -1;
4898
4899         return anqp_send_req(wpa_s, dst_addr, id, num_id);
4900 }
4901
4902
4903 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
4904 {
4905         u8 dst_addr[ETH_ALEN];
4906         struct wpabuf *advproto, *query = NULL;
4907         int used, ret = -1;
4908         char *pos, *end;
4909         size_t len;
4910
4911         used = hwaddr_aton2(cmd, dst_addr);
4912         if (used < 0)
4913                 return -1;
4914
4915         pos = cmd + used;
4916         while (*pos == ' ')
4917                 pos++;
4918
4919         /* Advertisement Protocol ID */
4920         end = os_strchr(pos, ' ');
4921         if (end)
4922                 len = end - pos;
4923         else
4924                 len = os_strlen(pos);
4925         if (len & 0x01)
4926                 return -1;
4927         len /= 2;
4928         if (len == 0)
4929                 return -1;
4930         advproto = wpabuf_alloc(len);
4931         if (advproto == NULL)
4932                 return -1;
4933         if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
4934                 goto fail;
4935
4936         if (end) {
4937                 /* Optional Query Request */
4938                 pos = end + 1;
4939                 while (*pos == ' ')
4940                         pos++;
4941
4942                 len = os_strlen(pos);
4943                 if (len) {
4944                         if (len & 0x01)
4945                                 goto fail;
4946                         len /= 2;
4947                         if (len == 0)
4948                                 goto fail;
4949                         query = wpabuf_alloc(len);
4950                         if (query == NULL)
4951                                 goto fail;
4952                         if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
4953                                 goto fail;
4954                 }
4955         }
4956
4957         ret = gas_send_request(wpa_s, dst_addr, advproto, query);
4958
4959 fail:
4960         wpabuf_free(advproto);
4961         wpabuf_free(query);
4962
4963         return ret;
4964 }
4965
4966
4967 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
4968                             size_t buflen)
4969 {
4970         u8 addr[ETH_ALEN];
4971         int dialog_token;
4972         int used;
4973         char *pos;
4974         size_t resp_len, start, requested_len;
4975         struct wpabuf *resp;
4976         int ret;
4977
4978         used = hwaddr_aton2(cmd, addr);
4979         if (used < 0)
4980                 return -1;
4981
4982         pos = cmd + used;
4983         while (*pos == ' ')
4984                 pos++;
4985         dialog_token = atoi(pos);
4986
4987         if (wpa_s->last_gas_resp &&
4988             os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
4989             dialog_token == wpa_s->last_gas_dialog_token)
4990                 resp = wpa_s->last_gas_resp;
4991         else if (wpa_s->prev_gas_resp &&
4992                  os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
4993                  dialog_token == wpa_s->prev_gas_dialog_token)
4994                 resp = wpa_s->prev_gas_resp;
4995         else
4996                 return -1;
4997
4998         resp_len = wpabuf_len(resp);
4999         start = 0;
5000         requested_len = resp_len;
5001
5002         pos = os_strchr(pos, ' ');
5003         if (pos) {
5004                 start = atoi(pos);
5005                 if (start > resp_len)
5006                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
5007                 pos = os_strchr(pos, ',');
5008                 if (pos == NULL)
5009                         return -1;
5010                 pos++;
5011                 requested_len = atoi(pos);
5012                 if (start + requested_len > resp_len)
5013                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
5014         }
5015
5016         if (requested_len * 2 + 1 > buflen)
5017                 return os_snprintf(buf, buflen, "FAIL-Too long response");
5018
5019         ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
5020                                requested_len);
5021
5022         if (start + requested_len == resp_len) {
5023                 /*
5024                  * Free memory by dropping the response after it has been
5025                  * fetched.
5026                  */
5027                 if (resp == wpa_s->prev_gas_resp) {
5028                         wpabuf_free(wpa_s->prev_gas_resp);
5029                         wpa_s->prev_gas_resp = NULL;
5030                 } else {
5031                         wpabuf_free(wpa_s->last_gas_resp);
5032                         wpa_s->last_gas_resp = NULL;
5033                 }
5034         }
5035
5036         return ret;
5037 }
5038 #endif /* CONFIG_INTERWORKING */
5039
5040
5041 #ifdef CONFIG_HS20
5042
5043 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
5044 {
5045         u8 dst_addr[ETH_ALEN];
5046         int used;
5047         char *pos;
5048         u32 subtypes = 0;
5049
5050         used = hwaddr_aton2(dst, dst_addr);
5051         if (used < 0)
5052                 return -1;
5053         pos = dst + used;
5054         for (;;) {
5055                 int num = atoi(pos);
5056                 if (num <= 0 || num > 31)
5057                         return -1;
5058                 subtypes |= BIT(num);
5059                 pos = os_strchr(pos + 1, ',');
5060                 if (pos == NULL)
5061                         break;
5062                 pos++;
5063         }
5064
5065         if (subtypes == 0)
5066                 return -1;
5067
5068         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
5069 }
5070
5071
5072 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
5073                                     const u8 *addr, const char *realm)
5074 {
5075         u8 *buf;
5076         size_t rlen, len;
5077         int ret;
5078
5079         rlen = os_strlen(realm);
5080         len = 3 + rlen;
5081         buf = os_malloc(len);
5082         if (buf == NULL)
5083                 return -1;
5084         buf[0] = 1; /* NAI Home Realm Count */
5085         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
5086         buf[2] = rlen;
5087         os_memcpy(buf + 3, realm, rlen);
5088
5089         ret = hs20_anqp_send_req(wpa_s, addr,
5090                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
5091                                  buf, len);
5092
5093         os_free(buf);
5094
5095         return ret;
5096 }
5097
5098
5099 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
5100                                         char *dst)
5101 {
5102         struct wpa_cred *cred = wpa_s->conf->cred;
5103         u8 dst_addr[ETH_ALEN];
5104         int used;
5105         u8 *buf;
5106         size_t len;
5107         int ret;
5108
5109         used = hwaddr_aton2(dst, dst_addr);
5110         if (used < 0)
5111                 return -1;
5112
5113         while (dst[used] == ' ')
5114                 used++;
5115         if (os_strncmp(dst + used, "realm=", 6) == 0)
5116                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
5117                                                 dst + used + 6);
5118
5119         len = os_strlen(dst + used);
5120
5121         if (len == 0 && cred && cred->realm)
5122                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
5123
5124         if (len % 1)
5125                 return -1;
5126         len /= 2;
5127         buf = os_malloc(len);
5128         if (buf == NULL)
5129                 return -1;
5130         if (hexstr2bin(dst + used, buf, len) < 0) {
5131                 os_free(buf);
5132                 return -1;
5133         }
5134
5135         ret = hs20_anqp_send_req(wpa_s, dst_addr,
5136                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
5137                                  buf, len);
5138         os_free(buf);
5139
5140         return ret;
5141 }
5142
5143
5144 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
5145 {
5146         u8 dst_addr[ETH_ALEN];
5147         int used;
5148         char *icon;
5149
5150         used = hwaddr_aton2(cmd, dst_addr);
5151         if (used < 0)
5152                 return -1;
5153
5154         while (cmd[used] == ' ')
5155                 used++;
5156         icon = &cmd[used];
5157
5158         wpa_s->fetch_osu_icon_in_progress = 0;
5159         return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
5160                                   (u8 *) icon, os_strlen(icon));
5161 }
5162
5163 #endif /* CONFIG_HS20 */
5164
5165
5166 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
5167         struct wpa_supplicant *wpa_s, char *cmd)
5168 {
5169         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
5170         return 0;
5171 }
5172
5173
5174 #ifdef CONFIG_AUTOSCAN
5175
5176 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
5177                                               char *cmd)
5178 {
5179         enum wpa_states state = wpa_s->wpa_state;
5180         char *new_params = NULL;
5181
5182         if (os_strlen(cmd) > 0) {
5183                 new_params = os_strdup(cmd);
5184                 if (new_params == NULL)
5185                         return -1;
5186         }
5187
5188         os_free(wpa_s->conf->autoscan);
5189         wpa_s->conf->autoscan = new_params;
5190
5191         if (wpa_s->conf->autoscan == NULL)
5192                 autoscan_deinit(wpa_s);
5193         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
5194                 autoscan_init(wpa_s, 1);
5195         else if (state == WPA_SCANNING)
5196                 wpa_supplicant_reinit_autoscan(wpa_s);
5197
5198         return 0;
5199 }
5200
5201 #endif /* CONFIG_AUTOSCAN */
5202
5203
5204 #ifdef CONFIG_WNM
5205
5206 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
5207 {
5208         int enter;
5209         int intval = 0;
5210         char *pos;
5211         int ret;
5212         struct wpabuf *tfs_req = NULL;
5213
5214         if (os_strncmp(cmd, "enter", 5) == 0)
5215                 enter = 1;
5216         else if (os_strncmp(cmd, "exit", 4) == 0)
5217                 enter = 0;
5218         else
5219                 return -1;
5220
5221         pos = os_strstr(cmd, " interval=");
5222         if (pos)
5223                 intval = atoi(pos + 10);
5224
5225         pos = os_strstr(cmd, " tfs_req=");
5226         if (pos) {
5227                 char *end;
5228                 size_t len;
5229                 pos += 9;
5230                 end = os_strchr(pos, ' ');
5231                 if (end)
5232                         len = end - pos;
5233                 else
5234                         len = os_strlen(pos);
5235                 if (len & 1)
5236                         return -1;
5237                 len /= 2;
5238                 tfs_req = wpabuf_alloc(len);
5239                 if (tfs_req == NULL)
5240                         return -1;
5241                 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
5242                         wpabuf_free(tfs_req);
5243                         return -1;
5244                 }
5245         }
5246
5247         ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
5248                                            WNM_SLEEP_MODE_EXIT, intval,
5249                                            tfs_req);
5250         wpabuf_free(tfs_req);
5251
5252         return ret;
5253 }
5254
5255
5256 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
5257 {
5258         int query_reason;
5259
5260         query_reason = atoi(cmd);
5261
5262         wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
5263                    query_reason);
5264
5265         return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
5266 }
5267
5268 #endif /* CONFIG_WNM */
5269
5270
5271 /* Get string representation of channel width */
5272 static const char * channel_width_name(enum chan_width width)
5273 {
5274         switch (width) {
5275         case CHAN_WIDTH_20_NOHT:
5276                 return "20 MHz (no HT)";
5277         case CHAN_WIDTH_20:
5278                 return "20 MHz";
5279         case CHAN_WIDTH_40:
5280                 return "40 MHz";
5281         case CHAN_WIDTH_80:
5282                 return "80 MHz";
5283         case CHAN_WIDTH_80P80:
5284                 return "80+80 MHz";
5285         case CHAN_WIDTH_160:
5286                 return "160 MHz";
5287         default:
5288                 return "unknown";
5289         }
5290 }
5291
5292
5293 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
5294                                       size_t buflen)
5295 {
5296         struct wpa_signal_info si;
5297         int ret;
5298         char *pos, *end;
5299
5300         ret = wpa_drv_signal_poll(wpa_s, &si);
5301         if (ret)
5302                 return -1;
5303
5304         pos = buf;
5305         end = buf + buflen;
5306
5307         ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
5308                           "NOISE=%d\nFREQUENCY=%u\n",
5309                           si.current_signal, si.current_txrate / 1000,
5310                           si.current_noise, si.frequency);
5311         if (ret < 0 || ret > end - pos)
5312                 return -1;
5313         pos += ret;
5314
5315         if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
5316                 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
5317                                   channel_width_name(si.chanwidth));
5318                 if (ret < 0 || ret > end - pos)
5319                         return -1;
5320                 pos += ret;
5321         }
5322
5323         if (si.center_frq1 > 0 && si.center_frq2 > 0) {
5324                 ret = os_snprintf(pos, end - pos,
5325                                   "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
5326                                   si.center_frq1, si.center_frq2);
5327                 if (ret < 0 || ret > end - pos)
5328                         return -1;
5329                 pos += ret;
5330         }
5331
5332         if (si.avg_signal) {
5333                 ret = os_snprintf(pos, end - pos,
5334                                   "AVG_RSSI=%d\n", si.avg_signal);
5335                 if (ret < 0 || ret >= end - pos)
5336                         return -1;
5337                 pos += ret;
5338         }
5339
5340         return pos - buf;
5341 }
5342
5343
5344 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
5345                                       size_t buflen)
5346 {
5347         struct hostap_sta_driver_data sta;
5348         int ret;
5349
5350         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
5351         if (ret)
5352                 return -1;
5353
5354         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
5355                           sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
5356         if (ret < 0 || (size_t) ret > buflen)
5357                 return -1;
5358         return ret;
5359 }
5360
5361
5362 #ifdef ANDROID
5363 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5364                                      char *buf, size_t buflen)
5365 {
5366         int ret;
5367
5368         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
5369         if (ret == 0) {
5370                 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
5371                         struct p2p_data *p2p = wpa_s->global->p2p;
5372                         if (p2p) {
5373                                 char country[3];
5374                                 country[0] = cmd[8];
5375                                 country[1] = cmd[9];
5376                                 country[2] = 0x04;
5377                                 p2p_set_country(p2p, country);
5378                         }
5379                 }
5380                 ret = os_snprintf(buf, buflen, "%s\n", "OK");
5381         }
5382         return ret;
5383 }
5384 #endif /* ANDROID */
5385
5386
5387 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5388                                      char *buf, size_t buflen)
5389 {
5390         int ret;
5391         char *pos;
5392         u8 *data = NULL;
5393         unsigned int vendor_id, subcmd;
5394         struct wpabuf *reply;
5395         size_t data_len = 0;
5396
5397         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
5398         vendor_id = strtoul(cmd, &pos, 16);
5399         if (!isblank(*pos))
5400                 return -EINVAL;
5401
5402         subcmd = strtoul(pos, &pos, 10);
5403
5404         if (*pos != '\0') {
5405                 if (!isblank(*pos++))
5406                         return -EINVAL;
5407                 data_len = os_strlen(pos);
5408         }
5409
5410         if (data_len) {
5411                 data_len /= 2;
5412                 data = os_malloc(data_len);
5413                 if (!data)
5414                         return -ENOBUFS;
5415
5416                 if (hexstr2bin(pos, data, data_len)) {
5417                         wpa_printf(MSG_DEBUG,
5418                                    "Vendor command: wrong parameter format");
5419                         os_free(data);
5420                         return -EINVAL;
5421                 }
5422         }
5423
5424         reply = wpabuf_alloc((buflen - 1) / 2);
5425         if (!reply) {
5426                 os_free(data);
5427                 return -ENOBUFS;
5428         }
5429
5430         ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
5431                                  reply);
5432
5433         if (ret == 0)
5434                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
5435                                        wpabuf_len(reply));
5436
5437         wpabuf_free(reply);
5438         os_free(data);
5439
5440         return ret;
5441 }
5442
5443
5444 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
5445 {
5446         wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
5447
5448 #ifdef CONFIG_P2P
5449         wpas_p2p_stop_find(wpa_s);
5450         p2p_ctrl_flush(wpa_s);
5451         wpas_p2p_group_remove(wpa_s, "*");
5452         wpas_p2p_service_flush(wpa_s);
5453         wpa_s->global->p2p_disabled = 0;
5454         wpa_s->global->p2p_per_sta_psk = 0;
5455         wpa_s->conf->num_sec_device_types = 0;
5456         wpa_s->p2p_disable_ip_addr_req = 0;
5457 #endif /* CONFIG_P2P */
5458
5459 #ifdef CONFIG_WPS_TESTING
5460         wps_version_number = 0x20;
5461         wps_testing_dummy_cred = 0;
5462         wps_corrupt_pkhash = 0;
5463 #endif /* CONFIG_WPS_TESTING */
5464 #ifdef CONFIG_WPS
5465         wpa_s->wps_fragment_size = 0;
5466         wpas_wps_cancel(wpa_s);
5467 #endif /* CONFIG_WPS */
5468         wpa_s->after_wps = 0;
5469         wpa_s->known_wps_freq = 0;
5470
5471 #ifdef CONFIG_TDLS
5472 #ifdef CONFIG_TDLS_TESTING
5473         extern unsigned int tdls_testing;
5474         tdls_testing = 0;
5475 #endif /* CONFIG_TDLS_TESTING */
5476         wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
5477         wpa_tdls_enable(wpa_s->wpa, 1);
5478 #endif /* CONFIG_TDLS */
5479
5480         eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
5481         wpa_supplicant_stop_countermeasures(wpa_s, NULL);
5482
5483         wpa_s->no_keep_alive = 0;
5484
5485         os_free(wpa_s->disallow_aps_bssid);
5486         wpa_s->disallow_aps_bssid = NULL;
5487         wpa_s->disallow_aps_bssid_count = 0;
5488         os_free(wpa_s->disallow_aps_ssid);
5489         wpa_s->disallow_aps_ssid = NULL;
5490         wpa_s->disallow_aps_ssid_count = 0;
5491
5492         wpa_s->set_sta_uapsd = 0;
5493         wpa_s->sta_uapsd = 0;
5494
5495         wpa_drv_radio_disable(wpa_s, 0);
5496
5497         wpa_bss_flush(wpa_s);
5498         wpa_blacklist_clear(wpa_s);
5499         wpa_s->extra_blacklist_count = 0;
5500         wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
5501         wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
5502         wpa_config_flush_blobs(wpa_s->conf);
5503         wpa_s->conf->auto_interworking = 0;
5504         wpa_s->conf->okc = 0;
5505
5506         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
5507         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
5508         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
5509         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
5510
5511         radio_remove_works(wpa_s, NULL, 1);
5512
5513         wpa_s->next_ssid = NULL;
5514
5515 #ifdef CONFIG_INTERWORKING
5516         hs20_cancel_fetch_osu(wpa_s);
5517 #endif /* CONFIG_INTERWORKING */
5518
5519         wpa_s->ext_mgmt_frame_handling = 0;
5520 }
5521
5522
5523 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
5524                                      char *buf, size_t buflen)
5525 {
5526         struct wpa_radio_work *work;
5527         char *pos, *end;
5528         struct os_reltime now, diff;
5529
5530         pos = buf;
5531         end = buf + buflen;
5532
5533         os_get_reltime(&now);
5534
5535         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
5536         {
5537                 int ret;
5538
5539                 os_reltime_sub(&now, &work->time, &diff);
5540                 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
5541                                   work->type, work->wpa_s->ifname, work->freq,
5542                                   work->started, diff.sec, diff.usec);
5543                 if (ret < 0 || ret >= end - pos)
5544                         break;
5545                 pos += ret;
5546         }
5547
5548         return pos - buf;
5549 }
5550
5551
5552 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
5553 {
5554         struct wpa_radio_work *work = eloop_ctx;
5555         struct wpa_external_work *ework = work->ctx;
5556
5557         wpa_dbg(work->wpa_s, MSG_DEBUG,
5558                 "Timing out external radio work %u (%s)",
5559                 ework->id, work->type);
5560         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
5561         os_free(ework);
5562         radio_work_done(work);
5563 }
5564
5565
5566 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
5567 {
5568         struct wpa_external_work *ework = work->ctx;
5569
5570         if (deinit) {
5571                 if (work->started)
5572                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
5573                                              work, NULL);
5574
5575                 os_free(ework);
5576                 return;
5577         }
5578
5579         wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
5580                 ework->id, ework->type);
5581         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
5582         if (!ework->timeout)
5583                 ework->timeout = 10;
5584         eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
5585                                work, NULL);
5586 }
5587
5588
5589 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
5590                                     char *buf, size_t buflen)
5591 {
5592         struct wpa_external_work *ework;
5593         char *pos, *pos2;
5594         size_t type_len;
5595         int ret;
5596         unsigned int freq = 0;
5597
5598         /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
5599
5600         ework = os_zalloc(sizeof(*ework));
5601         if (ework == NULL)
5602                 return -1;
5603
5604         pos = os_strchr(cmd, ' ');
5605         if (pos) {
5606                 type_len = pos - cmd;
5607                 pos++;
5608
5609                 pos2 = os_strstr(pos, "freq=");
5610                 if (pos2)
5611                         freq = atoi(pos2 + 5);
5612
5613                 pos2 = os_strstr(pos, "timeout=");
5614                 if (pos2)
5615                         ework->timeout = atoi(pos2 + 8);
5616         } else {
5617                 type_len = os_strlen(cmd);
5618         }
5619         if (4 + type_len >= sizeof(ework->type))
5620                 type_len = sizeof(ework->type) - 4 - 1;
5621         os_strlcpy(ework->type, "ext:", sizeof(ework->type));
5622         os_memcpy(ework->type + 4, cmd, type_len);
5623         ework->type[4 + type_len] = '\0';
5624
5625         wpa_s->ext_work_id++;
5626         if (wpa_s->ext_work_id == 0)
5627                 wpa_s->ext_work_id++;
5628         ework->id = wpa_s->ext_work_id;
5629
5630         if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
5631                            ework) < 0) {
5632                 os_free(ework);
5633                 return -1;
5634         }
5635
5636         ret = os_snprintf(buf, buflen, "%u", ework->id);
5637         if (ret < 0 || (size_t) ret >= buflen)
5638                 return -1;
5639         return ret;
5640 }
5641
5642
5643 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
5644 {
5645         struct wpa_radio_work *work;
5646         unsigned int id = atoi(cmd);
5647
5648         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
5649         {
5650                 struct wpa_external_work *ework;
5651
5652                 if (os_strncmp(work->type, "ext:", 4) != 0)
5653                         continue;
5654                 ework = work->ctx;
5655                 if (id && ework->id != id)
5656                         continue;
5657                 wpa_dbg(wpa_s, MSG_DEBUG,
5658                         "Completed external radio work %u (%s)",
5659                         ework->id, ework->type);
5660                 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
5661                 os_free(ework);
5662                 radio_work_done(work);
5663                 return 3; /* "OK\n" */
5664         }
5665
5666         return -1;
5667 }
5668
5669
5670 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
5671                                 char *buf, size_t buflen)
5672 {
5673         if (os_strcmp(cmd, "show") == 0)
5674                 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
5675         if (os_strncmp(cmd, "add ", 4) == 0)
5676                 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
5677         if (os_strncmp(cmd, "done ", 5) == 0)
5678                 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
5679         return -1;
5680 }
5681
5682
5683 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
5684 {
5685         struct wpa_radio_work *work, *tmp;
5686
5687         if (!wpa_s || !wpa_s->radio)
5688                 return;
5689
5690         dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
5691                               struct wpa_radio_work, list) {
5692                 struct wpa_external_work *ework;
5693
5694                 if (os_strncmp(work->type, "ext:", 4) != 0)
5695                         continue;
5696                 ework = work->ctx;
5697                 wpa_dbg(wpa_s, MSG_DEBUG,
5698                         "Flushing %sexternal radio work %u (%s)",
5699                         work->started ? " started" : "", ework->id,
5700                         ework->type);
5701                 if (work->started)
5702                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
5703                                              work, NULL);
5704                 os_free(ework);
5705                 radio_work_done(work);
5706         }
5707 }
5708
5709
5710 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
5711 {
5712         struct wpa_supplicant *wpa_s = eloop_ctx;
5713         eapol_sm_notify_ctrl_response(wpa_s->eapol);
5714 }
5715
5716
5717 static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
5718 {
5719         int *freqs = NULL;
5720
5721         freqs = freq_range_to_channel_list(wpa_s, val);
5722         if (freqs == NULL)
5723                 return -1;
5724
5725         os_free(wpa_s->manual_scan_freqs);
5726         wpa_s->manual_scan_freqs = freqs;
5727
5728         return 0;
5729 }
5730
5731
5732 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
5733                            char *reply, int reply_size, int *reply_len)
5734 {
5735         char *pos;
5736
5737         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5738                 *reply_len = -1;
5739                 return;
5740         }
5741
5742         wpa_s->manual_scan_passive = 0;
5743         wpa_s->manual_scan_use_id = 0;
5744         wpa_s->manual_scan_only_new = 0;
5745
5746         if (params) {
5747                 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
5748                         wpa_s->scan_res_handler = scan_only_handler;
5749
5750                 pos = os_strstr(params, "freq=");
5751                 if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
5752                         *reply_len = -1;
5753                         return;
5754                 }
5755
5756                 pos = os_strstr(params, "passive=");
5757                 if (pos)
5758                         wpa_s->manual_scan_passive = !!atoi(pos + 8);
5759
5760                 pos = os_strstr(params, "use_id=");
5761                 if (pos)
5762                         wpa_s->manual_scan_use_id = atoi(pos + 7);
5763
5764                 pos = os_strstr(params, "only_new=1");
5765                 if (pos)
5766                         wpa_s->manual_scan_only_new = 1;
5767         } else {
5768                 os_free(wpa_s->manual_scan_freqs);
5769                 wpa_s->manual_scan_freqs = NULL;
5770                 if (wpa_s->scan_res_handler == scan_only_handler)
5771                         wpa_s->scan_res_handler = NULL;
5772         }
5773
5774         if (!wpa_s->sched_scanning && !wpa_s->scanning &&
5775             ((wpa_s->wpa_state <= WPA_SCANNING) ||
5776              (wpa_s->wpa_state == WPA_COMPLETED))) {
5777                 wpa_s->normal_scans = 0;
5778                 wpa_s->scan_req = MANUAL_SCAN_REQ;
5779                 wpa_s->after_wps = 0;
5780                 wpa_s->known_wps_freq = 0;
5781                 wpa_supplicant_req_scan(wpa_s, 0, 0);
5782                 if (wpa_s->manual_scan_use_id) {
5783                         wpa_s->manual_scan_id++;
5784                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
5785                                 wpa_s->manual_scan_id);
5786                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
5787                                                  wpa_s->manual_scan_id);
5788                 }
5789         } else if (wpa_s->sched_scanning) {
5790                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
5791                 wpa_supplicant_cancel_sched_scan(wpa_s);
5792                 wpa_s->scan_req = MANUAL_SCAN_REQ;
5793                 wpa_supplicant_req_scan(wpa_s, 0, 0);
5794                 if (wpa_s->manual_scan_use_id) {
5795                         wpa_s->manual_scan_id++;
5796                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
5797                                                  wpa_s->manual_scan_id);
5798                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
5799                                 wpa_s->manual_scan_id);
5800                 }
5801         } else {
5802                 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
5803                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
5804         }
5805 }
5806
5807
5808 #ifdef CONFIG_TESTING_OPTIONS
5809
5810 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
5811                                        unsigned int freq, const u8 *dst,
5812                                        const u8 *src, const u8 *bssid,
5813                                        const u8 *data, size_t data_len,
5814                                        enum offchannel_send_action_result
5815                                        result)
5816 {
5817         wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
5818                 " src=" MACSTR " bssid=" MACSTR " result=%s",
5819                 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
5820                 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
5821                 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
5822                              "NO_ACK" : "FAILED"));
5823 }
5824
5825
5826 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
5827 {
5828         char *pos, *param;
5829         size_t len;
5830         u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
5831         int res, used;
5832         int freq = 0, no_cck = 0, wait_time = 0;
5833
5834         /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
5835          *    <action=Action frame payload> */
5836
5837         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
5838
5839         pos = cmd;
5840         used = hwaddr_aton2(pos, da);
5841         if (used < 0)
5842                 return -1;
5843         pos += used;
5844         while (*pos == ' ')
5845                 pos++;
5846         used = hwaddr_aton2(pos, bssid);
5847         if (used < 0)
5848                 return -1;
5849         pos += used;
5850
5851         param = os_strstr(pos, " freq=");
5852         if (param) {
5853                 param += 6;
5854                 freq = atoi(param);
5855         }
5856
5857         param = os_strstr(pos, " no_cck=");
5858         if (param) {
5859                 param += 8;
5860                 no_cck = atoi(param);
5861         }
5862
5863         param = os_strstr(pos, " wait_time=");
5864         if (param) {
5865                 param += 11;
5866                 wait_time = atoi(param);
5867         }
5868
5869         param = os_strstr(pos, " action=");
5870         if (param == NULL)
5871                 return -1;
5872         param += 8;
5873
5874         len = os_strlen(param);
5875         if (len & 1)
5876                 return -1;
5877         len /= 2;
5878
5879         buf = os_malloc(len);
5880         if (buf == NULL)
5881                 return -1;
5882
5883         if (hexstr2bin(param, buf, len) < 0) {
5884                 os_free(buf);
5885                 return -1;
5886         }
5887
5888         res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
5889                                      buf, len, wait_time,
5890                                      wpas_ctrl_iface_mgmt_tx_cb, no_cck);
5891         os_free(buf);
5892         return res;
5893 }
5894
5895
5896 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
5897 {
5898         wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
5899         offchannel_send_action_done(wpa_s);
5900 }
5901
5902 #endif /* CONFIG_TESTING_OPTIONS */
5903
5904
5905 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
5906                                          char *buf, size_t *resp_len)
5907 {
5908         char *reply;
5909         const int reply_size = 4096;
5910         int reply_len;
5911
5912         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
5913             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
5914                 if (wpa_debug_show_keys)
5915                         wpa_dbg(wpa_s, MSG_DEBUG,
5916                                 "Control interface command '%s'", buf);
5917                 else
5918                         wpa_dbg(wpa_s, MSG_DEBUG,
5919                                 "Control interface command '%s [REMOVED]'",
5920                                 os_strncmp(buf, WPA_CTRL_RSP,
5921                                            os_strlen(WPA_CTRL_RSP)) == 0 ?
5922                                 WPA_CTRL_RSP : "SET_NETWORK");
5923         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
5924                    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
5925                    os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
5926                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
5927                                       (const u8 *) buf, os_strlen(buf));
5928         } else {
5929                 int level = MSG_DEBUG;
5930                 if (os_strcmp(buf, "PING") == 0)
5931                         level = MSG_EXCESSIVE;
5932                 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
5933         }
5934
5935         reply = os_malloc(reply_size);
5936         if (reply == NULL) {
5937                 *resp_len = 1;
5938                 return NULL;
5939         }
5940
5941         os_memcpy(reply, "OK\n", 3);
5942         reply_len = 3;
5943
5944         if (os_strcmp(buf, "PING") == 0) {
5945                 os_memcpy(reply, "PONG\n", 5);
5946                 reply_len = 5;
5947         } else if (os_strcmp(buf, "IFNAME") == 0) {
5948                 reply_len = os_strlen(wpa_s->ifname);
5949                 os_memcpy(reply, wpa_s->ifname, reply_len);
5950         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
5951                 if (wpa_debug_reopen_file() < 0)
5952                         reply_len = -1;
5953         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
5954                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
5955         } else if (os_strcmp(buf, "MIB") == 0) {
5956                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
5957                 if (reply_len >= 0) {
5958                         int res;
5959                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
5960                                                reply_size - reply_len);
5961                         if (res < 0)
5962                                 reply_len = -1;
5963                         else
5964                                 reply_len += res;
5965                 }
5966         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
5967                 reply_len = wpa_supplicant_ctrl_iface_status(
5968                         wpa_s, buf + 6, reply, reply_size);
5969         } else if (os_strcmp(buf, "PMKSA") == 0) {
5970                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
5971                                                     reply_size);
5972         } else if (os_strncmp(buf, "SET ", 4) == 0) {
5973                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
5974                         reply_len = -1;
5975         } else if (os_strncmp(buf, "GET ", 4) == 0) {
5976                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
5977                                                           reply, reply_size);
5978         } else if (os_strcmp(buf, "LOGON") == 0) {
5979                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
5980         } else if (os_strcmp(buf, "LOGOFF") == 0) {
5981                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
5982         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
5983                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5984                         reply_len = -1;
5985                 else
5986                         wpas_request_connection(wpa_s);
5987         } else if (os_strcmp(buf, "REATTACH") == 0) {
5988                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
5989                     !wpa_s->current_ssid)
5990                         reply_len = -1;
5991                 else {
5992                         wpa_s->reattach = 1;
5993                         wpas_request_connection(wpa_s);
5994                 }
5995         } else if (os_strcmp(buf, "RECONNECT") == 0) {
5996                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
5997                         reply_len = -1;
5998                 else if (wpa_s->disconnected)
5999                         wpas_request_connection(wpa_s);
6000 #ifdef IEEE8021X_EAPOL
6001         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
6002                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
6003                         reply_len = -1;
6004 #endif /* IEEE8021X_EAPOL */
6005 #ifdef CONFIG_PEERKEY
6006         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
6007                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
6008                         reply_len = -1;
6009 #endif /* CONFIG_PEERKEY */
6010 #ifdef CONFIG_IEEE80211R
6011         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
6012                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
6013                         reply_len = -1;
6014 #endif /* CONFIG_IEEE80211R */
6015 #ifdef CONFIG_WPS
6016         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
6017                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
6018                 if (res == -2) {
6019                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6020                         reply_len = 17;
6021                 } else if (res)
6022                         reply_len = -1;
6023         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
6024                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
6025                 if (res == -2) {
6026                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6027                         reply_len = 17;
6028                 } else if (res)
6029                         reply_len = -1;
6030         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
6031                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
6032                                                               reply,
6033                                                               reply_size);
6034         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
6035                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
6036                         wpa_s, buf + 14, reply, reply_size);
6037         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
6038                 if (wpas_wps_cancel(wpa_s))
6039                         reply_len = -1;
6040 #ifdef CONFIG_WPS_NFC
6041         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
6042                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
6043                         reply_len = -1;
6044         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
6045                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
6046                         reply_len = -1;
6047         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
6048                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
6049                         wpa_s, buf + 21, reply, reply_size);
6050         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
6051                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
6052                         wpa_s, buf + 14, reply, reply_size);
6053         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
6054                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
6055                                                                buf + 17))
6056                         reply_len = -1;
6057         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
6058                 reply_len = wpas_ctrl_nfc_get_handover_req(
6059                         wpa_s, buf + 21, reply, reply_size);
6060         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
6061                 reply_len = wpas_ctrl_nfc_get_handover_sel(
6062                         wpa_s, buf + 21, reply, reply_size);
6063         } else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
6064                 if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
6065                         reply_len = -1;
6066         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
6067                 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
6068                         reply_len = -1;
6069 #endif /* CONFIG_WPS_NFC */
6070         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
6071                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
6072                         reply_len = -1;
6073 #ifdef CONFIG_AP
6074         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
6075                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
6076                         wpa_s, buf + 11, reply, reply_size);
6077 #endif /* CONFIG_AP */
6078 #ifdef CONFIG_WPS_ER
6079         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
6080                 if (wpas_wps_er_start(wpa_s, NULL))
6081                         reply_len = -1;
6082         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
6083                 if (wpas_wps_er_start(wpa_s, buf + 13))
6084                         reply_len = -1;
6085         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
6086                 if (wpas_wps_er_stop(wpa_s))
6087                         reply_len = -1;
6088         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
6089                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
6090                         reply_len = -1;
6091         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
6092                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
6093                 if (ret == -2) {
6094                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6095                         reply_len = 17;
6096                 } else if (ret == -3) {
6097                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
6098                         reply_len = 18;
6099                 } else if (ret == -4) {
6100                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
6101                         reply_len = 20;
6102                 } else if (ret)
6103                         reply_len = -1;
6104         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
6105                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
6106                         reply_len = -1;
6107         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
6108                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
6109                                                                 buf + 18))
6110                         reply_len = -1;
6111         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
6112                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
6113                         reply_len = -1;
6114 #ifdef CONFIG_WPS_NFC
6115         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
6116                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
6117                         wpa_s, buf + 24, reply, reply_size);
6118 #endif /* CONFIG_WPS_NFC */
6119 #endif /* CONFIG_WPS_ER */
6120 #endif /* CONFIG_WPS */
6121 #ifdef CONFIG_IBSS_RSN
6122         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
6123                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
6124                         reply_len = -1;
6125 #endif /* CONFIG_IBSS_RSN */
6126 #ifdef CONFIG_P2P
6127         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
6128                 if (p2p_ctrl_find(wpa_s, buf + 9))
6129                         reply_len = -1;
6130         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
6131                 if (p2p_ctrl_find(wpa_s, ""))
6132                         reply_len = -1;
6133         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
6134                 wpas_p2p_stop_find(wpa_s);
6135         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
6136                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
6137                                              reply_size);
6138         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
6139                 if (p2p_ctrl_listen(wpa_s, buf + 11))
6140                         reply_len = -1;
6141         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
6142                 if (p2p_ctrl_listen(wpa_s, ""))
6143                         reply_len = -1;
6144         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
6145                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
6146                         reply_len = -1;
6147         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
6148                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
6149                         reply_len = -1;
6150         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
6151                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
6152                         reply_len = -1;
6153         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
6154                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
6155                         reply_len = -1;
6156         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
6157                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
6158         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
6159                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
6160                                                    reply_size);
6161         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
6162                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
6163                         reply_len = -1;
6164         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
6165                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
6166                         reply_len = -1;
6167         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
6168                 wpas_p2p_sd_service_update(wpa_s);
6169         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
6170                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
6171                         reply_len = -1;
6172         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
6173                 wpas_p2p_service_flush(wpa_s);
6174         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
6175                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
6176                         reply_len = -1;
6177         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
6178                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
6179                         reply_len = -1;
6180         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
6181                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
6182                         reply_len = -1;
6183         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
6184                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
6185                         reply_len = -1;
6186         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
6187                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
6188                                               reply_size);
6189         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
6190                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
6191                         reply_len = -1;
6192         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
6193                 p2p_ctrl_flush(wpa_s);
6194         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
6195                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
6196                         reply_len = -1;
6197         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
6198                 if (wpas_p2p_cancel(wpa_s))
6199                         reply_len = -1;
6200         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
6201                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
6202                         reply_len = -1;
6203         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
6204                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
6205                         reply_len = -1;
6206         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
6207                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
6208                         reply_len = -1;
6209         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
6210                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
6211                         reply_len = -1;
6212         } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
6213                 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
6214                         reply_len = -1;
6215 #endif /* CONFIG_P2P */
6216 #ifdef CONFIG_WIFI_DISPLAY
6217         } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
6218                 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
6219                         reply_len = -1;
6220         } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
6221                 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
6222                                                      reply, reply_size);
6223 #endif /* CONFIG_WIFI_DISPLAY */
6224 #ifdef CONFIG_INTERWORKING
6225         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
6226                 if (interworking_fetch_anqp(wpa_s) < 0)
6227                         reply_len = -1;
6228         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
6229                 interworking_stop_fetch_anqp(wpa_s);
6230         } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
6231                 if (ctrl_interworking_select(wpa_s, NULL) < 0)
6232                         reply_len = -1;
6233         } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
6234                 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
6235                         reply_len = -1;
6236         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
6237                 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
6238                         reply_len = -1;
6239         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
6240                 if (get_anqp(wpa_s, buf + 9) < 0)
6241                         reply_len = -1;
6242         } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
6243                 if (gas_request(wpa_s, buf + 12) < 0)
6244                         reply_len = -1;
6245         } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
6246                 reply_len = gas_response_get(wpa_s, buf + 17, reply,
6247                                              reply_size);
6248 #endif /* CONFIG_INTERWORKING */
6249 #ifdef CONFIG_HS20
6250         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
6251                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
6252                         reply_len = -1;
6253         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
6254                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
6255                         reply_len = -1;
6256         } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
6257                 if (hs20_icon_request(wpa_s, buf + 18) < 0)
6258                         reply_len = -1;
6259         } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
6260                 if (hs20_fetch_osu(wpa_s) < 0)
6261                         reply_len = -1;
6262         } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
6263                 hs20_cancel_fetch_osu(wpa_s);
6264 #endif /* CONFIG_HS20 */
6265         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
6266         {
6267                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
6268                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
6269                         reply_len = -1;
6270                 else {
6271                         /*
6272                          * Notify response from timeout to allow the control
6273                          * interface response to be sent first.
6274                          */
6275                         eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
6276                                                wpa_s, NULL);
6277                 }
6278         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
6279                 if (wpa_supplicant_reload_configuration(wpa_s))
6280                         reply_len = -1;
6281         } else if (os_strcmp(buf, "TERMINATE") == 0) {
6282                 wpa_supplicant_terminate_proc(wpa_s->global);
6283         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
6284                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
6285                         reply_len = -1;
6286         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
6287                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
6288                         wpa_s, buf + 9, reply, reply_size);
6289         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
6290                 reply_len = wpa_supplicant_ctrl_iface_log_level(
6291                         wpa_s, buf + 9, reply, reply_size);
6292         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
6293                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
6294                         wpa_s, reply, reply_size);
6295         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
6296 #ifdef CONFIG_SME
6297                 wpa_s->sme.prev_bssid_set = 0;
6298 #endif /* CONFIG_SME */
6299                 wpa_s->reassociate = 0;
6300                 wpa_s->disconnected = 1;
6301                 wpa_supplicant_cancel_sched_scan(wpa_s);
6302                 wpa_supplicant_cancel_scan(wpa_s);
6303                 wpa_supplicant_deauthenticate(wpa_s,
6304                                               WLAN_REASON_DEAUTH_LEAVING);
6305         } else if (os_strcmp(buf, "SCAN") == 0) {
6306                 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
6307         } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
6308                 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
6309         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
6310                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
6311                         wpa_s, reply, reply_size);
6312         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
6313                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
6314                         reply_len = -1;
6315         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
6316                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
6317                         reply_len = -1;
6318         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
6319                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
6320                         reply_len = -1;
6321         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
6322                 reply_len = wpa_supplicant_ctrl_iface_add_network(
6323                         wpa_s, reply, reply_size);
6324         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
6325                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
6326                         reply_len = -1;
6327         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
6328                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
6329                         reply_len = -1;
6330         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
6331                 reply_len = wpa_supplicant_ctrl_iface_get_network(
6332                         wpa_s, buf + 12, reply, reply_size);
6333         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
6334                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
6335                         wpa_s, reply, reply_size);
6336         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
6337                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
6338                         wpa_s, reply, reply_size);
6339         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
6340                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
6341                         reply_len = -1;
6342         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
6343                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
6344                         reply_len = -1;
6345 #ifndef CONFIG_NO_CONFIG_WRITE
6346         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
6347                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
6348                         reply_len = -1;
6349 #endif /* CONFIG_NO_CONFIG_WRITE */
6350         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
6351                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
6352                         wpa_s, buf + 15, reply, reply_size);
6353         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
6354                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
6355                         reply_len = -1;
6356         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
6357                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
6358                         reply_len = -1;
6359         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
6360                 reply_len = wpa_supplicant_global_iface_list(
6361                         wpa_s->global, reply, reply_size);
6362         } else if (os_strcmp(buf, "INTERFACES") == 0) {
6363                 reply_len = wpa_supplicant_global_iface_interfaces(
6364                         wpa_s->global, reply, reply_size);
6365         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
6366                 reply_len = wpa_supplicant_ctrl_iface_bss(
6367                         wpa_s, buf + 4, reply, reply_size);
6368 #ifdef CONFIG_AP
6369         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
6370                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
6371         } else if (os_strncmp(buf, "STA ", 4) == 0) {
6372                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
6373                                               reply_size);
6374         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
6375                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
6376                                                    reply_size);
6377         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
6378                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
6379                         reply_len = -1;
6380         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
6381                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
6382                         reply_len = -1;
6383         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
6384                 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
6385                         reply_len = -1;
6386 #endif /* CONFIG_AP */
6387         } else if (os_strcmp(buf, "SUSPEND") == 0) {
6388                 wpas_notify_suspend(wpa_s->global);
6389         } else if (os_strcmp(buf, "RESUME") == 0) {
6390                 wpas_notify_resume(wpa_s->global);
6391         } else if (os_strcmp(buf, "DROP_SA") == 0) {
6392                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
6393         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
6394                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
6395                         reply_len = -1;
6396         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
6397                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
6398                         reply_len = -1;
6399         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
6400                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
6401                         reply_len = -1;
6402         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
6403                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
6404                                                                buf + 17))
6405                         reply_len = -1;
6406         } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
6407                 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
6408                         reply_len = -1;
6409 #ifdef CONFIG_TDLS
6410         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
6411                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
6412                         reply_len = -1;
6413         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
6414                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
6415                         reply_len = -1;
6416         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
6417                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
6418                         reply_len = -1;
6419 #endif /* CONFIG_TDLS */
6420         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
6421                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
6422                                                        reply_size);
6423         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
6424                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
6425                                                        reply_size);
6426 #ifdef CONFIG_AUTOSCAN
6427         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
6428                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
6429                         reply_len = -1;
6430 #endif /* CONFIG_AUTOSCAN */
6431 #ifdef ANDROID
6432         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
6433                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
6434                                                       reply_size);
6435 #endif /* ANDROID */
6436         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
6437                 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
6438                                                       reply_size);
6439         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
6440                 pmksa_cache_clear_current(wpa_s->wpa);
6441                 eapol_sm_request_reauth(wpa_s->eapol);
6442 #ifdef CONFIG_WNM
6443         } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
6444                 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
6445                         reply_len = -1;
6446         } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) {
6447                 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10))
6448                                 reply_len = -1;
6449 #endif /* CONFIG_WNM */
6450         } else if (os_strcmp(buf, "FLUSH") == 0) {
6451                 wpa_supplicant_ctrl_iface_flush(wpa_s);
6452         } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
6453                 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
6454                                                  reply_size);
6455 #ifdef CONFIG_TESTING_OPTIONS
6456         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
6457                 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
6458                         reply_len = -1;
6459         } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
6460                 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
6461 #endif /* CONFIG_TESTING_OPTIONS */
6462         } else {
6463                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
6464                 reply_len = 16;
6465         }
6466
6467         if (reply_len < 0) {
6468                 os_memcpy(reply, "FAIL\n", 5);
6469                 reply_len = 5;
6470         }
6471
6472         *resp_len = reply_len;
6473         return reply;
6474 }
6475
6476
6477 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
6478                                            char *cmd)
6479 {
6480         struct wpa_interface iface;
6481         char *pos;
6482
6483         /*
6484          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
6485          * TAB<bridge_ifname>
6486          */
6487         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
6488
6489         os_memset(&iface, 0, sizeof(iface));
6490
6491         do {
6492                 iface.ifname = pos = cmd;
6493                 pos = os_strchr(pos, '\t');
6494                 if (pos)
6495                         *pos++ = '\0';
6496                 if (iface.ifname[0] == '\0')
6497                         return -1;
6498                 if (pos == NULL)
6499                         break;
6500
6501                 iface.confname = pos;
6502                 pos = os_strchr(pos, '\t');
6503                 if (pos)
6504                         *pos++ = '\0';
6505                 if (iface.confname[0] == '\0')
6506                         iface.confname = NULL;
6507                 if (pos == NULL)
6508                         break;
6509
6510                 iface.driver = pos;
6511                 pos = os_strchr(pos, '\t');
6512                 if (pos)
6513                         *pos++ = '\0';
6514                 if (iface.driver[0] == '\0')
6515                         iface.driver = NULL;
6516                 if (pos == NULL)
6517                         break;
6518
6519                 iface.ctrl_interface = pos;
6520                 pos = os_strchr(pos, '\t');
6521                 if (pos)
6522                         *pos++ = '\0';
6523                 if (iface.ctrl_interface[0] == '\0')
6524                         iface.ctrl_interface = NULL;
6525                 if (pos == NULL)
6526                         break;
6527
6528                 iface.driver_param = pos;
6529                 pos = os_strchr(pos, '\t');
6530                 if (pos)
6531                         *pos++ = '\0';
6532                 if (iface.driver_param[0] == '\0')
6533                         iface.driver_param = NULL;
6534                 if (pos == NULL)
6535                         break;
6536
6537                 iface.bridge_ifname = pos;
6538                 pos = os_strchr(pos, '\t');
6539                 if (pos)
6540                         *pos++ = '\0';
6541                 if (iface.bridge_ifname[0] == '\0')
6542                         iface.bridge_ifname = NULL;
6543                 if (pos == NULL)
6544                         break;
6545         } while (0);
6546
6547         if (wpa_supplicant_get_iface(global, iface.ifname))
6548                 return -1;
6549
6550         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
6551 }
6552
6553
6554 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
6555                                               char *cmd)
6556 {
6557         struct wpa_supplicant *wpa_s;
6558
6559         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
6560
6561         wpa_s = wpa_supplicant_get_iface(global, cmd);
6562         if (wpa_s == NULL)
6563                 return -1;
6564         return wpa_supplicant_remove_iface(global, wpa_s, 0);
6565 }
6566
6567
6568 static void wpa_free_iface_info(struct wpa_interface_info *iface)
6569 {
6570         struct wpa_interface_info *prev;
6571
6572         while (iface) {
6573                 prev = iface;
6574                 iface = iface->next;
6575
6576                 os_free(prev->ifname);
6577                 os_free(prev->desc);
6578                 os_free(prev);
6579         }
6580 }
6581
6582
6583 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
6584                                             char *buf, int len)
6585 {
6586         int i, res;
6587         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
6588         char *pos, *end;
6589
6590         for (i = 0; wpa_drivers[i]; i++) {
6591                 struct wpa_driver_ops *drv = wpa_drivers[i];
6592                 if (drv->get_interfaces == NULL)
6593                         continue;
6594                 tmp = drv->get_interfaces(global->drv_priv[i]);
6595                 if (tmp == NULL)
6596                         continue;
6597
6598                 if (last == NULL)
6599                         iface = last = tmp;
6600                 else
6601                         last->next = tmp;
6602                 while (last->next)
6603                         last = last->next;
6604         }
6605
6606         pos = buf;
6607         end = buf + len;
6608         for (tmp = iface; tmp; tmp = tmp->next) {
6609                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
6610                                   tmp->drv_name, tmp->ifname,
6611                                   tmp->desc ? tmp->desc : "");
6612                 if (res < 0 || res >= end - pos) {
6613                         *pos = '\0';
6614                         break;
6615                 }
6616                 pos += res;
6617         }
6618
6619         wpa_free_iface_info(iface);
6620
6621         return pos - buf;
6622 }
6623
6624
6625 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
6626                                                   char *buf, int len)
6627 {
6628         int res;
6629         char *pos, *end;
6630         struct wpa_supplicant *wpa_s;
6631
6632         wpa_s = global->ifaces;
6633         pos = buf;
6634         end = buf + len;
6635
6636         while (wpa_s) {
6637                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
6638                 if (res < 0 || res >= end - pos) {
6639                         *pos = '\0';
6640                         break;
6641                 }
6642                 pos += res;
6643                 wpa_s = wpa_s->next;
6644         }
6645         return pos - buf;
6646 }
6647
6648
6649 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
6650                                             const char *ifname,
6651                                             char *cmd, size_t *resp_len)
6652 {
6653         struct wpa_supplicant *wpa_s;
6654
6655         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6656                 if (os_strcmp(ifname, wpa_s->ifname) == 0)
6657                         break;
6658         }
6659
6660         if (wpa_s == NULL) {
6661                 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
6662                 if (resp)
6663                         *resp_len = os_strlen(resp);
6664                 else
6665                         *resp_len = 1;
6666                 return resp;
6667         }
6668
6669         return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
6670 }
6671
6672
6673 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
6674                                                char *buf, size_t *resp_len)
6675 {
6676 #ifdef CONFIG_P2P
6677         static const char * cmd[] = {
6678                 "LIST_NETWORKS",
6679                 "SAVE_CONFIG",
6680                 "P2P_FIND",
6681                 "P2P_STOP_FIND",
6682                 "P2P_LISTEN",
6683                 "P2P_GROUP_ADD",
6684                 "P2P_GET_PASSPHRASE",
6685                 "P2P_SERVICE_UPDATE",
6686                 "P2P_SERVICE_FLUSH",
6687                 "P2P_FLUSH",
6688                 "P2P_CANCEL",
6689                 "P2P_PRESENCE_REQ",
6690                 "P2P_EXT_LISTEN",
6691                 NULL
6692         };
6693         static const char * prefix[] = {
6694 #ifdef ANDROID
6695                 "DRIVER ",
6696 #endif /* ANDROID */
6697                 "GET_NETWORK ",
6698                 "REMOVE_NETWORK ",
6699                 "SET ",
6700                 "P2P_FIND ",
6701                 "P2P_CONNECT ",
6702                 "P2P_LISTEN ",
6703                 "P2P_GROUP_REMOVE ",
6704                 "P2P_GROUP_ADD ",
6705                 "P2P_PROV_DISC ",
6706                 "P2P_SERV_DISC_REQ ",
6707                 "P2P_SERV_DISC_CANCEL_REQ ",
6708                 "P2P_SERV_DISC_RESP ",
6709                 "P2P_SERV_DISC_EXTERNAL ",
6710                 "P2P_SERVICE_ADD ",
6711                 "P2P_SERVICE_DEL ",
6712                 "P2P_REJECT ",
6713                 "P2P_INVITE ",
6714                 "P2P_PEER ",
6715                 "P2P_SET ",
6716                 "P2P_UNAUTHORIZE ",
6717                 "P2P_PRESENCE_REQ ",
6718                 "P2P_EXT_LISTEN ",
6719                 "P2P_REMOVE_CLIENT ",
6720                 NULL
6721         };
6722         int found = 0;
6723         int i;
6724
6725         if (global->p2p_init_wpa_s == NULL)
6726                 return NULL;
6727
6728         for (i = 0; !found && cmd[i]; i++) {
6729                 if (os_strcmp(buf, cmd[i]) == 0)
6730                         found = 1;
6731         }
6732
6733         for (i = 0; !found && prefix[i]; i++) {
6734                 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
6735                         found = 1;
6736         }
6737
6738         if (found)
6739                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6740                                                          buf, resp_len);
6741 #endif /* CONFIG_P2P */
6742         return NULL;
6743 }
6744
6745
6746 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
6747                                                char *buf, size_t *resp_len)
6748 {
6749 #ifdef CONFIG_WIFI_DISPLAY
6750         if (global->p2p_init_wpa_s == NULL)
6751                 return NULL;
6752         if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
6753             os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
6754                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6755                                                          buf, resp_len);
6756 #endif /* CONFIG_WIFI_DISPLAY */
6757         return NULL;
6758 }
6759
6760
6761 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
6762                                            char *buf, size_t *resp_len)
6763 {
6764         char *ret;
6765
6766         ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
6767         if (ret)
6768                 return ret;
6769
6770         ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
6771         if (ret)
6772                 return ret;
6773
6774         return NULL;
6775 }
6776
6777
6778 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
6779 {
6780         char *value;
6781
6782         value = os_strchr(cmd, ' ');
6783         if (value == NULL)
6784                 return -1;
6785         *value++ = '\0';
6786
6787         wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
6788
6789 #ifdef CONFIG_WIFI_DISPLAY
6790         if (os_strcasecmp(cmd, "wifi_display") == 0) {
6791                 wifi_display_enable(global, !!atoi(value));
6792                 return 0;
6793         }
6794 #endif /* CONFIG_WIFI_DISPLAY */
6795
6796         return -1;
6797 }
6798
6799
6800 #ifndef CONFIG_NO_CONFIG_WRITE
6801 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
6802 {
6803         int ret = 0;
6804         struct wpa_supplicant *wpa_s;
6805
6806         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6807                 if (!wpa_s->conf->update_config) {
6808                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
6809                         continue;
6810                 }
6811
6812                 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
6813                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
6814                         ret = 1;
6815                 } else {
6816                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
6817                 }
6818         }
6819
6820         return ret;
6821 }
6822 #endif /* CONFIG_NO_CONFIG_WRITE */
6823
6824
6825 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
6826                                          char *buf, size_t buflen)
6827 {
6828         char *pos, *end;
6829         int ret;
6830         struct wpa_supplicant *wpa_s;
6831
6832         pos = buf;
6833         end = buf + buflen;
6834
6835 #ifdef CONFIG_P2P
6836         if (global->p2p && !global->p2p_disabled) {
6837                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
6838                                   "\n"
6839                                   "p2p_state=%s\n",
6840                                   MAC2STR(global->p2p_dev_addr),
6841                                   p2p_get_state_txt(global->p2p));
6842                 if (ret < 0 || ret >= end - pos)
6843                         return pos - buf;
6844                 pos += ret;
6845         } else if (global->p2p) {
6846                 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
6847                 if (ret < 0 || ret >= end - pos)
6848                         return pos - buf;
6849                 pos += ret;
6850         }
6851 #endif /* CONFIG_P2P */
6852
6853 #ifdef CONFIG_WIFI_DISPLAY
6854         ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
6855                           !!global->wifi_display);
6856         if (ret < 0 || ret >= end - pos)
6857                 return pos - buf;
6858         pos += ret;
6859 #endif /* CONFIG_WIFI_DISPLAY */
6860
6861         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6862                 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
6863                                   "address=" MACSTR "\n",
6864                                   wpa_s->ifname, MAC2STR(wpa_s->own_addr));
6865                 if (ret < 0 || ret >= end - pos)
6866                         return pos - buf;
6867                 pos += ret;
6868         }
6869
6870         return pos - buf;
6871 }
6872
6873
6874 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
6875                                                 char *buf, size_t *resp_len)
6876 {
6877         char *reply;
6878         const int reply_size = 2048;
6879         int reply_len;
6880         int level = MSG_DEBUG;
6881
6882         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
6883                 char *pos = os_strchr(buf + 7, ' ');
6884                 if (pos) {
6885                         *pos++ = '\0';
6886                         return wpas_global_ctrl_iface_ifname(global,
6887                                                              buf + 7, pos,
6888                                                              resp_len);
6889                 }
6890         }
6891
6892         reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
6893         if (reply)
6894                 return reply;
6895
6896         if (os_strcmp(buf, "PING") == 0)
6897                 level = MSG_EXCESSIVE;
6898         wpa_hexdump_ascii(level, "RX global ctrl_iface",
6899                           (const u8 *) buf, os_strlen(buf));
6900
6901         reply = os_malloc(reply_size);
6902         if (reply == NULL) {
6903                 *resp_len = 1;
6904                 return NULL;
6905         }
6906
6907         os_memcpy(reply, "OK\n", 3);
6908         reply_len = 3;
6909
6910         if (os_strcmp(buf, "PING") == 0) {
6911                 os_memcpy(reply, "PONG\n", 5);
6912                 reply_len = 5;
6913         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
6914                 if (wpa_supplicant_global_iface_add(global, buf + 14))
6915                         reply_len = -1;
6916         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
6917                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
6918                         reply_len = -1;
6919         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
6920                 reply_len = wpa_supplicant_global_iface_list(
6921                         global, reply, reply_size);
6922         } else if (os_strcmp(buf, "INTERFACES") == 0) {
6923                 reply_len = wpa_supplicant_global_iface_interfaces(
6924                         global, reply, reply_size);
6925         } else if (os_strcmp(buf, "TERMINATE") == 0) {
6926                 wpa_supplicant_terminate_proc(global);
6927         } else if (os_strcmp(buf, "SUSPEND") == 0) {
6928                 wpas_notify_suspend(global);
6929         } else if (os_strcmp(buf, "RESUME") == 0) {
6930                 wpas_notify_resume(global);
6931         } else if (os_strncmp(buf, "SET ", 4) == 0) {
6932                 if (wpas_global_ctrl_iface_set(global, buf + 4))
6933                         reply_len = -1;
6934 #ifndef CONFIG_NO_CONFIG_WRITE
6935         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
6936                 if (wpas_global_ctrl_iface_save_config(global))
6937                         reply_len = -1;
6938 #endif /* CONFIG_NO_CONFIG_WRITE */
6939         } else if (os_strcmp(buf, "STATUS") == 0) {
6940                 reply_len = wpas_global_ctrl_iface_status(global, reply,
6941                                                           reply_size);
6942 #ifdef CONFIG_MODULE_TESTS
6943         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
6944                 int wpas_module_tests(void);
6945                 if (wpas_module_tests() < 0)
6946                         reply_len = -1;
6947 #endif /* CONFIG_MODULE_TESTS */
6948         } else {
6949                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
6950                 reply_len = 16;
6951         }
6952
6953         if (reply_len < 0) {
6954                 os_memcpy(reply, "FAIL\n", 5);
6955                 reply_len = 5;
6956         }
6957
6958         *resp_len = reply_len;
6959         return reply;
6960 }