Declare all read only data structures as const
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2015, 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 #ifdef CONFIG_TESTING_OPTIONS
11 #include <net/ethernet.h>
12 #include <netinet/ip.h>
13 #endif /* CONFIG_TESTING_OPTIONS */
14
15 #include "utils/common.h"
16 #include "utils/eloop.h"
17 #include "utils/uuid.h"
18 #include "common/version.h"
19 #include "common/ieee802_11_defs.h"
20 #include "common/ieee802_11_common.h"
21 #include "common/wpa_ctrl.h"
22 #include "crypto/tls.h"
23 #include "ap/hostapd.h"
24 #include "eap_peer/eap.h"
25 #include "eapol_supp/eapol_supp_sm.h"
26 #include "rsn_supp/wpa.h"
27 #include "rsn_supp/preauth.h"
28 #include "rsn_supp/pmksa_cache.h"
29 #include "l2_packet/l2_packet.h"
30 #include "wps/wps.h"
31 #include "config.h"
32 #include "wpa_supplicant_i.h"
33 #include "driver_i.h"
34 #include "wps_supplicant.h"
35 #include "ibss_rsn.h"
36 #include "ap.h"
37 #include "p2p_supplicant.h"
38 #include "p2p/p2p.h"
39 #include "hs20_supplicant.h"
40 #include "wifi_display.h"
41 #include "notify.h"
42 #include "bss.h"
43 #include "scan.h"
44 #include "ctrl_iface.h"
45 #include "interworking.h"
46 #include "blacklist.h"
47 #include "autoscan.h"
48 #include "wnm_sta.h"
49 #include "offchannel.h"
50 #include "drivers/driver.h"
51 #include "mesh.h"
52
53 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
54                                             char *buf, int len);
55 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
56                                                   char *buf, int len);
57 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
58                                         char *val);
59
60 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
61 {
62         char *pos;
63         u8 addr[ETH_ALEN], *filter = NULL, *n;
64         size_t count = 0;
65
66         pos = val;
67         while (pos) {
68                 if (*pos == '\0')
69                         break;
70                 if (hwaddr_aton(pos, addr)) {
71                         os_free(filter);
72                         return -1;
73                 }
74                 n = os_realloc_array(filter, count + 1, ETH_ALEN);
75                 if (n == NULL) {
76                         os_free(filter);
77                         return -1;
78                 }
79                 filter = n;
80                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
81                 count++;
82
83                 pos = os_strchr(pos, ' ');
84                 if (pos)
85                         pos++;
86         }
87
88         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
89         os_free(wpa_s->bssid_filter);
90         wpa_s->bssid_filter = filter;
91         wpa_s->bssid_filter_count = count;
92
93         return 0;
94 }
95
96
97 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
98 {
99         char *pos;
100         u8 addr[ETH_ALEN], *bssid = NULL, *n;
101         struct wpa_ssid_value *ssid = NULL, *ns;
102         size_t count = 0, ssid_count = 0;
103         struct wpa_ssid *c;
104
105         /*
106          * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
107          * SSID_SPEC ::= ssid <SSID_HEX>
108          * BSSID_SPEC ::= bssid <BSSID_HEX>
109          */
110
111         pos = val;
112         while (pos) {
113                 if (*pos == '\0')
114                         break;
115                 if (os_strncmp(pos, "bssid ", 6) == 0) {
116                         int res;
117                         pos += 6;
118                         res = hwaddr_aton2(pos, addr);
119                         if (res < 0) {
120                                 os_free(ssid);
121                                 os_free(bssid);
122                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
123                                            "BSSID value '%s'", pos);
124                                 return -1;
125                         }
126                         pos += res;
127                         n = os_realloc_array(bssid, count + 1, ETH_ALEN);
128                         if (n == NULL) {
129                                 os_free(ssid);
130                                 os_free(bssid);
131                                 return -1;
132                         }
133                         bssid = n;
134                         os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
135                         count++;
136                 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
137                         char *end;
138                         pos += 5;
139
140                         end = pos;
141                         while (*end) {
142                                 if (*end == '\0' || *end == ' ')
143                                         break;
144                                 end++;
145                         }
146
147                         ns = os_realloc_array(ssid, ssid_count + 1,
148                                               sizeof(struct wpa_ssid_value));
149                         if (ns == NULL) {
150                                 os_free(ssid);
151                                 os_free(bssid);
152                                 return -1;
153                         }
154                         ssid = ns;
155
156                         if ((end - pos) & 0x01 ||
157                             end - pos > 2 * SSID_MAX_LEN ||
158                             hexstr2bin(pos, ssid[ssid_count].ssid,
159                                        (end - pos) / 2) < 0) {
160                                 os_free(ssid);
161                                 os_free(bssid);
162                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
163                                            "SSID value '%s'", pos);
164                                 return -1;
165                         }
166                         ssid[ssid_count].ssid_len = (end - pos) / 2;
167                         wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
168                                           ssid[ssid_count].ssid,
169                                           ssid[ssid_count].ssid_len);
170                         ssid_count++;
171                         pos = end;
172                 } else {
173                         wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
174                                    "'%s'", pos);
175                         os_free(ssid);
176                         os_free(bssid);
177                         return -1;
178                 }
179
180                 pos = os_strchr(pos, ' ');
181                 if (pos)
182                         pos++;
183         }
184
185         wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
186         os_free(wpa_s->disallow_aps_bssid);
187         wpa_s->disallow_aps_bssid = bssid;
188         wpa_s->disallow_aps_bssid_count = count;
189
190         wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
191         os_free(wpa_s->disallow_aps_ssid);
192         wpa_s->disallow_aps_ssid = ssid;
193         wpa_s->disallow_aps_ssid_count = ssid_count;
194
195         if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
196                 return 0;
197
198         c = wpa_s->current_ssid;
199         if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
200                 return 0;
201
202         if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
203             !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
204                 return 0;
205
206         wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
207                    "because current AP was marked disallowed");
208
209 #ifdef CONFIG_SME
210         wpa_s->sme.prev_bssid_set = 0;
211 #endif /* CONFIG_SME */
212         wpa_s->reassociate = 1;
213         wpa_s->own_disconnect_req = 1;
214         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
215         wpa_supplicant_req_scan(wpa_s, 0, 0);
216
217         return 0;
218 }
219
220
221 #ifndef CONFIG_NO_CONFIG_BLOBS
222 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
223 {
224         char *name = pos;
225         struct wpa_config_blob *blob;
226         size_t len;
227
228         pos = os_strchr(pos, ' ');
229         if (pos == NULL)
230                 return -1;
231         *pos++ = '\0';
232         len = os_strlen(pos);
233         if (len & 1)
234                 return -1;
235
236         wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
237         blob = os_zalloc(sizeof(*blob));
238         if (blob == NULL)
239                 return -1;
240         blob->name = os_strdup(name);
241         blob->data = os_malloc(len / 2);
242         if (blob->name == NULL || blob->data == NULL) {
243                 wpa_config_free_blob(blob);
244                 return -1;
245         }
246
247         if (hexstr2bin(pos, blob->data, len / 2) < 0) {
248                 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
249                 wpa_config_free_blob(blob);
250                 return -1;
251         }
252         blob->len = len / 2;
253
254         wpa_config_set_blob(wpa_s->conf, blob);
255
256         return 0;
257 }
258 #endif /* CONFIG_NO_CONFIG_BLOBS */
259
260
261 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
262 {
263         char *params;
264         char *pos;
265         int *freqs = NULL;
266         int ret;
267
268         if (atoi(cmd)) {
269                 params = os_strchr(cmd, ' ');
270                 os_free(wpa_s->manual_sched_scan_freqs);
271                 if (params) {
272                         params++;
273                         pos = os_strstr(params, "freq=");
274                         if (pos)
275                                 freqs = freq_range_to_channel_list(wpa_s,
276                                                                    pos + 5);
277                 }
278                 wpa_s->manual_sched_scan_freqs = freqs;
279                 ret = wpas_start_pno(wpa_s);
280         } else {
281                 ret = wpas_stop_pno(wpa_s);
282         }
283         return ret;
284 }
285
286
287 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
288                                          char *cmd)
289 {
290         char *value;
291         int ret = 0;
292
293         value = os_strchr(cmd, ' ');
294         if (value == NULL)
295                 return -1;
296         *value++ = '\0';
297
298         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
299         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
300                 eapol_sm_configure(wpa_s->eapol,
301                                    atoi(value), -1, -1, -1);
302         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
303                 eapol_sm_configure(wpa_s->eapol,
304                                    -1, atoi(value), -1, -1);
305         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
306                 eapol_sm_configure(wpa_s->eapol,
307                                    -1, -1, atoi(value), -1);
308         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
309                 eapol_sm_configure(wpa_s->eapol,
310                                    -1, -1, -1, atoi(value));
311         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
312                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
313                                      atoi(value)))
314                         ret = -1;
315         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
316                    0) {
317                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
318                                      atoi(value)))
319                         ret = -1;
320         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
321                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
322                         ret = -1;
323         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
324                 wpa_s->wps_fragment_size = atoi(value);
325 #ifdef CONFIG_WPS_TESTING
326         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
327                 long int val;
328                 val = strtol(value, NULL, 0);
329                 if (val < 0 || val > 0xff) {
330                         ret = -1;
331                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
332                                    "wps_version_number %ld", val);
333                 } else {
334                         wps_version_number = val;
335                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
336                                    "version %u.%u",
337                                    (wps_version_number & 0xf0) >> 4,
338                                    wps_version_number & 0x0f);
339                 }
340         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
341                 wps_testing_dummy_cred = atoi(value);
342                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
343                            wps_testing_dummy_cred);
344         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
345                 wps_corrupt_pkhash = atoi(value);
346                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
347                            wps_corrupt_pkhash);
348 #endif /* CONFIG_WPS_TESTING */
349         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
350                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
351                         ret = -1;
352 #ifdef CONFIG_TDLS
353 #ifdef CONFIG_TDLS_TESTING
354         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
355                 extern unsigned int tdls_testing;
356                 tdls_testing = strtol(value, NULL, 0);
357                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
358 #endif /* CONFIG_TDLS_TESTING */
359         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
360                 int disabled = atoi(value);
361                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
362                 if (disabled) {
363                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
364                                 ret = -1;
365                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
366                         ret = -1;
367                 wpa_tdls_enable(wpa_s->wpa, !disabled);
368 #endif /* CONFIG_TDLS */
369         } else if (os_strcasecmp(cmd, "pno") == 0) {
370                 ret = wpas_ctrl_pno(wpa_s, value);
371         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
372                 int disabled = atoi(value);
373                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
374                         ret = -1;
375                 else if (disabled)
376                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
377         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
378                 if (os_strcmp(value, "disable") == 0)
379                         wpa_s->set_sta_uapsd = 0;
380                 else {
381                         int be, bk, vi, vo;
382                         char *pos;
383                         /* format: BE,BK,VI,VO;max SP Length */
384                         be = atoi(value);
385                         pos = os_strchr(value, ',');
386                         if (pos == NULL)
387                                 return -1;
388                         pos++;
389                         bk = atoi(pos);
390                         pos = os_strchr(pos, ',');
391                         if (pos == NULL)
392                                 return -1;
393                         pos++;
394                         vi = atoi(pos);
395                         pos = os_strchr(pos, ',');
396                         if (pos == NULL)
397                                 return -1;
398                         pos++;
399                         vo = atoi(pos);
400                         /* ignore max SP Length for now */
401
402                         wpa_s->set_sta_uapsd = 1;
403                         wpa_s->sta_uapsd = 0;
404                         if (be)
405                                 wpa_s->sta_uapsd |= BIT(0);
406                         if (bk)
407                                 wpa_s->sta_uapsd |= BIT(1);
408                         if (vi)
409                                 wpa_s->sta_uapsd |= BIT(2);
410                         if (vo)
411                                 wpa_s->sta_uapsd |= BIT(3);
412                 }
413         } else if (os_strcasecmp(cmd, "ps") == 0) {
414                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
415 #ifdef CONFIG_WIFI_DISPLAY
416         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
417                 int enabled = !!atoi(value);
418                 if (enabled && !wpa_s->global->p2p)
419                         ret = -1;
420                 else
421                         wifi_display_enable(wpa_s->global, enabled);
422 #endif /* CONFIG_WIFI_DISPLAY */
423         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
424                 ret = set_bssid_filter(wpa_s, value);
425         } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
426                 ret = set_disallow_aps(wpa_s, value);
427         } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
428                 wpa_s->no_keep_alive = !!atoi(value);
429 #ifdef CONFIG_TESTING_OPTIONS
430         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
431                 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
432         } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
433                 wpa_s->ext_eapol_frame_io = !!atoi(value);
434 #ifdef CONFIG_AP
435                 if (wpa_s->ap_iface) {
436                         wpa_s->ap_iface->bss[0]->ext_eapol_frame_io =
437                                 wpa_s->ext_eapol_frame_io;
438                 }
439 #endif /* CONFIG_AP */
440         } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) {
441                 wpa_s->extra_roc_dur = atoi(value);
442         } else if (os_strcasecmp(cmd, "test_failure") == 0) {
443                 wpa_s->test_failure = atoi(value);
444 #endif /* CONFIG_TESTING_OPTIONS */
445 #ifndef CONFIG_NO_CONFIG_BLOBS
446         } else if (os_strcmp(cmd, "blob") == 0) {
447                 ret = wpas_ctrl_set_blob(wpa_s, value);
448 #endif /* CONFIG_NO_CONFIG_BLOBS */
449         } else if (os_strcasecmp(cmd, "setband") == 0) {
450                 if (os_strcmp(value, "AUTO") == 0)
451                         wpa_s->setband = WPA_SETBAND_AUTO;
452                 else if (os_strcmp(value, "5G") == 0)
453                         wpa_s->setband = WPA_SETBAND_5G;
454                 else if (os_strcmp(value, "2G") == 0)
455                         wpa_s->setband = WPA_SETBAND_2G;
456                 else
457                         ret = -1;
458         } else {
459                 value[-1] = '=';
460                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
461                 if (ret == 0)
462                         wpa_supplicant_update_config(wpa_s);
463         }
464
465         return ret;
466 }
467
468
469 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
470                                          char *cmd, char *buf, size_t buflen)
471 {
472         int res = -1;
473
474         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
475
476         if (os_strcmp(cmd, "version") == 0) {
477                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
478         } else if (os_strcasecmp(cmd, "country") == 0) {
479                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
480                         res = os_snprintf(buf, buflen, "%c%c",
481                                           wpa_s->conf->country[0],
482                                           wpa_s->conf->country[1]);
483 #ifdef CONFIG_WIFI_DISPLAY
484         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
485                 int enabled;
486                 if (wpa_s->global->p2p == NULL ||
487                     wpa_s->global->p2p_disabled)
488                         enabled = 0;
489                 else
490                         enabled = wpa_s->global->wifi_display;
491                 res = os_snprintf(buf, buflen, "%d", enabled);
492 #endif /* CONFIG_WIFI_DISPLAY */
493 #ifdef CONFIG_TESTING_GET_GTK
494         } else if (os_strcmp(cmd, "gtk") == 0) {
495                 if (wpa_s->last_gtk_len == 0)
496                         return -1;
497                 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
498                                        wpa_s->last_gtk_len);
499                 return res;
500 #endif /* CONFIG_TESTING_GET_GTK */
501         } else if (os_strcmp(cmd, "tls_library") == 0) {
502                 res = tls_get_library_version(buf, buflen);
503         } else {
504                 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen);
505         }
506
507         if (os_snprintf_error(buflen, res))
508                 return -1;
509         return res;
510 }
511
512
513 #ifdef IEEE8021X_EAPOL
514 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
515                                              char *addr)
516 {
517         u8 bssid[ETH_ALEN];
518         struct wpa_ssid *ssid = wpa_s->current_ssid;
519
520         if (hwaddr_aton(addr, bssid)) {
521                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
522                            "'%s'", addr);
523                 return -1;
524         }
525
526         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
527         rsn_preauth_deinit(wpa_s->wpa);
528         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
529                 return -1;
530
531         return 0;
532 }
533 #endif /* IEEE8021X_EAPOL */
534
535
536 #ifdef CONFIG_PEERKEY
537 /* MLME-STKSTART.request(peer) */
538 static int wpa_supplicant_ctrl_iface_stkstart(
539         struct wpa_supplicant *wpa_s, char *addr)
540 {
541         u8 peer[ETH_ALEN];
542
543         if (hwaddr_aton(addr, peer)) {
544                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
545                            "address '%s'", addr);
546                 return -1;
547         }
548
549         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
550                    MAC2STR(peer));
551
552         return wpa_sm_stkstart(wpa_s->wpa, peer);
553 }
554 #endif /* CONFIG_PEERKEY */
555
556
557 #ifdef CONFIG_TDLS
558
559 static int wpa_supplicant_ctrl_iface_tdls_discover(
560         struct wpa_supplicant *wpa_s, char *addr)
561 {
562         u8 peer[ETH_ALEN];
563         int ret;
564
565         if (hwaddr_aton(addr, peer)) {
566                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
567                            "address '%s'", addr);
568                 return -1;
569         }
570
571         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
572                    MAC2STR(peer));
573
574         if (wpa_tdls_is_external_setup(wpa_s->wpa))
575                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
576         else
577                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
578
579         return ret;
580 }
581
582
583 static int wpa_supplicant_ctrl_iface_tdls_setup(
584         struct wpa_supplicant *wpa_s, char *addr)
585 {
586         u8 peer[ETH_ALEN];
587         int ret;
588
589         if (hwaddr_aton(addr, peer)) {
590                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
591                            "address '%s'", addr);
592                 return -1;
593         }
594
595         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
596                    MAC2STR(peer));
597
598         if ((wpa_s->conf->tdls_external_control) &&
599             wpa_tdls_is_external_setup(wpa_s->wpa))
600                 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
601
602         wpa_tdls_remove(wpa_s->wpa, peer);
603
604         if (wpa_tdls_is_external_setup(wpa_s->wpa))
605                 ret = wpa_tdls_start(wpa_s->wpa, peer);
606         else
607                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
608
609         return ret;
610 }
611
612
613 static int wpa_supplicant_ctrl_iface_tdls_teardown(
614         struct wpa_supplicant *wpa_s, char *addr)
615 {
616         u8 peer[ETH_ALEN];
617         int ret;
618
619         if (os_strcmp(addr, "*") == 0) {
620                 /* remove everyone */
621                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *");
622                 wpa_tdls_teardown_peers(wpa_s->wpa);
623                 return 0;
624         }
625
626         if (hwaddr_aton(addr, peer)) {
627                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
628                            "address '%s'", addr);
629                 return -1;
630         }
631
632         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
633                    MAC2STR(peer));
634
635         if ((wpa_s->conf->tdls_external_control) &&
636             wpa_tdls_is_external_setup(wpa_s->wpa))
637                 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
638
639         if (wpa_tdls_is_external_setup(wpa_s->wpa))
640                 ret = wpa_tdls_teardown_link(
641                         wpa_s->wpa, peer,
642                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
643         else
644                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
645
646         return ret;
647 }
648
649
650 static int ctrl_iface_get_capability_tdls(
651         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
652 {
653         int ret;
654
655         ret = os_snprintf(buf, buflen, "%s\n",
656                           wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
657                           (wpa_s->drv_flags &
658                            WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
659                            "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
660         if (os_snprintf_error(buflen, ret))
661                 return -1;
662         return ret;
663 }
664
665
666 static int wpa_supplicant_ctrl_iface_tdls_chan_switch(
667         struct wpa_supplicant *wpa_s, char *cmd)
668 {
669         u8 peer[ETH_ALEN];
670         struct hostapd_freq_params freq_params;
671         u8 oper_class;
672         char *pos, *end;
673
674         if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
675                 wpa_printf(MSG_INFO,
676                            "tdls_chanswitch: Only supported with external setup");
677                 return -1;
678         }
679
680         os_memset(&freq_params, 0, sizeof(freq_params));
681
682         pos = os_strchr(cmd, ' ');
683         if (pos == NULL)
684                 return -1;
685         *pos++ = '\0';
686
687         oper_class = strtol(pos, &end, 10);
688         if (pos == end) {
689                 wpa_printf(MSG_INFO,
690                            "tdls_chanswitch: Invalid op class provided");
691                 return -1;
692         }
693
694         pos = end;
695         freq_params.freq = atoi(pos);
696         if (freq_params.freq == 0) {
697                 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided");
698                 return -1;
699         }
700
701 #define SET_FREQ_SETTING(str) \
702         do { \
703                 const char *pos2 = os_strstr(pos, " " #str "="); \
704                 if (pos2) { \
705                         pos2 += sizeof(" " #str "=") - 1; \
706                         freq_params.str = atoi(pos2); \
707                 } \
708         } while (0)
709
710         SET_FREQ_SETTING(center_freq1);
711         SET_FREQ_SETTING(center_freq2);
712         SET_FREQ_SETTING(bandwidth);
713         SET_FREQ_SETTING(sec_channel_offset);
714 #undef SET_FREQ_SETTING
715
716         freq_params.ht_enabled = !!os_strstr(pos, " ht");
717         freq_params.vht_enabled = !!os_strstr(pos, " vht");
718
719         if (hwaddr_aton(cmd, peer)) {
720                 wpa_printf(MSG_DEBUG,
721                            "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'",
722                            cmd);
723                 return -1;
724         }
725
726         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR
727                    " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
728                    MAC2STR(peer), oper_class, freq_params.freq,
729                    freq_params.center_freq1, freq_params.center_freq2,
730                    freq_params.bandwidth, freq_params.sec_channel_offset,
731                    freq_params.ht_enabled ? " HT" : "",
732                    freq_params.vht_enabled ? " VHT" : "");
733
734         return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
735                                            &freq_params);
736 }
737
738
739 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(
740         struct wpa_supplicant *wpa_s, char *cmd)
741 {
742         u8 peer[ETH_ALEN];
743
744         if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
745                 wpa_printf(MSG_INFO,
746                            "tdls_chanswitch: Only supported with external setup");
747                 return -1;
748         }
749
750         if (hwaddr_aton(cmd, peer)) {
751                 wpa_printf(MSG_DEBUG,
752                            "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'",
753                            cmd);
754                 return -1;
755         }
756
757         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR,
758                    MAC2STR(peer));
759
760         return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
761 }
762
763 #endif /* CONFIG_TDLS */
764
765
766 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd)
767 {
768         char *token, *context = NULL;
769         struct wmm_ac_ts_setup_params params = {
770                 .tsid = 0xff,
771                 .direction = 0xff,
772         };
773
774         while ((token = str_token(cmd, " ", &context))) {
775                 if (sscanf(token, "tsid=%i", &params.tsid) == 1 ||
776                     sscanf(token, "up=%i", &params.user_priority) == 1 ||
777                     sscanf(token, "nominal_msdu_size=%i",
778                            &params.nominal_msdu_size) == 1 ||
779                     sscanf(token, "mean_data_rate=%i",
780                            &params.mean_data_rate) == 1 ||
781                     sscanf(token, "min_phy_rate=%i",
782                            &params.minimum_phy_rate) == 1 ||
783                     sscanf(token, "sba=%i",
784                            &params.surplus_bandwidth_allowance) == 1)
785                         continue;
786
787                 if (os_strcasecmp(token, "downlink") == 0) {
788                         params.direction = WMM_TSPEC_DIRECTION_DOWNLINK;
789                 } else if (os_strcasecmp(token, "uplink") == 0) {
790                         params.direction = WMM_TSPEC_DIRECTION_UPLINK;
791                 } else if (os_strcasecmp(token, "bidi") == 0) {
792                         params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL;
793                 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) {
794                         params.fixed_nominal_msdu = 1;
795                 } else {
796                         wpa_printf(MSG_DEBUG,
797                                    "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'",
798                                    token);
799                         return -1;
800                 }
801
802         }
803
804         return wpas_wmm_ac_addts(wpa_s, &params);
805 }
806
807
808 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd)
809 {
810         u8 tsid = atoi(cmd);
811
812         return wpas_wmm_ac_delts(wpa_s, tsid);
813 }
814
815
816 #ifdef CONFIG_IEEE80211R
817 static int wpa_supplicant_ctrl_iface_ft_ds(
818         struct wpa_supplicant *wpa_s, char *addr)
819 {
820         u8 target_ap[ETH_ALEN];
821         struct wpa_bss *bss;
822         const u8 *mdie;
823
824         if (hwaddr_aton(addr, target_ap)) {
825                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
826                            "address '%s'", addr);
827                 return -1;
828         }
829
830         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
831
832         bss = wpa_bss_get_bssid(wpa_s, target_ap);
833         if (bss)
834                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
835         else
836                 mdie = NULL;
837
838         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
839 }
840 #endif /* CONFIG_IEEE80211R */
841
842
843 #ifdef CONFIG_WPS
844 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
845                                              char *cmd)
846 {
847         u8 bssid[ETH_ALEN], *_bssid = bssid;
848 #ifdef CONFIG_P2P
849         u8 p2p_dev_addr[ETH_ALEN];
850 #endif /* CONFIG_P2P */
851 #ifdef CONFIG_AP
852         u8 *_p2p_dev_addr = NULL;
853 #endif /* CONFIG_AP */
854
855         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
856                 _bssid = NULL;
857 #ifdef CONFIG_P2P
858         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
859                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
860                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
861                                    "P2P Device Address '%s'",
862                                    cmd + 13);
863                         return -1;
864                 }
865                 _p2p_dev_addr = p2p_dev_addr;
866 #endif /* CONFIG_P2P */
867         } else if (hwaddr_aton(cmd, bssid)) {
868                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
869                            cmd);
870                 return -1;
871         }
872
873 #ifdef CONFIG_AP
874         if (wpa_s->ap_iface)
875                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
876 #endif /* CONFIG_AP */
877
878         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
879 }
880
881
882 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
883                                              char *cmd, char *buf,
884                                              size_t buflen)
885 {
886         u8 bssid[ETH_ALEN], *_bssid = bssid;
887         char *pin;
888         int ret;
889
890         pin = os_strchr(cmd, ' ');
891         if (pin)
892                 *pin++ = '\0';
893
894         if (os_strcmp(cmd, "any") == 0)
895                 _bssid = NULL;
896         else if (os_strcmp(cmd, "get") == 0) {
897                 ret = wps_generate_pin();
898                 goto done;
899         } else if (hwaddr_aton(cmd, bssid)) {
900                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
901                            cmd);
902                 return -1;
903         }
904
905 #ifdef CONFIG_AP
906         if (wpa_s->ap_iface) {
907                 int timeout = 0;
908                 char *pos;
909
910                 if (pin) {
911                         pos = os_strchr(pin, ' ');
912                         if (pos) {
913                                 *pos++ = '\0';
914                                 timeout = atoi(pos);
915                         }
916                 }
917
918                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
919                                                  buf, buflen, timeout);
920         }
921 #endif /* CONFIG_AP */
922
923         if (pin) {
924                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
925                                          DEV_PW_DEFAULT);
926                 if (ret < 0)
927                         return -1;
928                 ret = os_snprintf(buf, buflen, "%s", pin);
929                 if (os_snprintf_error(buflen, ret))
930                         return -1;
931                 return ret;
932         }
933
934         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
935         if (ret < 0)
936                 return -1;
937
938 done:
939         /* Return the generated PIN */
940         ret = os_snprintf(buf, buflen, "%08d", ret);
941         if (os_snprintf_error(buflen, ret))
942                 return -1;
943         return ret;
944 }
945
946
947 static int wpa_supplicant_ctrl_iface_wps_check_pin(
948         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
949 {
950         char pin[9];
951         size_t len;
952         char *pos;
953         int ret;
954
955         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
956                               (u8 *) cmd, os_strlen(cmd));
957         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
958                 if (*pos < '0' || *pos > '9')
959                         continue;
960                 pin[len++] = *pos;
961                 if (len == 9) {
962                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
963                         return -1;
964                 }
965         }
966         if (len != 4 && len != 8) {
967                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
968                 return -1;
969         }
970         pin[len] = '\0';
971
972         if (len == 8) {
973                 unsigned int pin_val;
974                 pin_val = atoi(pin);
975                 if (!wps_pin_valid(pin_val)) {
976                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
977                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
978                         if (os_snprintf_error(buflen, ret))
979                                 return -1;
980                         return ret;
981                 }
982         }
983
984         ret = os_snprintf(buf, buflen, "%s", pin);
985         if (os_snprintf_error(buflen, ret))
986                 return -1;
987
988         return ret;
989 }
990
991
992 #ifdef CONFIG_WPS_NFC
993
994 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
995                                              char *cmd)
996 {
997         u8 bssid[ETH_ALEN], *_bssid = bssid;
998
999         if (cmd == NULL || cmd[0] == '\0')
1000                 _bssid = NULL;
1001         else if (hwaddr_aton(cmd, bssid))
1002                 return -1;
1003
1004         return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
1005                                   0, 0);
1006 }
1007
1008
1009 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
1010         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1011 {
1012         int ndef;
1013         struct wpabuf *buf;
1014         int res;
1015         char *pos;
1016
1017         pos = os_strchr(cmd, ' ');
1018         if (pos)
1019                 *pos++ = '\0';
1020         if (os_strcmp(cmd, "WPS") == 0)
1021                 ndef = 0;
1022         else if (os_strcmp(cmd, "NDEF") == 0)
1023                 ndef = 1;
1024         else
1025                 return -1;
1026
1027         buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
1028         if (buf == NULL)
1029                 return -1;
1030
1031         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1032                                          wpabuf_len(buf));
1033         reply[res++] = '\n';
1034         reply[res] = '\0';
1035
1036         wpabuf_free(buf);
1037
1038         return res;
1039 }
1040
1041
1042 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
1043         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1044 {
1045         int ndef;
1046         struct wpabuf *buf;
1047         int res;
1048
1049         if (os_strcmp(cmd, "WPS") == 0)
1050                 ndef = 0;
1051         else if (os_strcmp(cmd, "NDEF") == 0)
1052                 ndef = 1;
1053         else
1054                 return -1;
1055
1056         buf = wpas_wps_nfc_token(wpa_s, ndef);
1057         if (buf == NULL)
1058                 return -1;
1059
1060         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1061                                          wpabuf_len(buf));
1062         reply[res++] = '\n';
1063         reply[res] = '\0';
1064
1065         wpabuf_free(buf);
1066
1067         return res;
1068 }
1069
1070
1071 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
1072         struct wpa_supplicant *wpa_s, char *pos)
1073 {
1074         size_t len;
1075         struct wpabuf *buf;
1076         int ret;
1077         char *freq;
1078         int forced_freq = 0;
1079
1080         freq = strstr(pos, " freq=");
1081         if (freq) {
1082                 *freq = '\0';
1083                 freq += 6;
1084                 forced_freq = atoi(freq);
1085         }
1086
1087         len = os_strlen(pos);
1088         if (len & 0x01)
1089                 return -1;
1090         len /= 2;
1091
1092         buf = wpabuf_alloc(len);
1093         if (buf == NULL)
1094                 return -1;
1095         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
1096                 wpabuf_free(buf);
1097                 return -1;
1098         }
1099
1100         ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
1101         wpabuf_free(buf);
1102
1103         return ret;
1104 }
1105
1106
1107 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
1108                                               char *reply, size_t max_len,
1109                                               int ndef)
1110 {
1111         struct wpabuf *buf;
1112         int res;
1113
1114         buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
1115         if (buf == NULL)
1116                 return -1;
1117
1118         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1119                                          wpabuf_len(buf));
1120         reply[res++] = '\n';
1121         reply[res] = '\0';
1122
1123         wpabuf_free(buf);
1124
1125         return res;
1126 }
1127
1128
1129 #ifdef CONFIG_P2P
1130 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
1131                                               char *reply, size_t max_len,
1132                                               int ndef)
1133 {
1134         struct wpabuf *buf;
1135         int res;
1136
1137         buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
1138         if (buf == NULL) {
1139                 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
1140                 return -1;
1141         }
1142
1143         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1144                                          wpabuf_len(buf));
1145         reply[res++] = '\n';
1146         reply[res] = '\0';
1147
1148         wpabuf_free(buf);
1149
1150         return res;
1151 }
1152 #endif /* CONFIG_P2P */
1153
1154
1155 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
1156                                           char *cmd, char *reply,
1157                                           size_t max_len)
1158 {
1159         char *pos;
1160         int ndef;
1161
1162         pos = os_strchr(cmd, ' ');
1163         if (pos == NULL)
1164                 return -1;
1165         *pos++ = '\0';
1166
1167         if (os_strcmp(cmd, "WPS") == 0)
1168                 ndef = 0;
1169         else if (os_strcmp(cmd, "NDEF") == 0)
1170                 ndef = 1;
1171         else
1172                 return -1;
1173
1174         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1175                 if (!ndef)
1176                         return -1;
1177                 return wpas_ctrl_nfc_get_handover_req_wps(
1178                         wpa_s, reply, max_len, ndef);
1179         }
1180
1181 #ifdef CONFIG_P2P
1182         if (os_strcmp(pos, "P2P-CR") == 0) {
1183                 return wpas_ctrl_nfc_get_handover_req_p2p(
1184                         wpa_s, reply, max_len, ndef);
1185         }
1186 #endif /* CONFIG_P2P */
1187
1188         return -1;
1189 }
1190
1191
1192 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1193                                               char *reply, size_t max_len,
1194                                               int ndef, int cr, char *uuid)
1195 {
1196         struct wpabuf *buf;
1197         int res;
1198
1199         buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1200         if (buf == NULL)
1201                 return -1;
1202
1203         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1204                                          wpabuf_len(buf));
1205         reply[res++] = '\n';
1206         reply[res] = '\0';
1207
1208         wpabuf_free(buf);
1209
1210         return res;
1211 }
1212
1213
1214 #ifdef CONFIG_P2P
1215 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1216                                               char *reply, size_t max_len,
1217                                               int ndef, int tag)
1218 {
1219         struct wpabuf *buf;
1220         int res;
1221
1222         buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1223         if (buf == NULL)
1224                 return -1;
1225
1226         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1227                                          wpabuf_len(buf));
1228         reply[res++] = '\n';
1229         reply[res] = '\0';
1230
1231         wpabuf_free(buf);
1232
1233         return res;
1234 }
1235 #endif /* CONFIG_P2P */
1236
1237
1238 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1239                                           char *cmd, char *reply,
1240                                           size_t max_len)
1241 {
1242         char *pos, *pos2;
1243         int ndef;
1244
1245         pos = os_strchr(cmd, ' ');
1246         if (pos == NULL)
1247                 return -1;
1248         *pos++ = '\0';
1249
1250         if (os_strcmp(cmd, "WPS") == 0)
1251                 ndef = 0;
1252         else if (os_strcmp(cmd, "NDEF") == 0)
1253                 ndef = 1;
1254         else
1255                 return -1;
1256
1257         pos2 = os_strchr(pos, ' ');
1258         if (pos2)
1259                 *pos2++ = '\0';
1260         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1261                 if (!ndef)
1262                         return -1;
1263                 return wpas_ctrl_nfc_get_handover_sel_wps(
1264                         wpa_s, reply, max_len, ndef,
1265                         os_strcmp(pos, "WPS-CR") == 0, pos2);
1266         }
1267
1268 #ifdef CONFIG_P2P
1269         if (os_strcmp(pos, "P2P-CR") == 0) {
1270                 return wpas_ctrl_nfc_get_handover_sel_p2p(
1271                         wpa_s, reply, max_len, ndef, 0);
1272         }
1273
1274         if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1275                 return wpas_ctrl_nfc_get_handover_sel_p2p(
1276                         wpa_s, reply, max_len, ndef, 1);
1277         }
1278 #endif /* CONFIG_P2P */
1279
1280         return -1;
1281 }
1282
1283
1284 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1285                                          char *cmd)
1286 {
1287         size_t len;
1288         struct wpabuf *req, *sel;
1289         int ret;
1290         char *pos, *role, *type, *pos2;
1291 #ifdef CONFIG_P2P
1292         char *freq;
1293         int forced_freq = 0;
1294
1295         freq = strstr(cmd, " freq=");
1296         if (freq) {
1297                 *freq = '\0';
1298                 freq += 6;
1299                 forced_freq = atoi(freq);
1300         }
1301 #endif /* CONFIG_P2P */
1302
1303         role = cmd;
1304         pos = os_strchr(role, ' ');
1305         if (pos == NULL) {
1306                 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1307                 return -1;
1308         }
1309         *pos++ = '\0';
1310
1311         type = pos;
1312         pos = os_strchr(type, ' ');
1313         if (pos == NULL) {
1314                 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1315                 return -1;
1316         }
1317         *pos++ = '\0';
1318
1319         pos2 = os_strchr(pos, ' ');
1320         if (pos2 == NULL) {
1321                 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1322                 return -1;
1323         }
1324         *pos2++ = '\0';
1325
1326         len = os_strlen(pos);
1327         if (len & 0x01) {
1328                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1329                 return -1;
1330         }
1331         len /= 2;
1332
1333         req = wpabuf_alloc(len);
1334         if (req == NULL) {
1335                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1336                 return -1;
1337         }
1338         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1339                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1340                 wpabuf_free(req);
1341                 return -1;
1342         }
1343
1344         len = os_strlen(pos2);
1345         if (len & 0x01) {
1346                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1347                 wpabuf_free(req);
1348                 return -1;
1349         }
1350         len /= 2;
1351
1352         sel = wpabuf_alloc(len);
1353         if (sel == NULL) {
1354                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1355                 wpabuf_free(req);
1356                 return -1;
1357         }
1358         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1359                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1360                 wpabuf_free(req);
1361                 wpabuf_free(sel);
1362                 return -1;
1363         }
1364
1365         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1366                    role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1367
1368         if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1369                 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1370 #ifdef CONFIG_AP
1371         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1372         {
1373                 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1374                 if (ret < 0)
1375                         ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1376 #endif /* CONFIG_AP */
1377 #ifdef CONFIG_P2P
1378         } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1379         {
1380                 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1381         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1382         {
1383                 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1384                                                    forced_freq);
1385 #endif /* CONFIG_P2P */
1386         } else {
1387                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1388                            "reported: role=%s type=%s", role, type);
1389                 ret = -1;
1390         }
1391         wpabuf_free(req);
1392         wpabuf_free(sel);
1393
1394         if (ret)
1395                 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1396
1397         return ret;
1398 }
1399
1400 #endif /* CONFIG_WPS_NFC */
1401
1402
1403 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1404                                              char *cmd)
1405 {
1406         u8 bssid[ETH_ALEN];
1407         char *pin;
1408         char *new_ssid;
1409         char *new_auth;
1410         char *new_encr;
1411         char *new_key;
1412         struct wps_new_ap_settings ap;
1413
1414         pin = os_strchr(cmd, ' ');
1415         if (pin == NULL)
1416                 return -1;
1417         *pin++ = '\0';
1418
1419         if (hwaddr_aton(cmd, bssid)) {
1420                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1421                            cmd);
1422                 return -1;
1423         }
1424
1425         new_ssid = os_strchr(pin, ' ');
1426         if (new_ssid == NULL)
1427                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1428         *new_ssid++ = '\0';
1429
1430         new_auth = os_strchr(new_ssid, ' ');
1431         if (new_auth == NULL)
1432                 return -1;
1433         *new_auth++ = '\0';
1434
1435         new_encr = os_strchr(new_auth, ' ');
1436         if (new_encr == NULL)
1437                 return -1;
1438         *new_encr++ = '\0';
1439
1440         new_key = os_strchr(new_encr, ' ');
1441         if (new_key == NULL)
1442                 return -1;
1443         *new_key++ = '\0';
1444
1445         os_memset(&ap, 0, sizeof(ap));
1446         ap.ssid_hex = new_ssid;
1447         ap.auth = new_auth;
1448         ap.encr = new_encr;
1449         ap.key_hex = new_key;
1450         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1451 }
1452
1453
1454 #ifdef CONFIG_AP
1455 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1456                                                 char *cmd, char *buf,
1457                                                 size_t buflen)
1458 {
1459         int timeout = 300;
1460         char *pos;
1461         const char *pin_txt;
1462
1463         if (!wpa_s->ap_iface)
1464                 return -1;
1465
1466         pos = os_strchr(cmd, ' ');
1467         if (pos)
1468                 *pos++ = '\0';
1469
1470         if (os_strcmp(cmd, "disable") == 0) {
1471                 wpas_wps_ap_pin_disable(wpa_s);
1472                 return os_snprintf(buf, buflen, "OK\n");
1473         }
1474
1475         if (os_strcmp(cmd, "random") == 0) {
1476                 if (pos)
1477                         timeout = atoi(pos);
1478                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1479                 if (pin_txt == NULL)
1480                         return -1;
1481                 return os_snprintf(buf, buflen, "%s", pin_txt);
1482         }
1483
1484         if (os_strcmp(cmd, "get") == 0) {
1485                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
1486                 if (pin_txt == NULL)
1487                         return -1;
1488                 return os_snprintf(buf, buflen, "%s", pin_txt);
1489         }
1490
1491         if (os_strcmp(cmd, "set") == 0) {
1492                 char *pin;
1493                 if (pos == NULL)
1494                         return -1;
1495                 pin = pos;
1496                 pos = os_strchr(pos, ' ');
1497                 if (pos) {
1498                         *pos++ = '\0';
1499                         timeout = atoi(pos);
1500                 }
1501                 if (os_strlen(pin) > buflen)
1502                         return -1;
1503                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1504                         return -1;
1505                 return os_snprintf(buf, buflen, "%s", pin);
1506         }
1507
1508         return -1;
1509 }
1510 #endif /* CONFIG_AP */
1511
1512
1513 #ifdef CONFIG_WPS_ER
1514 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1515                                                 char *cmd)
1516 {
1517         char *uuid = cmd, *pin, *pos;
1518         u8 addr_buf[ETH_ALEN], *addr = NULL;
1519         pin = os_strchr(uuid, ' ');
1520         if (pin == NULL)
1521                 return -1;
1522         *pin++ = '\0';
1523         pos = os_strchr(pin, ' ');
1524         if (pos) {
1525                 *pos++ = '\0';
1526                 if (hwaddr_aton(pos, addr_buf) == 0)
1527                         addr = addr_buf;
1528         }
1529         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1530 }
1531
1532
1533 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1534                                                   char *cmd)
1535 {
1536         char *uuid = cmd, *pin;
1537         pin = os_strchr(uuid, ' ');
1538         if (pin == NULL)
1539                 return -1;
1540         *pin++ = '\0';
1541         return wpas_wps_er_learn(wpa_s, uuid, pin);
1542 }
1543
1544
1545 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1546         struct wpa_supplicant *wpa_s, char *cmd)
1547 {
1548         char *uuid = cmd, *id;
1549         id = os_strchr(uuid, ' ');
1550         if (id == NULL)
1551                 return -1;
1552         *id++ = '\0';
1553         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1554 }
1555
1556
1557 static int wpa_supplicant_ctrl_iface_wps_er_config(
1558         struct wpa_supplicant *wpa_s, char *cmd)
1559 {
1560         char *pin;
1561         char *new_ssid;
1562         char *new_auth;
1563         char *new_encr;
1564         char *new_key;
1565         struct wps_new_ap_settings ap;
1566
1567         pin = os_strchr(cmd, ' ');
1568         if (pin == NULL)
1569                 return -1;
1570         *pin++ = '\0';
1571
1572         new_ssid = os_strchr(pin, ' ');
1573         if (new_ssid == NULL)
1574                 return -1;
1575         *new_ssid++ = '\0';
1576
1577         new_auth = os_strchr(new_ssid, ' ');
1578         if (new_auth == NULL)
1579                 return -1;
1580         *new_auth++ = '\0';
1581
1582         new_encr = os_strchr(new_auth, ' ');
1583         if (new_encr == NULL)
1584                 return -1;
1585         *new_encr++ = '\0';
1586
1587         new_key = os_strchr(new_encr, ' ');
1588         if (new_key == NULL)
1589                 return -1;
1590         *new_key++ = '\0';
1591
1592         os_memset(&ap, 0, sizeof(ap));
1593         ap.ssid_hex = new_ssid;
1594         ap.auth = new_auth;
1595         ap.encr = new_encr;
1596         ap.key_hex = new_key;
1597         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1598 }
1599
1600
1601 #ifdef CONFIG_WPS_NFC
1602 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1603         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1604 {
1605         int ndef;
1606         struct wpabuf *buf;
1607         int res;
1608         char *uuid;
1609
1610         uuid = os_strchr(cmd, ' ');
1611         if (uuid == NULL)
1612                 return -1;
1613         *uuid++ = '\0';
1614
1615         if (os_strcmp(cmd, "WPS") == 0)
1616                 ndef = 0;
1617         else if (os_strcmp(cmd, "NDEF") == 0)
1618                 ndef = 1;
1619         else
1620                 return -1;
1621
1622         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1623         if (buf == NULL)
1624                 return -1;
1625
1626         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1627                                          wpabuf_len(buf));
1628         reply[res++] = '\n';
1629         reply[res] = '\0';
1630
1631         wpabuf_free(buf);
1632
1633         return res;
1634 }
1635 #endif /* CONFIG_WPS_NFC */
1636 #endif /* CONFIG_WPS_ER */
1637
1638 #endif /* CONFIG_WPS */
1639
1640
1641 #ifdef CONFIG_IBSS_RSN
1642 static int wpa_supplicant_ctrl_iface_ibss_rsn(
1643         struct wpa_supplicant *wpa_s, char *addr)
1644 {
1645         u8 peer[ETH_ALEN];
1646
1647         if (hwaddr_aton(addr, peer)) {
1648                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1649                            "address '%s'", addr);
1650                 return -1;
1651         }
1652
1653         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1654                    MAC2STR(peer));
1655
1656         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1657 }
1658 #endif /* CONFIG_IBSS_RSN */
1659
1660
1661 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1662                                               char *rsp)
1663 {
1664 #ifdef IEEE8021X_EAPOL
1665         char *pos, *id_pos;
1666         int id;
1667         struct wpa_ssid *ssid;
1668
1669         pos = os_strchr(rsp, '-');
1670         if (pos == NULL)
1671                 return -1;
1672         *pos++ = '\0';
1673         id_pos = pos;
1674         pos = os_strchr(pos, ':');
1675         if (pos == NULL)
1676                 return -1;
1677         *pos++ = '\0';
1678         id = atoi(id_pos);
1679         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
1680         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1681                               (u8 *) pos, os_strlen(pos));
1682
1683         ssid = wpa_config_get_network(wpa_s->conf, id);
1684         if (ssid == NULL) {
1685                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1686                            "to update", id);
1687                 return -1;
1688         }
1689
1690         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
1691                                                          pos);
1692 #else /* IEEE8021X_EAPOL */
1693         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1694         return -1;
1695 #endif /* IEEE8021X_EAPOL */
1696 }
1697
1698
1699 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
1700                                             const char *params,
1701                                             char *buf, size_t buflen)
1702 {
1703         char *pos, *end, tmp[30];
1704         int res, verbose, wps, ret;
1705 #ifdef CONFIG_HS20
1706         const u8 *hs20;
1707 #endif /* CONFIG_HS20 */
1708         const u8 *sess_id;
1709         size_t sess_id_len;
1710
1711         if (os_strcmp(params, "-DRIVER") == 0)
1712                 return wpa_drv_status(wpa_s, buf, buflen);
1713         verbose = os_strcmp(params, "-VERBOSE") == 0;
1714         wps = os_strcmp(params, "-WPS") == 0;
1715         pos = buf;
1716         end = buf + buflen;
1717         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1718                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1719                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1720                                   MAC2STR(wpa_s->bssid));
1721                 if (os_snprintf_error(end - pos, ret))
1722                         return pos - buf;
1723                 pos += ret;
1724                 ret = os_snprintf(pos, end - pos, "freq=%u\n",
1725                                   wpa_s->assoc_freq);
1726                 if (os_snprintf_error(end - pos, ret))
1727                         return pos - buf;
1728                 pos += ret;
1729                 if (ssid) {
1730                         u8 *_ssid = ssid->ssid;
1731                         size_t ssid_len = ssid->ssid_len;
1732                         u8 ssid_buf[SSID_MAX_LEN];
1733                         if (ssid_len == 0) {
1734                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1735                                 if (_res < 0)
1736                                         ssid_len = 0;
1737                                 else
1738                                         ssid_len = _res;
1739                                 _ssid = ssid_buf;
1740                         }
1741                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1742                                           wpa_ssid_txt(_ssid, ssid_len),
1743                                           ssid->id);
1744                         if (os_snprintf_error(end - pos, ret))
1745                                 return pos - buf;
1746                         pos += ret;
1747
1748                         if (wps && ssid->passphrase &&
1749                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1750                             (ssid->mode == WPAS_MODE_AP ||
1751                              ssid->mode == WPAS_MODE_P2P_GO)) {
1752                                 ret = os_snprintf(pos, end - pos,
1753                                                   "passphrase=%s\n",
1754                                                   ssid->passphrase);
1755                                 if (os_snprintf_error(end - pos, ret))
1756                                         return pos - buf;
1757                                 pos += ret;
1758                         }
1759                         if (ssid->id_str) {
1760                                 ret = os_snprintf(pos, end - pos,
1761                                                   "id_str=%s\n",
1762                                                   ssid->id_str);
1763                                 if (os_snprintf_error(end - pos, ret))
1764                                         return pos - buf;
1765                                 pos += ret;
1766                         }
1767
1768                         switch (ssid->mode) {
1769                         case WPAS_MODE_INFRA:
1770                                 ret = os_snprintf(pos, end - pos,
1771                                                   "mode=station\n");
1772                                 break;
1773                         case WPAS_MODE_IBSS:
1774                                 ret = os_snprintf(pos, end - pos,
1775                                                   "mode=IBSS\n");
1776                                 break;
1777                         case WPAS_MODE_AP:
1778                                 ret = os_snprintf(pos, end - pos,
1779                                                   "mode=AP\n");
1780                                 break;
1781                         case WPAS_MODE_P2P_GO:
1782                                 ret = os_snprintf(pos, end - pos,
1783                                                   "mode=P2P GO\n");
1784                                 break;
1785                         case WPAS_MODE_P2P_GROUP_FORMATION:
1786                                 ret = os_snprintf(pos, end - pos,
1787                                                   "mode=P2P GO - group "
1788                                                   "formation\n");
1789                                 break;
1790                         default:
1791                                 ret = 0;
1792                                 break;
1793                         }
1794                         if (os_snprintf_error(end - pos, ret))
1795                                 return pos - buf;
1796                         pos += ret;
1797                 }
1798
1799 #ifdef CONFIG_AP
1800                 if (wpa_s->ap_iface) {
1801                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1802                                                             end - pos,
1803                                                             verbose);
1804                 } else
1805 #endif /* CONFIG_AP */
1806                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1807         }
1808 #ifdef CONFIG_SAE
1809         if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
1810 #ifdef CONFIG_AP
1811             !wpa_s->ap_iface &&
1812 #endif /* CONFIG_AP */
1813             wpa_s->sme.sae.state == SAE_ACCEPTED) {
1814                 ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
1815                                   wpa_s->sme.sae.group);
1816                 if (os_snprintf_error(end - pos, ret))
1817                         return pos - buf;
1818                 pos += ret;
1819         }
1820 #endif /* CONFIG_SAE */
1821         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1822                           wpa_supplicant_state_txt(wpa_s->wpa_state));
1823         if (os_snprintf_error(end - pos, ret))
1824                 return pos - buf;
1825         pos += ret;
1826
1827         if (wpa_s->l2 &&
1828             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1829                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1830                 if (os_snprintf_error(end - pos, ret))
1831                         return pos - buf;
1832                 pos += ret;
1833         }
1834
1835 #ifdef CONFIG_P2P
1836         if (wpa_s->global->p2p) {
1837                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1838                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1839                 if (os_snprintf_error(end - pos, ret))
1840                         return pos - buf;
1841                 pos += ret;
1842         }
1843 #endif /* CONFIG_P2P */
1844
1845         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1846                           MAC2STR(wpa_s->own_addr));
1847         if (os_snprintf_error(end - pos, ret))
1848                 return pos - buf;
1849         pos += ret;
1850
1851 #ifdef CONFIG_HS20
1852         if (wpa_s->current_bss &&
1853             (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
1854                                           HS20_IE_VENDOR_TYPE)) &&
1855             wpa_s->wpa_proto == WPA_PROTO_RSN &&
1856             wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1857                 int release = 1;
1858                 if (hs20[1] >= 5) {
1859                         u8 rel_num = (hs20[6] & 0xf0) >> 4;
1860                         release = rel_num + 1;
1861                 }
1862                 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
1863                 if (os_snprintf_error(end - pos, ret))
1864                         return pos - buf;
1865                 pos += ret;
1866         }
1867
1868         if (wpa_s->current_ssid) {
1869                 struct wpa_cred *cred;
1870                 char *type;
1871
1872                 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1873                         size_t i;
1874
1875                         if (wpa_s->current_ssid->parent_cred != cred)
1876                                 continue;
1877
1878                         if (cred->provisioning_sp) {
1879                                 ret = os_snprintf(pos, end - pos,
1880                                                   "provisioning_sp=%s\n",
1881                                                   cred->provisioning_sp);
1882                                 if (os_snprintf_error(end - pos, ret))
1883                                         return pos - buf;
1884                                 pos += ret;
1885                         }
1886
1887                         if (!cred->domain)
1888                                 goto no_domain;
1889
1890                         i = 0;
1891                         if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
1892                                 struct wpabuf *names =
1893                                         wpa_s->current_bss->anqp->domain_name;
1894                                 for (i = 0; names && i < cred->num_domain; i++)
1895                                 {
1896                                         if (domain_name_list_contains(
1897                                                     names, cred->domain[i], 1))
1898                                                 break;
1899                                 }
1900                                 if (i == cred->num_domain)
1901                                         i = 0; /* show first entry by default */
1902                         }
1903                         ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
1904                                           cred->domain[i]);
1905                         if (os_snprintf_error(end - pos, ret))
1906                                 return pos - buf;
1907                         pos += ret;
1908
1909                 no_domain:
1910                         if (wpa_s->current_bss == NULL ||
1911                             wpa_s->current_bss->anqp == NULL)
1912                                 res = -1;
1913                         else
1914                                 res = interworking_home_sp_cred(
1915                                         wpa_s, cred,
1916                                         wpa_s->current_bss->anqp->domain_name);
1917                         if (res > 0)
1918                                 type = "home";
1919                         else if (res == 0)
1920                                 type = "roaming";
1921                         else
1922                                 type = "unknown";
1923
1924                         ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
1925                         if (os_snprintf_error(end - pos, ret))
1926                                 return pos - buf;
1927                         pos += ret;
1928
1929                         break;
1930                 }
1931         }
1932 #endif /* CONFIG_HS20 */
1933
1934         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1935             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1936                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1937                                           verbose);
1938                 if (res >= 0)
1939                         pos += res;
1940         }
1941
1942         sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len);
1943         if (sess_id) {
1944                 char *start = pos;
1945
1946                 ret = os_snprintf(pos, end - pos, "eap_session_id=");
1947                 if (os_snprintf_error(end - pos, ret))
1948                         return start - buf;
1949                 pos += ret;
1950                 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len);
1951                 if (ret <= 0)
1952                         return start - buf;
1953                 pos += ret;
1954                 ret = os_snprintf(pos, end - pos, "\n");
1955                 if (os_snprintf_error(end - pos, ret))
1956                         return start - buf;
1957                 pos += ret;
1958         }
1959
1960         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1961         if (res >= 0)
1962                 pos += res;
1963
1964 #ifdef CONFIG_WPS
1965         {
1966                 char uuid_str[100];
1967                 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
1968                 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
1969                 if (os_snprintf_error(end - pos, ret))
1970                         return pos - buf;
1971                 pos += ret;
1972         }
1973 #endif /* CONFIG_WPS */
1974
1975 #ifdef ANDROID
1976         /*
1977          * Allow using the STATUS command with default behavior, say for debug,
1978          * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE
1979          * events with STATUS-NO_EVENTS.
1980          */
1981         if (os_strcmp(params, "-NO_EVENTS")) {
1982                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1983                              "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1984                              wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1985                              wpa_s->wpa_state,
1986                              MAC2STR(wpa_s->bssid),
1987                              wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1988                              wpa_ssid_txt(wpa_s->current_ssid->ssid,
1989                                           wpa_s->current_ssid->ssid_len) : "");
1990                 if (wpa_s->wpa_state == WPA_COMPLETED) {
1991                         struct wpa_ssid *ssid = wpa_s->current_ssid;
1992                         wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
1993                                      "- connection to " MACSTR
1994                                      " completed %s [id=%d id_str=%s]",
1995                                      MAC2STR(wpa_s->bssid), "(auth)",
1996                                      ssid ? ssid->id : -1,
1997                                      ssid && ssid->id_str ? ssid->id_str : "");
1998                 }
1999         }
2000 #endif /* ANDROID */
2001
2002         return pos - buf;
2003 }
2004
2005
2006 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
2007                                            char *cmd)
2008 {
2009         char *pos;
2010         int id;
2011         struct wpa_ssid *ssid;
2012         u8 bssid[ETH_ALEN];
2013
2014         /* cmd: "<network id> <BSSID>" */
2015         pos = os_strchr(cmd, ' ');
2016         if (pos == NULL)
2017                 return -1;
2018         *pos++ = '\0';
2019         id = atoi(cmd);
2020         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
2021         if (hwaddr_aton(pos, bssid)) {
2022                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
2023                 return -1;
2024         }
2025
2026         ssid = wpa_config_get_network(wpa_s->conf, id);
2027         if (ssid == NULL) {
2028                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2029                            "to update", id);
2030                 return -1;
2031         }
2032
2033         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
2034         ssid->bssid_set = !is_zero_ether_addr(bssid);
2035
2036         return 0;
2037 }
2038
2039
2040 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
2041                                                char *cmd, char *buf,
2042                                                size_t buflen)
2043 {
2044         u8 bssid[ETH_ALEN];
2045         struct wpa_blacklist *e;
2046         char *pos, *end;
2047         int ret;
2048
2049         /* cmd: "BLACKLIST [<BSSID>]" */
2050         if (*cmd == '\0') {
2051                 pos = buf;
2052                 end = buf + buflen;
2053                 e = wpa_s->blacklist;
2054                 while (e) {
2055                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
2056                                           MAC2STR(e->bssid));
2057                         if (os_snprintf_error(end - pos, ret))
2058                                 return pos - buf;
2059                         pos += ret;
2060                         e = e->next;
2061                 }
2062                 return pos - buf;
2063         }
2064
2065         cmd++;
2066         if (os_strncmp(cmd, "clear", 5) == 0) {
2067                 wpa_blacklist_clear(wpa_s);
2068                 os_memcpy(buf, "OK\n", 3);
2069                 return 3;
2070         }
2071
2072         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
2073         if (hwaddr_aton(cmd, bssid)) {
2074                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
2075                 return -1;
2076         }
2077
2078         /*
2079          * Add the BSSID twice, so its count will be 2, causing it to be
2080          * skipped when processing scan results.
2081          */
2082         ret = wpa_blacklist_add(wpa_s, bssid);
2083         if (ret < 0)
2084                 return -1;
2085         ret = wpa_blacklist_add(wpa_s, bssid);
2086         if (ret < 0)
2087                 return -1;
2088         os_memcpy(buf, "OK\n", 3);
2089         return 3;
2090 }
2091
2092
2093 static const char * debug_level_str(int level)
2094 {
2095         switch (level) {
2096         case MSG_EXCESSIVE:
2097                 return "EXCESSIVE";
2098         case MSG_MSGDUMP:
2099                 return "MSGDUMP";
2100         case MSG_DEBUG:
2101                 return "DEBUG";
2102         case MSG_INFO:
2103                 return "INFO";
2104         case MSG_WARNING:
2105                 return "WARNING";
2106         case MSG_ERROR:
2107                 return "ERROR";
2108         default:
2109                 return "?";
2110         }
2111 }
2112
2113
2114 static int str_to_debug_level(const char *s)
2115 {
2116         if (os_strcasecmp(s, "EXCESSIVE") == 0)
2117                 return MSG_EXCESSIVE;
2118         if (os_strcasecmp(s, "MSGDUMP") == 0)
2119                 return MSG_MSGDUMP;
2120         if (os_strcasecmp(s, "DEBUG") == 0)
2121                 return MSG_DEBUG;
2122         if (os_strcasecmp(s, "INFO") == 0)
2123                 return MSG_INFO;
2124         if (os_strcasecmp(s, "WARNING") == 0)
2125                 return MSG_WARNING;
2126         if (os_strcasecmp(s, "ERROR") == 0)
2127                 return MSG_ERROR;
2128         return -1;
2129 }
2130
2131
2132 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
2133                                                char *cmd, char *buf,
2134                                                size_t buflen)
2135 {
2136         char *pos, *end, *stamp;
2137         int ret;
2138
2139         /* cmd: "LOG_LEVEL [<level>]" */
2140         if (*cmd == '\0') {
2141                 pos = buf;
2142                 end = buf + buflen;
2143                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
2144                                   "Timestamp: %d\n",
2145                                   debug_level_str(wpa_debug_level),
2146                                   wpa_debug_timestamp);
2147                 if (os_snprintf_error(end - pos, ret))
2148                         ret = 0;
2149
2150                 return ret;
2151         }
2152
2153         while (*cmd == ' ')
2154                 cmd++;
2155
2156         stamp = os_strchr(cmd, ' ');
2157         if (stamp) {
2158                 *stamp++ = '\0';
2159                 while (*stamp == ' ') {
2160                         stamp++;
2161                 }
2162         }
2163
2164         if (cmd && os_strlen(cmd)) {
2165                 int level = str_to_debug_level(cmd);
2166                 if (level < 0)
2167                         return -1;
2168                 wpa_debug_level = level;
2169         }
2170
2171         if (stamp && os_strlen(stamp))
2172                 wpa_debug_timestamp = atoi(stamp);
2173
2174         os_memcpy(buf, "OK\n", 3);
2175         return 3;
2176 }
2177
2178
2179 static int wpa_supplicant_ctrl_iface_list_networks(
2180         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2181 {
2182         char *pos, *end, *prev;
2183         struct wpa_ssid *ssid;
2184         int ret;
2185
2186         pos = buf;
2187         end = buf + buflen;
2188         ret = os_snprintf(pos, end - pos,
2189                           "network id / ssid / bssid / flags\n");
2190         if (os_snprintf_error(end - pos, ret))
2191                 return pos - buf;
2192         pos += ret;
2193
2194         ssid = wpa_s->conf->ssid;
2195
2196         /* skip over ssids until we find next one */
2197         if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) {
2198                 int last_id = atoi(cmd + 8);
2199                 if (last_id != -1) {
2200                         while (ssid != NULL && ssid->id <= last_id) {
2201                                 ssid = ssid->next;
2202                         }
2203                 }
2204         }
2205
2206         while (ssid) {
2207                 prev = pos;
2208                 ret = os_snprintf(pos, end - pos, "%d\t%s",
2209                                   ssid->id,
2210                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2211                 if (os_snprintf_error(end - pos, ret))
2212                         return prev - buf;
2213                 pos += ret;
2214                 if (ssid->bssid_set) {
2215                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2216                                           MAC2STR(ssid->bssid));
2217                 } else {
2218                         ret = os_snprintf(pos, end - pos, "\tany");
2219                 }
2220                 if (os_snprintf_error(end - pos, ret))
2221                         return prev - buf;
2222                 pos += ret;
2223                 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2224                                   ssid == wpa_s->current_ssid ?
2225                                   "[CURRENT]" : "",
2226                                   ssid->disabled ? "[DISABLED]" : "",
2227                                   ssid->disabled_until.sec ?
2228                                   "[TEMP-DISABLED]" : "",
2229                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2230                                   "");
2231                 if (os_snprintf_error(end - pos, ret))
2232                         return prev - buf;
2233                 pos += ret;
2234                 ret = os_snprintf(pos, end - pos, "\n");
2235                 if (os_snprintf_error(end - pos, ret))
2236                         return prev - buf;
2237                 pos += ret;
2238
2239                 ssid = ssid->next;
2240         }
2241
2242         return pos - buf;
2243 }
2244
2245
2246 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2247 {
2248         int ret;
2249         ret = os_snprintf(pos, end - pos, "-");
2250         if (os_snprintf_error(end - pos, ret))
2251                 return pos;
2252         pos += ret;
2253         ret = wpa_write_ciphers(pos, end, cipher, "+");
2254         if (ret < 0)
2255                 return pos;
2256         pos += ret;
2257         return pos;
2258 }
2259
2260
2261 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2262                                     const u8 *ie, size_t ie_len)
2263 {
2264         struct wpa_ie_data data;
2265         char *start;
2266         int ret;
2267
2268         ret = os_snprintf(pos, end - pos, "[%s-", proto);
2269         if (os_snprintf_error(end - pos, ret))
2270                 return pos;
2271         pos += ret;
2272
2273         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2274                 ret = os_snprintf(pos, end - pos, "?]");
2275                 if (os_snprintf_error(end - pos, ret))
2276                         return pos;
2277                 pos += ret;
2278                 return pos;
2279         }
2280
2281         start = pos;
2282         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2283                 ret = os_snprintf(pos, end - pos, "%sEAP",
2284                                   pos == start ? "" : "+");
2285                 if (os_snprintf_error(end - pos, ret))
2286                         return pos;
2287                 pos += ret;
2288         }
2289         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2290                 ret = os_snprintf(pos, end - pos, "%sPSK",
2291                                   pos == start ? "" : "+");
2292                 if (os_snprintf_error(end - pos, ret))
2293                         return pos;
2294                 pos += ret;
2295         }
2296         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2297                 ret = os_snprintf(pos, end - pos, "%sNone",
2298                                   pos == start ? "" : "+");
2299                 if (os_snprintf_error(end - pos, ret))
2300                         return pos;
2301                 pos += ret;
2302         }
2303         if (data.key_mgmt & WPA_KEY_MGMT_SAE) {
2304                 ret = os_snprintf(pos, end - pos, "%sSAE",
2305                                   pos == start ? "" : "+");
2306                 if (os_snprintf_error(end - pos, ret))
2307                         return pos;
2308                 pos += ret;
2309         }
2310 #ifdef CONFIG_IEEE80211R
2311         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2312                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2313                                   pos == start ? "" : "+");
2314                 if (os_snprintf_error(end - pos, ret))
2315                         return pos;
2316                 pos += ret;
2317         }
2318         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2319                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2320                                   pos == start ? "" : "+");
2321                 if (os_snprintf_error(end - pos, ret))
2322                         return pos;
2323                 pos += ret;
2324         }
2325         if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) {
2326                 ret = os_snprintf(pos, end - pos, "%sFT/SAE",
2327                                   pos == start ? "" : "+");
2328                 if (os_snprintf_error(end - pos, ret))
2329                         return pos;
2330                 pos += ret;
2331         }
2332 #endif /* CONFIG_IEEE80211R */
2333 #ifdef CONFIG_IEEE80211W
2334         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2335                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2336                                   pos == start ? "" : "+");
2337                 if (os_snprintf_error(end - pos, ret))
2338                         return pos;
2339                 pos += ret;
2340         }
2341         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2342                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2343                                   pos == start ? "" : "+");
2344                 if (os_snprintf_error(end - pos, ret))
2345                         return pos;
2346                 pos += ret;
2347         }
2348 #endif /* CONFIG_IEEE80211W */
2349
2350 #ifdef CONFIG_SUITEB
2351         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
2352                 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
2353                                   pos == start ? "" : "+");
2354                 if (os_snprintf_error(end - pos, ret))
2355                         return pos;
2356                 pos += ret;
2357         }
2358 #endif /* CONFIG_SUITEB */
2359
2360 #ifdef CONFIG_SUITEB192
2361         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
2362                 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
2363                                   pos == start ? "" : "+");
2364                 if (os_snprintf_error(end - pos, ret))
2365                         return pos;
2366                 pos += ret;
2367         }
2368 #endif /* CONFIG_SUITEB192 */
2369
2370         if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
2371                 ret = os_snprintf(pos, end - pos, "%sOSEN",
2372                                   pos == start ? "" : "+");
2373                 if (os_snprintf_error(end - pos, ret))
2374                         return pos;
2375                 pos += ret;
2376         }
2377
2378         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2379
2380         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2381                 ret = os_snprintf(pos, end - pos, "-preauth");
2382                 if (os_snprintf_error(end - pos, ret))
2383                         return pos;
2384                 pos += ret;
2385         }
2386
2387         ret = os_snprintf(pos, end - pos, "]");
2388         if (os_snprintf_error(end - pos, ret))
2389                 return pos;
2390         pos += ret;
2391
2392         return pos;
2393 }
2394
2395
2396 #ifdef CONFIG_WPS
2397 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2398                                             char *pos, char *end,
2399                                             struct wpabuf *wps_ie)
2400 {
2401         int ret;
2402         const char *txt;
2403
2404         if (wps_ie == NULL)
2405                 return pos;
2406         if (wps_is_selected_pbc_registrar(wps_ie))
2407                 txt = "[WPS-PBC]";
2408         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2409                 txt = "[WPS-AUTH]";
2410         else if (wps_is_selected_pin_registrar(wps_ie))
2411                 txt = "[WPS-PIN]";
2412         else
2413                 txt = "[WPS]";
2414
2415         ret = os_snprintf(pos, end - pos, "%s", txt);
2416         if (!os_snprintf_error(end - pos, ret))
2417                 pos += ret;
2418         wpabuf_free(wps_ie);
2419         return pos;
2420 }
2421 #endif /* CONFIG_WPS */
2422
2423
2424 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2425                                         char *pos, char *end,
2426                                         const struct wpa_bss *bss)
2427 {
2428 #ifdef CONFIG_WPS
2429         struct wpabuf *wps_ie;
2430         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2431         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2432 #else /* CONFIG_WPS */
2433         return pos;
2434 #endif /* CONFIG_WPS */
2435 }
2436
2437
2438 /* Format one result on one text line into a buffer. */
2439 static int wpa_supplicant_ctrl_iface_scan_result(
2440         struct wpa_supplicant *wpa_s,
2441         const struct wpa_bss *bss, char *buf, size_t buflen)
2442 {
2443         char *pos, *end;
2444         int ret;
2445         const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
2446
2447         mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
2448         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2449         if (!p2p)
2450                 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2451         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2452             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2453             0)
2454                 return 0; /* Do not show P2P listen discovery results here */
2455
2456         pos = buf;
2457         end = buf + buflen;
2458
2459         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2460                           MAC2STR(bss->bssid), bss->freq, bss->level);
2461         if (os_snprintf_error(end - pos, ret))
2462                 return -1;
2463         pos += ret;
2464         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2465         if (ie)
2466                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2467         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2468         if (ie2) {
2469                 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
2470                                             ie2, 2 + ie2[1]);
2471         }
2472         osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
2473         if (osen_ie)
2474                 pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
2475                                             osen_ie, 2 + osen_ie[1]);
2476         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2477         if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
2478                 ret = os_snprintf(pos, end - pos, "[WEP]");
2479                 if (os_snprintf_error(end - pos, ret))
2480                         return -1;
2481                 pos += ret;
2482         }
2483         if (mesh) {
2484                 ret = os_snprintf(pos, end - pos, "[MESH]");
2485                 if (os_snprintf_error(end - pos, ret))
2486                         return -1;
2487                 pos += ret;
2488         }
2489         if (bss_is_dmg(bss)) {
2490                 const char *s;
2491                 ret = os_snprintf(pos, end - pos, "[DMG]");
2492                 if (os_snprintf_error(end - pos, ret))
2493                         return -1;
2494                 pos += ret;
2495                 switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
2496                 case IEEE80211_CAP_DMG_IBSS:
2497                         s = "[IBSS]";
2498                         break;
2499                 case IEEE80211_CAP_DMG_AP:
2500                         s = "[ESS]";
2501                         break;
2502                 case IEEE80211_CAP_DMG_PBSS:
2503                         s = "[PBSS]";
2504                         break;
2505                 default:
2506                         s = "";
2507                         break;
2508                 }
2509                 ret = os_snprintf(pos, end - pos, "%s", s);
2510                 if (os_snprintf_error(end - pos, ret))
2511                         return -1;
2512                 pos += ret;
2513         } else {
2514                 if (bss->caps & IEEE80211_CAP_IBSS) {
2515                         ret = os_snprintf(pos, end - pos, "[IBSS]");
2516                         if (os_snprintf_error(end - pos, ret))
2517                                 return -1;
2518                         pos += ret;
2519                 }
2520                 if (bss->caps & IEEE80211_CAP_ESS) {
2521                         ret = os_snprintf(pos, end - pos, "[ESS]");
2522                         if (os_snprintf_error(end - pos, ret))
2523                                 return -1;
2524                         pos += ret;
2525                 }
2526         }
2527         if (p2p) {
2528                 ret = os_snprintf(pos, end - pos, "[P2P]");
2529                 if (os_snprintf_error(end - pos, ret))
2530                         return -1;
2531                 pos += ret;
2532         }
2533 #ifdef CONFIG_HS20
2534         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2535                 ret = os_snprintf(pos, end - pos, "[HS20]");
2536                 if (os_snprintf_error(end - pos, ret))
2537                         return -1;
2538                 pos += ret;
2539         }
2540 #endif /* CONFIG_HS20 */
2541
2542         ret = os_snprintf(pos, end - pos, "\t%s",
2543                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
2544         if (os_snprintf_error(end - pos, ret))
2545                 return -1;
2546         pos += ret;
2547
2548         ret = os_snprintf(pos, end - pos, "\n");
2549         if (os_snprintf_error(end - pos, ret))
2550                 return -1;
2551         pos += ret;
2552
2553         return pos - buf;
2554 }
2555
2556
2557 static int wpa_supplicant_ctrl_iface_scan_results(
2558         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2559 {
2560         char *pos, *end;
2561         struct wpa_bss *bss;
2562         int ret;
2563
2564         pos = buf;
2565         end = buf + buflen;
2566         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2567                           "flags / ssid\n");
2568         if (os_snprintf_error(end - pos, ret))
2569                 return pos - buf;
2570         pos += ret;
2571
2572         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2573                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2574                                                             end - pos);
2575                 if (ret < 0 || ret >= end - pos)
2576                         return pos - buf;
2577                 pos += ret;
2578         }
2579
2580         return pos - buf;
2581 }
2582
2583
2584 #ifdef CONFIG_MESH
2585
2586 static int wpa_supplicant_ctrl_iface_mesh_interface_add(
2587         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
2588 {
2589         char *pos, ifname[IFNAMSIZ + 1];
2590
2591         ifname[0] = '\0';
2592
2593         pos = os_strstr(cmd, "ifname=");
2594         if (pos) {
2595                 pos += 7;
2596                 os_strlcpy(ifname, pos, sizeof(ifname));
2597         }
2598
2599         if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0)
2600                 return -1;
2601
2602         os_strlcpy(reply, ifname, max_len);
2603         return os_strlen(ifname);
2604 }
2605
2606
2607 static int wpa_supplicant_ctrl_iface_mesh_group_add(
2608         struct wpa_supplicant *wpa_s, char *cmd)
2609 {
2610         int id;
2611         struct wpa_ssid *ssid;
2612
2613         id = atoi(cmd);
2614         wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
2615
2616         ssid = wpa_config_get_network(wpa_s->conf, id);
2617         if (ssid == NULL) {
2618                 wpa_printf(MSG_DEBUG,
2619                            "CTRL_IFACE: Could not find network id=%d", id);
2620                 return -1;
2621         }
2622         if (ssid->mode != WPAS_MODE_MESH) {
2623                 wpa_printf(MSG_DEBUG,
2624                            "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
2625                 return -1;
2626         }
2627         if (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
2628             ssid->key_mgmt != WPA_KEY_MGMT_SAE) {
2629                 wpa_printf(MSG_ERROR,
2630                            "CTRL_IFACE: key_mgmt for mesh network should be open or SAE");
2631                 return -1;
2632         }
2633
2634         /*
2635          * TODO: If necessary write our own group_add function,
2636          * for now we can reuse select_network
2637          */
2638         wpa_supplicant_select_network(wpa_s, ssid);
2639
2640         return 0;
2641 }
2642
2643
2644 static int wpa_supplicant_ctrl_iface_mesh_group_remove(
2645         struct wpa_supplicant *wpa_s, char *cmd)
2646 {
2647         struct wpa_supplicant *orig;
2648         struct wpa_global *global;
2649         int found = 0;
2650
2651         wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
2652
2653         global = wpa_s->global;
2654         orig = wpa_s;
2655
2656         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
2657                 if (os_strcmp(wpa_s->ifname, cmd) == 0) {
2658                         found = 1;
2659                         break;
2660                 }
2661         }
2662         if (!found) {
2663                 wpa_printf(MSG_ERROR,
2664                            "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found",
2665                            cmd);
2666                 return -1;
2667         }
2668         if (wpa_s->mesh_if_created && wpa_s == orig) {
2669                 wpa_printf(MSG_ERROR,
2670                            "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself");
2671                 return -1;
2672         }
2673
2674         wpa_s->reassociate = 0;
2675         wpa_s->disconnected = 1;
2676         wpa_supplicant_cancel_sched_scan(wpa_s);
2677         wpa_supplicant_cancel_scan(wpa_s);
2678
2679         /*
2680          * TODO: If necessary write our own group_remove function,
2681          * for now we can reuse deauthenticate
2682          */
2683         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2684
2685         if (wpa_s->mesh_if_created)
2686                 wpa_supplicant_remove_iface(global, wpa_s, 0);
2687
2688         return 0;
2689 }
2690
2691 #endif /* CONFIG_MESH */
2692
2693
2694 static int wpa_supplicant_ctrl_iface_select_network(
2695         struct wpa_supplicant *wpa_s, char *cmd)
2696 {
2697         int id;
2698         struct wpa_ssid *ssid;
2699         char *pos;
2700
2701         /* cmd: "<network id>" or "any" */
2702         if (os_strncmp(cmd, "any", 3) == 0) {
2703                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2704                 ssid = NULL;
2705         } else {
2706                 id = atoi(cmd);
2707                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2708
2709                 ssid = wpa_config_get_network(wpa_s->conf, id);
2710                 if (ssid == NULL) {
2711                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2712                                    "network id=%d", id);
2713                         return -1;
2714                 }
2715                 if (ssid->disabled == 2) {
2716                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2717                                    "SELECT_NETWORK with persistent P2P group");
2718                         return -1;
2719                 }
2720         }
2721
2722         pos = os_strstr(cmd, " freq=");
2723         if (pos) {
2724                 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
2725                 if (freqs) {
2726                         wpa_s->scan_req = MANUAL_SCAN_REQ;
2727                         os_free(wpa_s->manual_scan_freqs);
2728                         wpa_s->manual_scan_freqs = freqs;
2729                 }
2730         }
2731
2732         wpa_supplicant_select_network(wpa_s, ssid);
2733
2734         return 0;
2735 }
2736
2737
2738 static int wpa_supplicant_ctrl_iface_enable_network(
2739         struct wpa_supplicant *wpa_s, char *cmd)
2740 {
2741         int id;
2742         struct wpa_ssid *ssid;
2743
2744         /* cmd: "<network id>" or "all" */
2745         if (os_strcmp(cmd, "all") == 0) {
2746                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2747                 ssid = NULL;
2748         } else {
2749                 id = atoi(cmd);
2750                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2751
2752                 ssid = wpa_config_get_network(wpa_s->conf, id);
2753                 if (ssid == NULL) {
2754                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2755                                    "network id=%d", id);
2756                         return -1;
2757                 }
2758                 if (ssid->disabled == 2) {
2759                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2760                                    "ENABLE_NETWORK with persistent P2P group");
2761                         return -1;
2762                 }
2763
2764                 if (os_strstr(cmd, " no-connect")) {
2765                         ssid->disabled = 0;
2766                         return 0;
2767                 }
2768         }
2769         wpa_supplicant_enable_network(wpa_s, ssid);
2770
2771         return 0;
2772 }
2773
2774
2775 static int wpa_supplicant_ctrl_iface_disable_network(
2776         struct wpa_supplicant *wpa_s, char *cmd)
2777 {
2778         int id;
2779         struct wpa_ssid *ssid;
2780
2781         /* cmd: "<network id>" or "all" */
2782         if (os_strcmp(cmd, "all") == 0) {
2783                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2784                 ssid = NULL;
2785         } else {
2786                 id = atoi(cmd);
2787                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2788
2789                 ssid = wpa_config_get_network(wpa_s->conf, id);
2790                 if (ssid == NULL) {
2791                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2792                                    "network id=%d", id);
2793                         return -1;
2794                 }
2795                 if (ssid->disabled == 2) {
2796                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2797                                    "DISABLE_NETWORK with persistent P2P "
2798                                    "group");
2799                         return -1;
2800                 }
2801         }
2802         wpa_supplicant_disable_network(wpa_s, ssid);
2803
2804         return 0;
2805 }
2806
2807
2808 static int wpa_supplicant_ctrl_iface_add_network(
2809         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2810 {
2811         struct wpa_ssid *ssid;
2812         int ret;
2813
2814         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2815
2816         ssid = wpa_config_add_network(wpa_s->conf);
2817         if (ssid == NULL)
2818                 return -1;
2819
2820         wpas_notify_network_added(wpa_s, ssid);
2821
2822         ssid->disabled = 1;
2823         wpa_config_set_network_defaults(ssid);
2824
2825         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2826         if (os_snprintf_error(buflen, ret))
2827                 return -1;
2828         return ret;
2829 }
2830
2831
2832 static int wpa_supplicant_ctrl_iface_remove_network(
2833         struct wpa_supplicant *wpa_s, char *cmd)
2834 {
2835         int id;
2836         struct wpa_ssid *ssid;
2837         int was_disabled;
2838
2839         /* cmd: "<network id>" or "all" */
2840         if (os_strcmp(cmd, "all") == 0) {
2841                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2842                 if (wpa_s->sched_scanning)
2843                         wpa_supplicant_cancel_sched_scan(wpa_s);
2844
2845                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2846                 if (wpa_s->current_ssid) {
2847 #ifdef CONFIG_SME
2848                         wpa_s->sme.prev_bssid_set = 0;
2849 #endif /* CONFIG_SME */
2850                         wpa_sm_set_config(wpa_s->wpa, NULL);
2851                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2852                         wpa_s->own_disconnect_req = 1;
2853                         wpa_supplicant_deauthenticate(
2854                                 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2855                 }
2856                 ssid = wpa_s->conf->ssid;
2857                 while (ssid) {
2858                         struct wpa_ssid *remove_ssid = ssid;
2859                         id = ssid->id;
2860                         ssid = ssid->next;
2861                         if (wpa_s->last_ssid == remove_ssid)
2862                                 wpa_s->last_ssid = NULL;
2863                         wpas_notify_network_removed(wpa_s, remove_ssid);
2864                         wpa_config_remove_network(wpa_s->conf, id);
2865                 }
2866                 return 0;
2867         }
2868
2869         id = atoi(cmd);
2870         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2871
2872         ssid = wpa_config_get_network(wpa_s->conf, id);
2873         if (ssid)
2874                 wpas_notify_network_removed(wpa_s, ssid);
2875         if (ssid == NULL) {
2876                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2877                            "id=%d", id);
2878                 return -1;
2879         }
2880
2881         if (wpa_s->last_ssid == ssid)
2882                 wpa_s->last_ssid = NULL;
2883
2884         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2885 #ifdef CONFIG_SME
2886                 wpa_s->sme.prev_bssid_set = 0;
2887 #endif /* CONFIG_SME */
2888                 /*
2889                  * Invalidate the EAP session cache if the current or
2890                  * previously used network is removed.
2891                  */
2892                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2893         }
2894
2895         if (ssid == wpa_s->current_ssid) {
2896                 wpa_sm_set_config(wpa_s->wpa, NULL);
2897                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2898
2899                 wpa_s->own_disconnect_req = 1;
2900                 wpa_supplicant_deauthenticate(wpa_s,
2901                                               WLAN_REASON_DEAUTH_LEAVING);
2902         }
2903
2904         was_disabled = ssid->disabled;
2905
2906         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2907                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2908                            "network id=%d", id);
2909                 return -1;
2910         }
2911
2912         if (!was_disabled && wpa_s->sched_scanning) {
2913                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2914                            "network from filters");
2915                 wpa_supplicant_cancel_sched_scan(wpa_s);
2916                 wpa_supplicant_req_scan(wpa_s, 0, 0);
2917         }
2918
2919         return 0;
2920 }
2921
2922
2923 static int wpa_supplicant_ctrl_iface_update_network(
2924         struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2925         char *name, char *value)
2926 {
2927         if (wpa_config_set(ssid, name, value, 0) < 0) {
2928                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2929                            "variable '%s'", name);
2930                 return -1;
2931         }
2932
2933         if (os_strcmp(name, "bssid") != 0 &&
2934             os_strcmp(name, "priority") != 0)
2935                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2936
2937         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2938                 /*
2939                  * Invalidate the EAP session cache if anything in the current
2940                  * or previously used configuration changes.
2941                  */
2942                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2943         }
2944
2945         if ((os_strcmp(name, "psk") == 0 &&
2946              value[0] == '"' && ssid->ssid_len) ||
2947             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2948                 wpa_config_update_psk(ssid);
2949         else if (os_strcmp(name, "priority") == 0)
2950                 wpa_config_update_prio_list(wpa_s->conf);
2951
2952         return 0;
2953 }
2954
2955
2956 static int wpa_supplicant_ctrl_iface_set_network(
2957         struct wpa_supplicant *wpa_s, char *cmd)
2958 {
2959         int id, ret, prev_bssid_set, prev_disabled;
2960         struct wpa_ssid *ssid;
2961         char *name, *value;
2962         u8 prev_bssid[ETH_ALEN];
2963
2964         /* cmd: "<network id> <variable name> <value>" */
2965         name = os_strchr(cmd, ' ');
2966         if (name == NULL)
2967                 return -1;
2968         *name++ = '\0';
2969
2970         value = os_strchr(name, ' ');
2971         if (value == NULL)
2972                 return -1;
2973         *value++ = '\0';
2974
2975         id = atoi(cmd);
2976         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2977                    id, name);
2978         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2979                               (u8 *) value, os_strlen(value));
2980
2981         ssid = wpa_config_get_network(wpa_s->conf, id);
2982         if (ssid == NULL) {
2983                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2984                            "id=%d", id);
2985                 return -1;
2986         }
2987
2988         prev_bssid_set = ssid->bssid_set;
2989         prev_disabled = ssid->disabled;
2990         os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN);
2991         ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name,
2992                                                        value);
2993         if (ret == 0 &&
2994             (ssid->bssid_set != prev_bssid_set ||
2995              os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0))
2996                 wpas_notify_network_bssid_set_changed(wpa_s, ssid);
2997
2998         if (prev_disabled != ssid->disabled &&
2999             (prev_disabled == 2 || ssid->disabled == 2))
3000                 wpas_notify_network_type_changed(wpa_s, ssid);
3001
3002         return ret;
3003 }
3004
3005
3006 static int wpa_supplicant_ctrl_iface_get_network(
3007         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
3008 {
3009         int id;
3010         size_t res;
3011         struct wpa_ssid *ssid;
3012         char *name, *value;
3013
3014         /* cmd: "<network id> <variable name>" */
3015         name = os_strchr(cmd, ' ');
3016         if (name == NULL || buflen == 0)
3017                 return -1;
3018         *name++ = '\0';
3019
3020         id = atoi(cmd);
3021         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
3022                    id, name);
3023
3024         ssid = wpa_config_get_network(wpa_s->conf, id);
3025         if (ssid == NULL) {
3026                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
3027                            "id=%d", id);
3028                 return -1;
3029         }
3030
3031         value = wpa_config_get_no_key(ssid, name);
3032         if (value == NULL) {
3033                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3034                            "variable '%s'", name);
3035                 return -1;
3036         }
3037
3038         res = os_strlcpy(buf, value, buflen);
3039         if (res >= buflen) {
3040                 os_free(value);
3041                 return -1;
3042         }
3043
3044         os_free(value);
3045
3046         return res;
3047 }
3048
3049
3050 static int wpa_supplicant_ctrl_iface_dup_network(
3051         struct wpa_supplicant *wpa_s, char *cmd)
3052 {
3053         struct wpa_ssid *ssid_s, *ssid_d;
3054         char *name, *id, *value;
3055         int id_s, id_d, ret;
3056
3057         /* cmd: "<src network id> <dst network id> <variable name>" */
3058         id = os_strchr(cmd, ' ');
3059         if (id == NULL)
3060                 return -1;
3061         *id++ = '\0';
3062
3063         name = os_strchr(id, ' ');
3064         if (name == NULL)
3065                 return -1;
3066         *name++ = '\0';
3067
3068         id_s = atoi(cmd);
3069         id_d = atoi(id);
3070         wpa_printf(MSG_DEBUG, "CTRL_IFACE: DUP_NETWORK id=%d -> %d name='%s'",
3071                    id_s, id_d, name);
3072
3073         ssid_s = wpa_config_get_network(wpa_s->conf, id_s);
3074         if (ssid_s == NULL) {
3075                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3076                            "network id=%d", id_s);
3077                 return -1;
3078         }
3079
3080         ssid_d = wpa_config_get_network(wpa_s->conf, id_d);
3081         if (ssid_d == NULL) {
3082                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3083                            "network id=%d", id_d);
3084                 return -1;
3085         }
3086
3087         value = wpa_config_get(ssid_s, name);
3088         if (value == NULL) {
3089                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
3090                            "variable '%s'", name);
3091                 return -1;
3092         }
3093
3094         ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid_d, name,
3095                                                        value);
3096
3097         os_free(value);
3098
3099         return ret;
3100 }
3101
3102
3103 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
3104                                                 char *buf, size_t buflen)
3105 {
3106         char *pos, *end;
3107         struct wpa_cred *cred;
3108         int ret;
3109
3110         pos = buf;
3111         end = buf + buflen;
3112         ret = os_snprintf(pos, end - pos,
3113                           "cred id / realm / username / domain / imsi\n");
3114         if (os_snprintf_error(end - pos, ret))
3115                 return pos - buf;
3116         pos += ret;
3117
3118         cred = wpa_s->conf->cred;
3119         while (cred) {
3120                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
3121                                   cred->id, cred->realm ? cred->realm : "",
3122                                   cred->username ? cred->username : "",
3123                                   cred->domain ? cred->domain[0] : "",
3124                                   cred->imsi ? cred->imsi : "");
3125                 if (os_snprintf_error(end - pos, ret))
3126                         return pos - buf;
3127                 pos += ret;
3128
3129                 cred = cred->next;
3130         }
3131
3132         return pos - buf;
3133 }
3134
3135
3136 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
3137                                               char *buf, size_t buflen)
3138 {
3139         struct wpa_cred *cred;
3140         int ret;
3141
3142         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
3143
3144         cred = wpa_config_add_cred(wpa_s->conf);
3145         if (cred == NULL)
3146                 return -1;
3147
3148         wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
3149
3150         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
3151         if (os_snprintf_error(buflen, ret))
3152                 return -1;
3153         return ret;
3154 }
3155
3156
3157 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
3158                                  struct wpa_cred *cred)
3159 {
3160         struct wpa_ssid *ssid;
3161         char str[20];
3162         int id;
3163
3164         if (cred == NULL) {
3165                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3166                 return -1;
3167         }
3168
3169         id = cred->id;
3170         if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
3171                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
3172                 return -1;
3173         }
3174
3175         wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
3176
3177         /* Remove any network entry created based on the removed credential */
3178         ssid = wpa_s->conf->ssid;
3179         while (ssid) {
3180                 if (ssid->parent_cred == cred) {
3181                         int res;
3182
3183                         wpa_printf(MSG_DEBUG, "Remove network id %d since it "
3184                                    "used the removed credential", ssid->id);
3185                         res = os_snprintf(str, sizeof(str), "%d", ssid->id);
3186                         if (os_snprintf_error(sizeof(str), res))
3187                                 str[sizeof(str) - 1] = '\0';
3188                         ssid = ssid->next;
3189                         wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
3190                 } else
3191                         ssid = ssid->next;
3192         }
3193
3194         return 0;
3195 }
3196
3197
3198 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
3199                                                  char *cmd)
3200 {
3201         int id;
3202         struct wpa_cred *cred, *prev;
3203
3204         /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
3205          * "provisioning_sp=<FQDN> */
3206         if (os_strcmp(cmd, "all") == 0) {
3207                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
3208                 cred = wpa_s->conf->cred;
3209                 while (cred) {
3210                         prev = cred;
3211                         cred = cred->next;
3212                         wpas_ctrl_remove_cred(wpa_s, prev);
3213                 }
3214                 return 0;
3215         }
3216
3217         if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
3218                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
3219                            cmd + 8);
3220                 cred = wpa_s->conf->cred;
3221                 while (cred) {
3222                         prev = cred;
3223                         cred = cred->next;
3224                         if (prev->domain) {
3225                                 size_t i;
3226                                 for (i = 0; i < prev->num_domain; i++) {
3227                                         if (os_strcmp(prev->domain[i], cmd + 8)
3228                                             != 0)
3229                                                 continue;
3230                                         wpas_ctrl_remove_cred(wpa_s, prev);
3231                                         break;
3232                                 }
3233                         }
3234                 }
3235                 return 0;
3236         }
3237
3238         if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
3239                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
3240                            cmd + 16);
3241                 cred = wpa_s->conf->cred;
3242                 while (cred) {
3243                         prev = cred;
3244                         cred = cred->next;
3245                         if (prev->provisioning_sp &&
3246                             os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
3247                                 wpas_ctrl_remove_cred(wpa_s, prev);
3248                 }
3249                 return 0;
3250         }
3251
3252         id = atoi(cmd);
3253         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
3254
3255         cred = wpa_config_get_cred(wpa_s->conf, id);
3256         return wpas_ctrl_remove_cred(wpa_s, cred);
3257 }
3258
3259
3260 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
3261                                               char *cmd)
3262 {
3263         int id;
3264         struct wpa_cred *cred;
3265         char *name, *value;
3266
3267         /* cmd: "<cred id> <variable name> <value>" */
3268         name = os_strchr(cmd, ' ');
3269         if (name == NULL)
3270                 return -1;
3271         *name++ = '\0';
3272
3273         value = os_strchr(name, ' ');
3274         if (value == NULL)
3275                 return -1;
3276         *value++ = '\0';
3277
3278         id = atoi(cmd);
3279         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
3280                    id, name);
3281         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
3282                               (u8 *) value, os_strlen(value));
3283
3284         cred = wpa_config_get_cred(wpa_s->conf, id);
3285         if (cred == NULL) {
3286                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3287                            id);
3288                 return -1;
3289         }
3290
3291         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
3292                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
3293                            "variable '%s'", name);
3294                 return -1;
3295         }
3296
3297         wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
3298
3299         return 0;
3300 }
3301
3302
3303 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
3304                                               char *cmd, char *buf,
3305                                               size_t buflen)
3306 {
3307         int id;
3308         size_t res;
3309         struct wpa_cred *cred;
3310         char *name, *value;
3311
3312         /* cmd: "<cred id> <variable name>" */
3313         name = os_strchr(cmd, ' ');
3314         if (name == NULL)
3315                 return -1;
3316         *name++ = '\0';
3317
3318         id = atoi(cmd);
3319         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
3320                    id, name);
3321
3322         cred = wpa_config_get_cred(wpa_s->conf, id);
3323         if (cred == NULL) {
3324                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
3325                            id);
3326                 return -1;
3327         }
3328
3329         value = wpa_config_get_cred_no_key(cred, name);
3330         if (value == NULL) {
3331                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
3332                            name);
3333                 return -1;
3334         }
3335
3336         res = os_strlcpy(buf, value, buflen);
3337         if (res >= buflen) {
3338                 os_free(value);
3339                 return -1;
3340         }
3341
3342         os_free(value);
3343
3344         return res;
3345 }
3346
3347
3348 #ifndef CONFIG_NO_CONFIG_WRITE
3349 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
3350 {
3351         int ret;
3352
3353         if (!wpa_s->conf->update_config) {
3354                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
3355                            "to update configuration (update_config=0)");
3356                 return -1;
3357         }
3358
3359         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
3360         if (ret) {
3361                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
3362                            "update configuration");
3363         } else {
3364                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
3365                            " updated");
3366         }
3367
3368         return ret;
3369 }
3370 #endif /* CONFIG_NO_CONFIG_WRITE */
3371
3372
3373 struct cipher_info {
3374         unsigned int capa;
3375         const char *name;
3376         int group_only;
3377 };
3378
3379 static const struct cipher_info ciphers[] = {
3380         { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
3381         { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
3382         { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
3383         { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
3384         { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
3385         { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
3386         { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
3387         { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
3388 };
3389
3390 static const struct cipher_info ciphers_group_mgmt[] = {
3391         { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 },
3392         { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 },
3393         { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 },
3394         { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 },
3395 };
3396
3397
3398 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
3399                                               struct wpa_driver_capa *capa,
3400                                               char *buf, size_t buflen)
3401 {
3402         int ret;
3403         char *pos, *end;
3404         size_t len;
3405         unsigned int i;
3406
3407         pos = buf;
3408         end = pos + buflen;
3409
3410         if (res < 0) {
3411                 if (strict)
3412                         return 0;
3413                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
3414                 if (len >= buflen)
3415                         return -1;
3416                 return len;
3417         }
3418
3419         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
3420                 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
3421                         ret = os_snprintf(pos, end - pos, "%s%s",
3422                                           pos == buf ? "" : " ",
3423                                           ciphers[i].name);
3424                         if (os_snprintf_error(end - pos, ret))
3425                                 return pos - buf;
3426                         pos += ret;
3427                 }
3428         }
3429
3430         return pos - buf;
3431 }
3432
3433
3434 static int ctrl_iface_get_capability_group(int res, char *strict,
3435                                            struct wpa_driver_capa *capa,
3436                                            char *buf, size_t buflen)
3437 {
3438         int ret;
3439         char *pos, *end;
3440         size_t len;
3441         unsigned int i;
3442
3443         pos = buf;
3444         end = pos + buflen;
3445
3446         if (res < 0) {
3447                 if (strict)
3448                         return 0;
3449                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
3450                 if (len >= buflen)
3451                         return -1;
3452                 return len;
3453         }
3454
3455         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
3456                 if (capa->enc & ciphers[i].capa) {
3457                         ret = os_snprintf(pos, end - pos, "%s%s",
3458                                           pos == buf ? "" : " ",
3459                                           ciphers[i].name);
3460                         if (os_snprintf_error(end - pos, ret))
3461                                 return pos - buf;
3462                         pos += ret;
3463                 }
3464         }
3465
3466         return pos - buf;
3467 }
3468
3469
3470 static int ctrl_iface_get_capability_group_mgmt(int res, char *strict,
3471                                                 struct wpa_driver_capa *capa,
3472                                                 char *buf, size_t buflen)
3473 {
3474         int ret;
3475         char *pos, *end;
3476         unsigned int i;
3477
3478         pos = buf;
3479         end = pos + buflen;
3480
3481         if (res < 0)
3482                 return 0;
3483
3484         for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) {
3485                 if (capa->enc & ciphers_group_mgmt[i].capa) {
3486                         ret = os_snprintf(pos, end - pos, "%s%s",
3487                                           pos == buf ? "" : " ",
3488                                           ciphers_group_mgmt[i].name);
3489                         if (os_snprintf_error(end - pos, ret))
3490                                 return pos - buf;
3491                         pos += ret;
3492                 }
3493         }
3494
3495         return pos - buf;
3496 }
3497
3498
3499 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
3500                                               struct wpa_driver_capa *capa,
3501                                               char *buf, size_t buflen)
3502 {
3503         int ret;
3504         char *pos, *end;
3505         size_t len;
3506
3507         pos = buf;
3508         end = pos + buflen;
3509
3510         if (res < 0) {
3511                 if (strict)
3512                         return 0;
3513                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
3514                                  "NONE", buflen);
3515                 if (len >= buflen)
3516                         return -1;
3517                 return len;
3518         }
3519
3520         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
3521         if (os_snprintf_error(end - pos, ret))
3522                 return pos - buf;
3523         pos += ret;
3524
3525         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3526                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
3527                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
3528                 if (os_snprintf_error(end - pos, ret))
3529                         return pos - buf;
3530                 pos += ret;
3531         }
3532
3533         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3534                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3535                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
3536                 if (os_snprintf_error(end - pos, ret))
3537                         return pos - buf;
3538                 pos += ret;
3539         }
3540
3541         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
3542                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
3543                 if (os_snprintf_error(end - pos, ret))
3544                         return pos - buf;
3545                 pos += ret;
3546         }
3547
3548 #ifdef CONFIG_SUITEB
3549         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) {
3550                 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B");
3551                 if (os_snprintf_error(end - pos, ret))
3552                         return pos - buf;
3553                 pos += ret;
3554         }
3555 #endif /* CONFIG_SUITEB */
3556 #ifdef CONFIG_SUITEB192
3557         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
3558                 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192");
3559                 if (os_snprintf_error(end - pos, ret))
3560                         return pos - buf;
3561                 pos += ret;
3562         }
3563 #endif /* CONFIG_SUITEB192 */
3564
3565         return pos - buf;
3566 }
3567
3568
3569 static int ctrl_iface_get_capability_proto(int res, char *strict,
3570                                            struct wpa_driver_capa *capa,
3571                                            char *buf, size_t buflen)
3572 {
3573         int ret;
3574         char *pos, *end;
3575         size_t len;
3576
3577         pos = buf;
3578         end = pos + buflen;
3579
3580         if (res < 0) {
3581                 if (strict)
3582                         return 0;
3583                 len = os_strlcpy(buf, "RSN WPA", buflen);
3584                 if (len >= buflen)
3585                         return -1;
3586                 return len;
3587         }
3588
3589         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
3590                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3591                 ret = os_snprintf(pos, end - pos, "%sRSN",
3592                                   pos == buf ? "" : " ");
3593                 if (os_snprintf_error(end - pos, ret))
3594                         return pos - buf;
3595                 pos += ret;
3596         }
3597
3598         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3599                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
3600                 ret = os_snprintf(pos, end - pos, "%sWPA",
3601                                   pos == buf ? "" : " ");
3602                 if (os_snprintf_error(end - pos, ret))
3603                         return pos - buf;
3604                 pos += ret;
3605         }
3606
3607         return pos - buf;
3608 }
3609
3610
3611 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
3612                                               int res, char *strict,
3613                                               struct wpa_driver_capa *capa,
3614                                               char *buf, size_t buflen)
3615 {
3616         int ret;
3617         char *pos, *end;
3618         size_t len;
3619
3620         pos = buf;
3621         end = pos + buflen;
3622
3623         if (res < 0) {
3624                 if (strict)
3625                         return 0;
3626                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
3627                 if (len >= buflen)
3628                         return -1;
3629                 return len;
3630         }
3631
3632         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
3633                 ret = os_snprintf(pos, end - pos, "%sOPEN",
3634                                   pos == buf ? "" : " ");
3635                 if (os_snprintf_error(end - pos, ret))
3636                         return pos - buf;
3637                 pos += ret;
3638         }
3639
3640         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
3641                 ret = os_snprintf(pos, end - pos, "%sSHARED",
3642                                   pos == buf ? "" : " ");
3643                 if (os_snprintf_error(end - pos, ret))
3644                         return pos - buf;
3645                 pos += ret;
3646         }
3647
3648         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
3649                 ret = os_snprintf(pos, end - pos, "%sLEAP",
3650                                   pos == buf ? "" : " ");
3651                 if (os_snprintf_error(end - pos, ret))
3652                         return pos - buf;
3653                 pos += ret;
3654         }
3655
3656 #ifdef CONFIG_SAE
3657         if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
3658                 ret = os_snprintf(pos, end - pos, "%sSAE",
3659                                   pos == buf ? "" : " ");
3660                 if (os_snprintf_error(end - pos, ret))
3661                         return pos - buf;
3662                 pos += ret;
3663         }
3664 #endif /* CONFIG_SAE */
3665
3666         return pos - buf;
3667 }
3668
3669
3670 static int ctrl_iface_get_capability_modes(int res, char *strict,
3671                                            struct wpa_driver_capa *capa,
3672                                            char *buf, size_t buflen)
3673 {
3674         int ret;
3675         char *pos, *end;
3676         size_t len;
3677
3678         pos = buf;
3679         end = pos + buflen;
3680
3681         if (res < 0) {
3682                 if (strict)
3683                         return 0;
3684                 len = os_strlcpy(buf, "IBSS AP", buflen);
3685                 if (len >= buflen)
3686                         return -1;
3687                 return len;
3688         }
3689
3690         if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
3691                 ret = os_snprintf(pos, end - pos, "%sIBSS",
3692                                   pos == buf ? "" : " ");
3693                 if (os_snprintf_error(end - pos, ret))
3694                         return pos - buf;
3695                 pos += ret;
3696         }
3697
3698         if (capa->flags & WPA_DRIVER_FLAGS_AP) {
3699                 ret = os_snprintf(pos, end - pos, "%sAP",
3700                                   pos == buf ? "" : " ");
3701                 if (os_snprintf_error(end - pos, ret))
3702                         return pos - buf;
3703                 pos += ret;
3704         }
3705
3706 #ifdef CONFIG_MESH
3707         if (capa->flags & WPA_DRIVER_FLAGS_MESH) {
3708                 ret = os_snprintf(pos, end - pos, "%sMESH",
3709                                   pos == buf ? "" : " ");
3710                 if (os_snprintf_error(end - pos, ret))
3711                         return pos - buf;
3712                 pos += ret;
3713         }
3714 #endif /* CONFIG_MESH */
3715
3716         return pos - buf;
3717 }
3718
3719
3720 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
3721                                               char *buf, size_t buflen)
3722 {
3723         struct hostapd_channel_data *chnl;
3724         int ret, i, j;
3725         char *pos, *end, *hmode;
3726
3727         pos = buf;
3728         end = pos + buflen;
3729
3730         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3731                 switch (wpa_s->hw.modes[j].mode) {
3732                 case HOSTAPD_MODE_IEEE80211B:
3733                         hmode = "B";
3734                         break;
3735                 case HOSTAPD_MODE_IEEE80211G:
3736                         hmode = "G";
3737                         break;
3738                 case HOSTAPD_MODE_IEEE80211A:
3739                         hmode = "A";
3740                         break;
3741                 case HOSTAPD_MODE_IEEE80211AD:
3742                         hmode = "AD";
3743                         break;
3744                 default:
3745                         continue;
3746                 }
3747                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
3748                 if (os_snprintf_error(end - pos, ret))
3749                         return pos - buf;
3750                 pos += ret;
3751                 chnl = wpa_s->hw.modes[j].channels;
3752                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3753                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3754                                 continue;
3755                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
3756                         if (os_snprintf_error(end - pos, ret))
3757                                 return pos - buf;
3758                         pos += ret;
3759                 }
3760                 ret = os_snprintf(pos, end - pos, "\n");
3761                 if (os_snprintf_error(end - pos, ret))
3762                         return pos - buf;
3763                 pos += ret;
3764         }
3765
3766         return pos - buf;
3767 }
3768
3769
3770 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
3771                                           char *buf, size_t buflen)
3772 {
3773         struct hostapd_channel_data *chnl;
3774         int ret, i, j;
3775         char *pos, *end, *hmode;
3776
3777         pos = buf;
3778         end = pos + buflen;
3779
3780         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3781                 switch (wpa_s->hw.modes[j].mode) {
3782                 case HOSTAPD_MODE_IEEE80211B:
3783                         hmode = "B";
3784                         break;
3785                 case HOSTAPD_MODE_IEEE80211G:
3786                         hmode = "G";
3787                         break;
3788                 case HOSTAPD_MODE_IEEE80211A:
3789                         hmode = "A";
3790                         break;
3791                 case HOSTAPD_MODE_IEEE80211AD:
3792                         hmode = "AD";
3793                         break;
3794                 default:
3795                         continue;
3796                 }
3797                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
3798                                   hmode);
3799                 if (os_snprintf_error(end - pos, ret))
3800                         return pos - buf;
3801                 pos += ret;
3802                 chnl = wpa_s->hw.modes[j].channels;
3803                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3804                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3805                                 continue;
3806                         ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
3807                                           chnl[i].chan, chnl[i].freq,
3808                                           chnl[i].flag & HOSTAPD_CHAN_NO_IR ?
3809                                           " (NO_IR)" : "",
3810                                           chnl[i].flag & HOSTAPD_CHAN_RADAR ?
3811                                           " (DFS)" : "");
3812
3813                         if (os_snprintf_error(end - pos, ret))
3814                                 return pos - buf;
3815                         pos += ret;
3816                 }
3817                 ret = os_snprintf(pos, end - pos, "\n");
3818                 if (os_snprintf_error(end - pos, ret))
3819                         return pos - buf;
3820                 pos += ret;
3821         }
3822
3823         return pos - buf;
3824 }
3825
3826
3827 static int wpa_supplicant_ctrl_iface_get_capability(
3828         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
3829         size_t buflen)
3830 {
3831         struct wpa_driver_capa capa;
3832         int res;
3833         char *strict;
3834         char field[30];
3835         size_t len;
3836
3837         /* Determine whether or not strict checking was requested */
3838         len = os_strlcpy(field, _field, sizeof(field));
3839         if (len >= sizeof(field))
3840                 return -1;
3841         strict = os_strchr(field, ' ');
3842         if (strict != NULL) {
3843                 *strict++ = '\0';
3844                 if (os_strcmp(strict, "strict") != 0)
3845                         return -1;
3846         }
3847
3848         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
3849                 field, strict ? strict : "");
3850
3851         if (os_strcmp(field, "eap") == 0) {
3852                 return eap_get_names(buf, buflen);
3853         }
3854
3855         res = wpa_drv_get_capa(wpa_s, &capa);
3856
3857         if (os_strcmp(field, "pairwise") == 0)
3858                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
3859                                                           buf, buflen);
3860
3861         if (os_strcmp(field, "group") == 0)
3862                 return ctrl_iface_get_capability_group(res, strict, &capa,
3863                                                        buf, buflen);
3864
3865         if (os_strcmp(field, "group_mgmt") == 0)
3866                 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa,
3867                                                             buf, buflen);
3868
3869         if (os_strcmp(field, "key_mgmt") == 0)
3870                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3871                                                           buf, buflen);
3872
3873         if (os_strcmp(field, "proto") == 0)
3874                 return ctrl_iface_get_capability_proto(res, strict, &capa,
3875                                                        buf, buflen);
3876
3877         if (os_strcmp(field, "auth_alg") == 0)
3878                 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict,
3879                                                           &capa, buf, buflen);
3880
3881         if (os_strcmp(field, "modes") == 0)
3882                 return ctrl_iface_get_capability_modes(res, strict, &capa,
3883                                                        buf, buflen);
3884
3885         if (os_strcmp(field, "channels") == 0)
3886                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3887
3888         if (os_strcmp(field, "freq") == 0)
3889                 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
3890
3891 #ifdef CONFIG_TDLS
3892         if (os_strcmp(field, "tdls") == 0)
3893                 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
3894 #endif /* CONFIG_TDLS */
3895
3896 #ifdef CONFIG_ERP
3897         if (os_strcmp(field, "erp") == 0) {
3898                 res = os_snprintf(buf, buflen, "ERP");
3899                 if (os_snprintf_error(buflen, res))
3900                         return -1;
3901                 return res;
3902         }
3903 #endif /* CONFIG_EPR */
3904
3905         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3906                    field);
3907
3908         return -1;
3909 }
3910
3911
3912 #ifdef CONFIG_INTERWORKING
3913 static char * anqp_add_hex(char *pos, char *end, const char *title,
3914                            struct wpabuf *data)
3915 {
3916         char *start = pos;
3917         size_t i;
3918         int ret;
3919         const u8 *d;
3920
3921         if (data == NULL)
3922                 return start;
3923
3924         ret = os_snprintf(pos, end - pos, "%s=", title);
3925         if (os_snprintf_error(end - pos, ret))
3926                 return start;
3927         pos += ret;
3928
3929         d = wpabuf_head_u8(data);
3930         for (i = 0; i < wpabuf_len(data); i++) {
3931                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
3932                 if (os_snprintf_error(end - pos, ret))
3933                         return start;
3934                 pos += ret;
3935         }
3936
3937         ret = os_snprintf(pos, end - pos, "\n");
3938         if (os_snprintf_error(end - pos, ret))
3939                 return start;
3940         pos += ret;
3941
3942         return pos;
3943 }
3944 #endif /* CONFIG_INTERWORKING */
3945
3946
3947 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3948                           unsigned long mask, char *buf, size_t buflen)
3949 {
3950         size_t i;
3951         int ret;
3952         char *pos, *end;
3953         const u8 *ie, *ie2, *osen_ie;
3954
3955         pos = buf;
3956         end = buf + buflen;
3957
3958         if (mask & WPA_BSS_MASK_ID) {
3959                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3960                 if (os_snprintf_error(end - pos, ret))
3961                         return 0;
3962                 pos += ret;
3963         }
3964
3965         if (mask & WPA_BSS_MASK_BSSID) {
3966                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3967                                   MAC2STR(bss->bssid));
3968                 if (os_snprintf_error(end - pos, ret))
3969                         return 0;
3970                 pos += ret;
3971         }
3972
3973         if (mask & WPA_BSS_MASK_FREQ) {
3974                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3975                 if (os_snprintf_error(end - pos, ret))
3976                         return 0;
3977                 pos += ret;
3978         }
3979
3980         if (mask & WPA_BSS_MASK_BEACON_INT) {
3981                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3982                                   bss->beacon_int);
3983                 if (os_snprintf_error(end - pos, ret))
3984                         return 0;
3985                 pos += ret;
3986         }
3987
3988         if (mask & WPA_BSS_MASK_CAPABILITIES) {
3989                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3990                                   bss->caps);
3991                 if (os_snprintf_error(end - pos, ret))
3992                         return 0;
3993                 pos += ret;
3994         }
3995
3996         if (mask & WPA_BSS_MASK_QUAL) {
3997                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3998                 if (os_snprintf_error(end - pos, ret))
3999                         return 0;
4000                 pos += ret;
4001         }
4002
4003         if (mask & WPA_BSS_MASK_NOISE) {
4004                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
4005                 if (os_snprintf_error(end - pos, ret))
4006                         return 0;
4007                 pos += ret;
4008         }
4009
4010         if (mask & WPA_BSS_MASK_LEVEL) {
4011                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
4012                 if (os_snprintf_error(end - pos, ret))
4013                         return 0;
4014                 pos += ret;
4015         }
4016
4017         if (mask & WPA_BSS_MASK_TSF) {
4018                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
4019                                   (unsigned long long) bss->tsf);
4020                 if (os_snprintf_error(end - pos, ret))
4021                         return 0;
4022                 pos += ret;
4023         }
4024
4025         if (mask & WPA_BSS_MASK_AGE) {
4026                 struct os_reltime now;
4027
4028                 os_get_reltime(&now);
4029                 ret = os_snprintf(pos, end - pos, "age=%d\n",
4030                                   (int) (now.sec - bss->last_update.sec));
4031                 if (os_snprintf_error(end - pos, ret))
4032                         return 0;
4033                 pos += ret;
4034         }
4035
4036         if (mask & WPA_BSS_MASK_IE) {
4037                 ret = os_snprintf(pos, end - pos, "ie=");
4038                 if (os_snprintf_error(end - pos, ret))
4039                         return 0;
4040                 pos += ret;
4041
4042                 ie = (const u8 *) (bss + 1);
4043                 for (i = 0; i < bss->ie_len; i++) {
4044                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
4045                         if (os_snprintf_error(end - pos, ret))
4046                                 return 0;
4047                         pos += ret;
4048                 }
4049
4050                 ret = os_snprintf(pos, end - pos, "\n");
4051                 if (os_snprintf_error(end - pos, ret))
4052                         return 0;
4053                 pos += ret;
4054         }
4055
4056         if (mask & WPA_BSS_MASK_FLAGS) {
4057                 ret = os_snprintf(pos, end - pos, "flags=");
4058                 if (os_snprintf_error(end - pos, ret))
4059                         return 0;
4060                 pos += ret;
4061
4062                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
4063                 if (ie)
4064                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
4065                                                     2 + ie[1]);
4066                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4067                 if (ie2)
4068                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
4069                                                     2 + ie2[1]);
4070                 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
4071                 if (osen_ie)
4072                         pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
4073                                                     osen_ie, 2 + osen_ie[1]);
4074                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
4075                 if (!ie && !ie2 && !osen_ie &&
4076                     (bss->caps & IEEE80211_CAP_PRIVACY)) {
4077                         ret = os_snprintf(pos, end - pos, "[WEP]");
4078                         if (os_snprintf_error(end - pos, ret))
4079                                 return 0;
4080                         pos += ret;
4081                 }
4082                 if (bss_is_dmg(bss)) {
4083                         const char *s;
4084                         ret = os_snprintf(pos, end - pos, "[DMG]");
4085                         if (os_snprintf_error(end - pos, ret))
4086                                 return 0;
4087                         pos += ret;
4088                         switch (bss->caps & IEEE80211_CAP_DMG_MASK) {
4089                         case IEEE80211_CAP_DMG_IBSS:
4090                                 s = "[IBSS]";
4091                                 break;
4092                         case IEEE80211_CAP_DMG_AP:
4093                                 s = "[ESS]";
4094                                 break;
4095                         case IEEE80211_CAP_DMG_PBSS:
4096                                 s = "[PBSS]";
4097                                 break;
4098                         default:
4099                                 s = "";
4100                                 break;
4101                         }
4102                         ret = os_snprintf(pos, end - pos, "%s", s);
4103                         if (os_snprintf_error(end - pos, ret))
4104                                 return 0;
4105                         pos += ret;
4106                 } else {
4107                         if (bss->caps & IEEE80211_CAP_IBSS) {
4108                                 ret = os_snprintf(pos, end - pos, "[IBSS]");
4109                                 if (os_snprintf_error(end - pos, ret))
4110                                         return 0;
4111                                 pos += ret;
4112                         }
4113                         if (bss->caps & IEEE80211_CAP_ESS) {
4114                                 ret = os_snprintf(pos, end - pos, "[ESS]");
4115                                 if (os_snprintf_error(end - pos, ret))
4116                                         return 0;
4117                                 pos += ret;
4118                         }
4119                 }
4120                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
4121                     wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
4122                         ret = os_snprintf(pos, end - pos, "[P2P]");
4123                         if (os_snprintf_error(end - pos, ret))
4124                                 return 0;
4125                         pos += ret;
4126                 }
4127 #ifdef CONFIG_HS20
4128                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
4129                         ret = os_snprintf(pos, end - pos, "[HS20]");
4130                         if (os_snprintf_error(end - pos, ret))
4131                                 return 0;
4132                         pos += ret;
4133                 }
4134 #endif /* CONFIG_HS20 */
4135
4136                 ret = os_snprintf(pos, end - pos, "\n");
4137                 if (os_snprintf_error(end - pos, ret))
4138                         return 0;
4139                 pos += ret;
4140         }
4141
4142         if (mask & WPA_BSS_MASK_SSID) {
4143                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
4144                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
4145                 if (os_snprintf_error(end - pos, ret))
4146                         return 0;
4147                 pos += ret;
4148         }
4149
4150 #ifdef CONFIG_WPS
4151         if (mask & WPA_BSS_MASK_WPS_SCAN) {
4152                 ie = (const u8 *) (bss + 1);
4153                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
4154                 if (ret < 0 || ret >= end - pos)
4155                         return 0;
4156                 pos += ret;
4157         }
4158 #endif /* CONFIG_WPS */
4159
4160 #ifdef CONFIG_P2P
4161         if (mask & WPA_BSS_MASK_P2P_SCAN) {
4162                 ie = (const u8 *) (bss + 1);
4163                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
4164                 if (ret < 0 || ret >= end - pos)
4165                         return 0;
4166                 pos += ret;
4167         }
4168 #endif /* CONFIG_P2P */
4169
4170 #ifdef CONFIG_WIFI_DISPLAY
4171         if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
4172                 struct wpabuf *wfd;
4173                 ie = (const u8 *) (bss + 1);
4174                 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
4175                                                   WFD_IE_VENDOR_TYPE);
4176                 if (wfd) {
4177                         ret = os_snprintf(pos, end - pos, "wfd_subelems=");
4178                         if (os_snprintf_error(end - pos, ret)) {
4179                                 wpabuf_free(wfd);
4180                                 return 0;
4181                         }
4182                         pos += ret;
4183
4184                         pos += wpa_snprintf_hex(pos, end - pos,
4185                                                 wpabuf_head(wfd),
4186                                                 wpabuf_len(wfd));
4187                         wpabuf_free(wfd);
4188
4189                         ret = os_snprintf(pos, end - pos, "\n");
4190                         if (os_snprintf_error(end - pos, ret))
4191                                 return 0;
4192                         pos += ret;
4193                 }
4194         }
4195 #endif /* CONFIG_WIFI_DISPLAY */
4196
4197 #ifdef CONFIG_INTERWORKING
4198         if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
4199                 struct wpa_bss_anqp *anqp = bss->anqp;
4200                 pos = anqp_add_hex(pos, end, "anqp_capability_list",
4201                                    anqp->capability_list);
4202                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
4203                                    anqp->venue_name);
4204                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
4205                                    anqp->network_auth_type);
4206                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
4207                                    anqp->roaming_consortium);
4208                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
4209                                    anqp->ip_addr_type_availability);
4210                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
4211                                    anqp->nai_realm);
4212                 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
4213                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
4214                                    anqp->domain_name);
4215 #ifdef CONFIG_HS20
4216                 pos = anqp_add_hex(pos, end, "hs20_capability_list",
4217                                    anqp->hs20_capability_list);
4218                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
4219                                    anqp->hs20_operator_friendly_name);
4220                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
4221                                    anqp->hs20_wan_metrics);
4222                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
4223                                    anqp->hs20_connection_capability);
4224                 pos = anqp_add_hex(pos, end, "hs20_operating_class",
4225                                    anqp->hs20_operating_class);
4226                 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
4227                                    anqp->hs20_osu_providers_list);
4228 #endif /* CONFIG_HS20 */
4229         }
4230 #endif /* CONFIG_INTERWORKING */
4231
4232 #ifdef CONFIG_MESH
4233         if (mask & WPA_BSS_MASK_MESH_SCAN) {
4234                 ie = (const u8 *) (bss + 1);
4235                 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
4236                 if (ret < 0 || ret >= end - pos)
4237                         return 0;
4238                 pos += ret;
4239         }
4240 #endif /* CONFIG_MESH */
4241
4242         if (mask & WPA_BSS_MASK_SNR) {
4243                 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr);
4244                 if (os_snprintf_error(end - pos, ret))
4245                         return 0;
4246                 pos += ret;
4247         }
4248
4249         if (mask & WPA_BSS_MASK_EST_THROUGHPUT) {
4250                 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n",
4251                                   bss->est_throughput);
4252                 if (os_snprintf_error(end - pos, ret))
4253                         return 0;
4254                 pos += ret;
4255         }
4256
4257         if (mask & WPA_BSS_MASK_DELIM) {
4258                 ret = os_snprintf(pos, end - pos, "====\n");
4259                 if (os_snprintf_error(end - pos, ret))
4260                         return 0;
4261                 pos += ret;
4262         }
4263
4264         return pos - buf;
4265 }
4266
4267
4268 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
4269                                          const char *cmd, char *buf,
4270                                          size_t buflen)
4271 {
4272         u8 bssid[ETH_ALEN];
4273         size_t i;
4274         struct wpa_bss *bss;
4275         struct wpa_bss *bsslast = NULL;
4276         struct dl_list *next;
4277         int ret = 0;
4278         int len;
4279         char *ctmp, *end = buf + buflen;
4280         unsigned long mask = WPA_BSS_MASK_ALL;
4281
4282         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
4283                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
4284                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
4285                                             list_id);
4286                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
4287                                                list_id);
4288                 } else { /* N1-N2 */
4289                         unsigned int id1, id2;
4290
4291                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
4292                                 wpa_printf(MSG_INFO, "Wrong BSS range "
4293                                            "format");
4294                                 return 0;
4295                         }
4296
4297                         if (*(cmd + 6) == '-')
4298                                 id1 = 0;
4299                         else
4300                                 id1 = atoi(cmd + 6);
4301                         ctmp++;
4302                         if (*ctmp >= '0' && *ctmp <= '9')
4303                                 id2 = atoi(ctmp);
4304                         else
4305                                 id2 = (unsigned int) -1;
4306                         bss = wpa_bss_get_id_range(wpa_s, id1, id2);
4307                         if (id2 == (unsigned int) -1)
4308                                 bsslast = dl_list_last(&wpa_s->bss_id,
4309                                                        struct wpa_bss,
4310                                                        list_id);
4311                         else {
4312                                 bsslast = wpa_bss_get_id(wpa_s, id2);
4313                                 if (bsslast == NULL && bss && id2 > id1) {
4314                                         struct wpa_bss *tmp = bss;
4315                                         for (;;) {
4316                                                 next = tmp->list_id.next;
4317                                                 if (next == &wpa_s->bss_id)
4318                                                         break;
4319                                                 tmp = dl_list_entry(
4320                                                         next, struct wpa_bss,
4321                                                         list_id);
4322                                                 if (tmp->id > id2)
4323                                                         break;
4324                                                 bsslast = tmp;
4325                                         }
4326                                 }
4327                         }
4328                 }
4329         } else if (os_strncmp(cmd, "FIRST", 5) == 0)
4330                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
4331         else if (os_strncmp(cmd, "LAST", 4) == 0)
4332                 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
4333         else if (os_strncmp(cmd, "ID-", 3) == 0) {
4334                 i = atoi(cmd + 3);
4335                 bss = wpa_bss_get_id(wpa_s, i);
4336         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4337                 i = atoi(cmd + 5);
4338                 bss = wpa_bss_get_id(wpa_s, i);
4339                 if (bss) {
4340                         next = bss->list_id.next;
4341                         if (next == &wpa_s->bss_id)
4342                                 bss = NULL;
4343                         else
4344                                 bss = dl_list_entry(next, struct wpa_bss,
4345                                                     list_id);
4346                 }
4347 #ifdef CONFIG_P2P
4348         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
4349                 if (hwaddr_aton(cmd + 13, bssid) == 0)
4350                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
4351                 else
4352                         bss = NULL;
4353 #endif /* CONFIG_P2P */
4354         } else if (hwaddr_aton(cmd, bssid) == 0)
4355                 bss = wpa_bss_get_bssid(wpa_s, bssid);
4356         else {
4357                 struct wpa_bss *tmp;
4358                 i = atoi(cmd);
4359                 bss = NULL;
4360                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
4361                 {
4362                         if (i-- == 0) {
4363                                 bss = tmp;
4364                                 break;
4365                         }
4366                 }
4367         }
4368
4369         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
4370                 mask = strtoul(ctmp + 5, NULL, 0x10);
4371                 if (mask == 0)
4372                         mask = WPA_BSS_MASK_ALL;
4373         }
4374
4375         if (bss == NULL)
4376                 return 0;
4377
4378         if (bsslast == NULL)
4379                 bsslast = bss;
4380         do {
4381                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
4382                 ret += len;
4383                 buf += len;
4384                 buflen -= len;
4385                 if (bss == bsslast) {
4386                         if ((mask & WPA_BSS_MASK_DELIM) && len &&
4387                             (bss == dl_list_last(&wpa_s->bss_id,
4388                                                  struct wpa_bss, list_id))) {
4389                                 int res;
4390
4391                                 res = os_snprintf(buf - 5, end - buf + 5,
4392                                                   "####\n");
4393                                 if (os_snprintf_error(end - buf + 5, res)) {
4394                                         wpa_printf(MSG_DEBUG,
4395                                                    "Could not add end delim");
4396                                 }
4397                         }
4398                         break;
4399                 }
4400                 next = bss->list_id.next;
4401                 if (next == &wpa_s->bss_id)
4402                         break;
4403                 bss = dl_list_entry(next, struct wpa_bss, list_id);
4404         } while (bss && len);
4405
4406         return ret;
4407 }
4408
4409
4410 static int wpa_supplicant_ctrl_iface_ap_scan(
4411         struct wpa_supplicant *wpa_s, char *cmd)
4412 {
4413         int ap_scan = atoi(cmd);
4414         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
4415 }
4416
4417
4418 static int wpa_supplicant_ctrl_iface_scan_interval(
4419         struct wpa_supplicant *wpa_s, char *cmd)
4420 {
4421         int scan_int = atoi(cmd);
4422         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
4423 }
4424
4425
4426 static int wpa_supplicant_ctrl_iface_bss_expire_age(
4427         struct wpa_supplicant *wpa_s, char *cmd)
4428 {
4429         int expire_age = atoi(cmd);
4430         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
4431 }
4432
4433
4434 static int wpa_supplicant_ctrl_iface_bss_expire_count(
4435         struct wpa_supplicant *wpa_s, char *cmd)
4436 {
4437         int expire_count = atoi(cmd);
4438         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
4439 }
4440
4441
4442 static void wpa_supplicant_ctrl_iface_bss_flush(
4443         struct wpa_supplicant *wpa_s, char *cmd)
4444 {
4445         int flush_age = atoi(cmd);
4446
4447         if (flush_age == 0)
4448                 wpa_bss_flush(wpa_s);
4449         else
4450                 wpa_bss_flush_by_age(wpa_s, flush_age);
4451 }
4452
4453
4454 #ifdef CONFIG_TESTING_OPTIONS
4455 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
4456 {
4457         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
4458         /* MLME-DELETEKEYS.request */
4459         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
4460         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
4461         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
4462         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
4463 #ifdef CONFIG_IEEE80211W
4464         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
4465         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
4466 #endif /* CONFIG_IEEE80211W */
4467
4468         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
4469                         0);
4470         /* MLME-SETPROTECTION.request(None) */
4471         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
4472                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
4473                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
4474         wpa_sm_drop_sa(wpa_s->wpa);
4475 }
4476 #endif /* CONFIG_TESTING_OPTIONS */
4477
4478
4479 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
4480                                           char *addr)
4481 {
4482 #ifdef CONFIG_NO_SCAN_PROCESSING
4483         return -1;
4484 #else /* CONFIG_NO_SCAN_PROCESSING */
4485         u8 bssid[ETH_ALEN];
4486         struct wpa_bss *bss;
4487         struct wpa_ssid *ssid = wpa_s->current_ssid;
4488
4489         if (hwaddr_aton(addr, bssid)) {
4490                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
4491                            "address '%s'", addr);
4492                 return -1;
4493         }
4494
4495         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
4496
4497         if (!ssid) {
4498                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
4499                            "configuration known for the target AP");
4500                 return -1;
4501         }
4502
4503         bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
4504         if (!bss) {
4505                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
4506                            "from BSS table");
4507                 return -1;
4508         }
4509
4510         /*
4511          * TODO: Find best network configuration block from configuration to
4512          * allow roaming to other networks
4513          */
4514
4515         wpa_s->reassociate = 1;
4516         wpa_supplicant_connect(wpa_s, bss, ssid);
4517
4518         return 0;
4519 #endif /* CONFIG_NO_SCAN_PROCESSING */
4520 }
4521
4522
4523 #ifdef CONFIG_P2P
4524 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
4525 {
4526         unsigned int timeout = atoi(cmd);
4527         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
4528         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
4529         u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
4530         char *pos;
4531         unsigned int search_delay;
4532         const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
4533         u8 seek_count = 0;
4534         int freq = 0;
4535
4536         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4537                 wpa_dbg(wpa_s, MSG_INFO,
4538                         "Reject P2P_FIND since interface is disabled");
4539                 return -1;
4540         }
4541         if (os_strstr(cmd, "type=social"))
4542                 type = P2P_FIND_ONLY_SOCIAL;
4543         else if (os_strstr(cmd, "type=progressive"))
4544                 type = P2P_FIND_PROGRESSIVE;
4545
4546         pos = os_strstr(cmd, "dev_id=");
4547         if (pos) {
4548                 pos += 7;
4549                 if (hwaddr_aton(pos, dev_id))
4550                         return -1;
4551                 _dev_id = dev_id;
4552         }
4553
4554         pos = os_strstr(cmd, "dev_type=");
4555         if (pos) {
4556                 pos += 9;
4557                 if (wps_dev_type_str2bin(pos, dev_type) < 0)
4558                         return -1;
4559                 _dev_type = dev_type;
4560         }
4561
4562         pos = os_strstr(cmd, "delay=");
4563         if (pos) {
4564                 pos += 6;
4565                 search_delay = atoi(pos);
4566         } else
4567                 search_delay = wpas_p2p_search_delay(wpa_s);
4568
4569         /* Must be searched for last, because it adds nul termination */
4570         pos = os_strstr(cmd, " seek=");
4571         while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) {
4572                 char *term;
4573
4574                 term = os_strchr(pos + 1, ' ');
4575                 _seek[seek_count++] = pos + 6;
4576                 seek = _seek;
4577                 pos = os_strstr(pos + 6, " seek=");
4578
4579                 if (term)
4580                         *term = '\0';
4581         }
4582         if (seek_count > P2P_MAX_QUERY_HASH) {
4583                 seek[0] = NULL;
4584                 seek_count = 1;
4585         }
4586
4587         pos = os_strstr(cmd, "freq=");
4588         if (pos) {
4589                 pos += 5;
4590                 freq = atoi(pos);
4591                 if (freq <= 0)
4592                         return -1;
4593         }
4594
4595         return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
4596                              _dev_id, search_delay, seek_count, seek, freq);
4597 }
4598
4599
4600 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
4601 {
4602         struct p2ps_provision *p2ps_prov;
4603         char *pos;
4604         size_t info_len = 0;
4605         char *info = NULL;
4606         u8 role = P2PS_SETUP_NONE;
4607         long long unsigned val;
4608
4609         pos = os_strstr(cmd, "info=");
4610         if (pos) {
4611                 pos += 5;
4612                 info_len = os_strlen(pos);
4613
4614                 if (info_len) {
4615                         info = os_malloc(info_len + 1);
4616                         if (info) {
4617                                 info_len = utf8_unescape(pos, info_len,
4618                                                          info, info_len + 1);
4619                         } else
4620                                 info_len = 0;
4621                 }
4622         }
4623
4624         p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
4625         if (p2ps_prov == NULL) {
4626                 os_free(info);
4627                 return NULL;
4628         }
4629
4630         if (info) {
4631                 os_memcpy(p2ps_prov->info, info, info_len);
4632                 p2ps_prov->info[info_len] = '\0';
4633                 os_free(info);
4634         }
4635
4636         pos = os_strstr(cmd, "status=");
4637         if (pos)
4638                 p2ps_prov->status = atoi(pos + 7);
4639         else
4640                 p2ps_prov->status = -1;
4641
4642         pos = os_strstr(cmd, "adv_id=");
4643         if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
4644                 goto invalid_args;
4645         p2ps_prov->adv_id = val;
4646
4647         pos = os_strstr(cmd, "method=");
4648         if (pos)
4649                 p2ps_prov->method = strtol(pos + 7, NULL, 16);
4650         else
4651                 p2ps_prov->method = 0;
4652
4653         pos = os_strstr(cmd, "session=");
4654         if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
4655                 goto invalid_args;
4656         p2ps_prov->session_id = val;
4657
4658         pos = os_strstr(cmd, "adv_mac=");
4659         if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
4660                 goto invalid_args;
4661
4662         pos = os_strstr(cmd, "session_mac=");
4663         if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
4664                 goto invalid_args;
4665
4666         /* force conncap with tstCap (no sanity checks) */
4667         pos = os_strstr(cmd, "tstCap=");
4668         if (pos) {
4669                 role = strtol(pos + 7, NULL, 16);
4670         } else {
4671                 pos = os_strstr(cmd, "role=");
4672                 if (pos) {
4673                         role = strtol(pos + 5, NULL, 16);
4674                         if (role != P2PS_SETUP_CLIENT &&
4675                             role != P2PS_SETUP_GROUP_OWNER)
4676                                 role = P2PS_SETUP_NONE;
4677                 }
4678         }
4679         p2ps_prov->role = role;
4680
4681         return p2ps_prov;
4682
4683 invalid_args:
4684         os_free(p2ps_prov);
4685         return NULL;
4686 }
4687
4688
4689 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
4690 {
4691         u8 addr[ETH_ALEN];
4692         struct p2ps_provision *p2ps_prov;
4693         char *pos;
4694
4695         /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
4696
4697         wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
4698
4699         if (hwaddr_aton(cmd, addr))
4700                 return -1;
4701
4702         pos = cmd + 17;
4703         if (*pos != ' ')
4704                 return -1;
4705
4706         p2ps_prov = p2p_parse_asp_provision_cmd(pos);
4707         if (!p2ps_prov)
4708                 return -1;
4709
4710         if (p2ps_prov->status < 0) {
4711                 os_free(p2ps_prov);
4712                 return -1;
4713         }
4714
4715         return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
4716                                   p2ps_prov);
4717 }
4718
4719
4720 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
4721 {
4722         u8 addr[ETH_ALEN];
4723         struct p2ps_provision *p2ps_prov;
4724         char *pos;
4725
4726         /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
4727          *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
4728          */
4729
4730         wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
4731         if (hwaddr_aton(cmd, addr))
4732                 return -1;
4733
4734         pos = cmd + 17;
4735         if (*pos != ' ')
4736                 return -1;
4737
4738         p2ps_prov = p2p_parse_asp_provision_cmd(pos);
4739         if (!p2ps_prov)
4740                 return -1;
4741
4742         return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
4743                                   p2ps_prov);
4744 }
4745
4746
4747 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
4748                             char *buf, size_t buflen)
4749 {
4750         u8 addr[ETH_ALEN];
4751         char *pos, *pos2;
4752         char *pin = NULL;
4753         enum p2p_wps_method wps_method;
4754         int new_pin;
4755         int ret;
4756         int persistent_group, persistent_id = -1;
4757         int join;
4758         int auth;
4759         int automatic;
4760         int go_intent = -1;
4761         int freq = 0;
4762         int pd;
4763         int ht40, vht;
4764
4765         if (!wpa_s->global->p2p_init_wpa_s)
4766                 return -1;
4767         if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
4768                 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
4769                         wpa_s->global->p2p_init_wpa_s->ifname);
4770                 wpa_s = wpa_s->global->p2p_init_wpa_s;
4771         }
4772
4773         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
4774          * [persistent|persistent=<network id>]
4775          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
4776          * [ht40] [vht] [auto] */
4777
4778         if (hwaddr_aton(cmd, addr))
4779                 return -1;
4780
4781         pos = cmd + 17;
4782         if (*pos != ' ')
4783                 return -1;
4784         pos++;
4785
4786         persistent_group = os_strstr(pos, " persistent") != NULL;
4787         pos2 = os_strstr(pos, " persistent=");
4788         if (pos2) {
4789                 struct wpa_ssid *ssid;
4790                 persistent_id = atoi(pos2 + 12);
4791                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
4792                 if (ssid == NULL || ssid->disabled != 2 ||
4793                     ssid->mode != WPAS_MODE_P2P_GO) {
4794                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
4795                                    "SSID id=%d for persistent P2P group (GO)",
4796                                    persistent_id);
4797                         return -1;
4798                 }
4799         }
4800         join = os_strstr(pos, " join") != NULL;
4801         auth = os_strstr(pos, " auth") != NULL;
4802         automatic = os_strstr(pos, " auto") != NULL;
4803         pd = os_strstr(pos, " provdisc") != NULL;
4804         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
4805         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4806                 vht;
4807
4808         pos2 = os_strstr(pos, " go_intent=");
4809         if (pos2) {
4810                 pos2 += 11;
4811                 go_intent = atoi(pos2);
4812                 if (go_intent < 0 || go_intent > 15)
4813                         return -1;
4814         }
4815
4816         pos2 = os_strstr(pos, " freq=");
4817         if (pos2) {
4818                 pos2 += 6;
4819                 freq = atoi(pos2);
4820                 if (freq <= 0)
4821                         return -1;
4822         }
4823
4824         if (os_strncmp(pos, "pin", 3) == 0) {
4825                 /* Request random PIN (to be displayed) and enable the PIN */
4826                 wps_method = WPS_PIN_DISPLAY;
4827         } else if (os_strncmp(pos, "pbc", 3) == 0) {
4828                 wps_method = WPS_PBC;
4829         } else {
4830                 pin = pos;
4831                 pos = os_strchr(pin, ' ');
4832                 wps_method = WPS_PIN_KEYPAD;
4833                 if (pos) {
4834                         *pos++ = '\0';
4835                         if (os_strncmp(pos, "display", 7) == 0)
4836                                 wps_method = WPS_PIN_DISPLAY;
4837                         else if (os_strncmp(pos, "p2ps", 4) == 0)
4838                                 wps_method = WPS_P2PS;
4839                 }
4840                 if (!wps_pin_str_valid(pin)) {
4841                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
4842                         return 17;
4843                 }
4844         }
4845
4846         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
4847                                    persistent_group, automatic, join,
4848                                    auth, go_intent, freq, persistent_id, pd,
4849                                    ht40, vht);
4850         if (new_pin == -2) {
4851                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
4852                 return 25;
4853         }
4854         if (new_pin == -3) {
4855                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
4856                 return 25;
4857         }
4858         if (new_pin < 0)
4859                 return -1;
4860         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
4861                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
4862                 if (os_snprintf_error(buflen, ret))
4863                         return -1;
4864                 return ret;
4865         }
4866
4867         os_memcpy(buf, "OK\n", 3);
4868         return 3;
4869 }
4870
4871
4872 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
4873 {
4874         unsigned int timeout = atoi(cmd);
4875         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4876                 wpa_dbg(wpa_s, MSG_INFO,
4877                         "Reject P2P_LISTEN since interface is disabled");
4878                 return -1;
4879         }
4880         return wpas_p2p_listen(wpa_s, timeout);
4881 }
4882
4883
4884 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
4885 {
4886         u8 addr[ETH_ALEN];
4887         char *pos;
4888         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
4889
4890         /* <addr> <config method> [join|auto] */
4891
4892         if (hwaddr_aton(cmd, addr))
4893                 return -1;
4894
4895         pos = cmd + 17;
4896         if (*pos != ' ')
4897                 return -1;
4898         pos++;
4899
4900         if (os_strstr(pos, " join") != NULL)
4901                 use = WPAS_P2P_PD_FOR_JOIN;
4902         else if (os_strstr(pos, " auto") != NULL)
4903                 use = WPAS_P2P_PD_AUTO;
4904
4905         return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL);
4906 }
4907
4908
4909 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
4910                               size_t buflen)
4911 {
4912         struct wpa_ssid *ssid = wpa_s->current_ssid;
4913
4914         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
4915             ssid->passphrase == NULL)
4916                 return -1;
4917
4918         os_strlcpy(buf, ssid->passphrase, buflen);
4919         return os_strlen(buf);
4920 }
4921
4922
4923 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
4924                                   char *buf, size_t buflen)
4925 {
4926         u64 ref;
4927         int res;
4928         u8 dst_buf[ETH_ALEN], *dst;
4929         struct wpabuf *tlvs;
4930         char *pos;
4931         size_t len;
4932
4933         if (hwaddr_aton(cmd, dst_buf))
4934                 return -1;
4935         dst = dst_buf;
4936         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
4937             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
4938                 dst = NULL;
4939         pos = cmd + 17;
4940         if (*pos != ' ')
4941                 return -1;
4942         pos++;
4943
4944         if (os_strncmp(pos, "upnp ", 5) == 0) {
4945                 u8 version;
4946                 pos += 5;
4947                 if (hexstr2bin(pos, &version, 1) < 0)
4948                         return -1;
4949                 pos += 2;
4950                 if (*pos != ' ')
4951                         return -1;
4952                 pos++;
4953                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
4954 #ifdef CONFIG_WIFI_DISPLAY
4955         } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
4956                 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
4957 #endif /* CONFIG_WIFI_DISPLAY */
4958         } else if (os_strncmp(pos, "asp ", 4) == 0) {
4959                 char *svc_str;
4960                 char *svc_info = NULL;
4961                 u32 id;
4962
4963                 pos += 4;
4964                 if (sscanf(pos, "%x", &id) != 1 || id > 0xff)
4965                         return -1;
4966
4967                 pos = os_strchr(pos, ' ');
4968                 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ')
4969                         return -1;
4970
4971                 svc_str = pos + 1;
4972
4973                 pos = os_strchr(svc_str, ' ');
4974
4975                 if (pos)
4976                         *pos++ = '\0';
4977
4978                 /* All remaining data is the svc_info string */
4979                 if (pos && pos[0] && pos[0] != ' ') {
4980                         len = os_strlen(pos);
4981
4982                         /* Unescape in place */
4983                         len = utf8_unescape(pos, len, pos, len);
4984                         if (len > 0xff)
4985                                 return -1;
4986
4987                         svc_info = pos;
4988                 }
4989
4990                 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id,
4991                                               svc_str, svc_info);
4992         } else {
4993                 len = os_strlen(pos);
4994                 if (len & 1)
4995                         return -1;
4996                 len /= 2;
4997                 tlvs = wpabuf_alloc(len);
4998                 if (tlvs == NULL)
4999                         return -1;
5000                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
5001                         wpabuf_free(tlvs);
5002                         return -1;
5003                 }
5004
5005                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
5006                 wpabuf_free(tlvs);
5007         }
5008         if (ref == 0)
5009                 return -1;
5010         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
5011         if (os_snprintf_error(buflen, res))
5012                 return -1;
5013         return res;
5014 }
5015
5016
5017 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
5018                                          char *cmd)
5019 {
5020         long long unsigned val;
5021         u64 req;
5022         if (sscanf(cmd, "%llx", &val) != 1)
5023                 return -1;
5024         req = val;
5025         return wpas_p2p_sd_cancel_request(wpa_s, req);
5026 }
5027
5028
5029 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
5030 {
5031         int freq;
5032         u8 dst[ETH_ALEN];
5033         u8 dialog_token;
5034         struct wpabuf *resp_tlvs;
5035         char *pos, *pos2;
5036         size_t len;
5037
5038         pos = os_strchr(cmd, ' ');
5039         if (pos == NULL)
5040                 return -1;
5041         *pos++ = '\0';
5042         freq = atoi(cmd);
5043         if (freq == 0)
5044                 return -1;
5045
5046         if (hwaddr_aton(pos, dst))
5047                 return -1;
5048         pos += 17;
5049         if (*pos != ' ')
5050                 return -1;
5051         pos++;
5052
5053         pos2 = os_strchr(pos, ' ');
5054         if (pos2 == NULL)
5055                 return -1;
5056         *pos2++ = '\0';
5057         dialog_token = atoi(pos);
5058
5059         len = os_strlen(pos2);
5060         if (len & 1)
5061                 return -1;
5062         len /= 2;
5063         resp_tlvs = wpabuf_alloc(len);
5064         if (resp_tlvs == NULL)
5065                 return -1;
5066         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
5067                 wpabuf_free(resp_tlvs);
5068                 return -1;
5069         }
5070
5071         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
5072         wpabuf_free(resp_tlvs);
5073         return 0;
5074 }
5075
5076
5077 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
5078                                        char *cmd)
5079 {
5080         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
5081                 return -1;
5082         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
5083         return 0;
5084 }
5085
5086
5087 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
5088                                         char *cmd)
5089 {
5090         char *pos;
5091         size_t len;
5092         struct wpabuf *query, *resp;
5093
5094         pos = os_strchr(cmd, ' ');
5095         if (pos == NULL)
5096                 return -1;
5097         *pos++ = '\0';
5098
5099         len = os_strlen(cmd);
5100         if (len & 1)
5101                 return -1;
5102         len /= 2;
5103         query = wpabuf_alloc(len);
5104         if (query == NULL)
5105                 return -1;
5106         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
5107                 wpabuf_free(query);
5108                 return -1;
5109         }
5110
5111         len = os_strlen(pos);
5112         if (len & 1) {
5113                 wpabuf_free(query);
5114                 return -1;
5115         }
5116         len /= 2;
5117         resp = wpabuf_alloc(len);
5118         if (resp == NULL) {
5119                 wpabuf_free(query);
5120                 return -1;
5121         }
5122         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
5123                 wpabuf_free(query);
5124                 wpabuf_free(resp);
5125                 return -1;
5126         }
5127
5128         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
5129                 wpabuf_free(query);
5130                 wpabuf_free(resp);
5131                 return -1;
5132         }
5133         return 0;
5134 }
5135
5136
5137 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
5138 {
5139         char *pos;
5140         u8 version;
5141
5142         pos = os_strchr(cmd, ' ');
5143         if (pos == NULL)
5144                 return -1;
5145         *pos++ = '\0';
5146
5147         if (hexstr2bin(cmd, &version, 1) < 0)
5148                 return -1;
5149
5150         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
5151 }
5152
5153
5154 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
5155                                     u8 replace, char *cmd)
5156 {
5157         char *pos;
5158         char *adv_str;
5159         u32 auto_accept, adv_id, svc_state, config_methods;
5160         char *svc_info = NULL;
5161
5162         pos = os_strchr(cmd, ' ');
5163         if (pos == NULL)
5164                 return -1;
5165         *pos++ = '\0';
5166
5167         /* Auto-Accept value is mandatory, and must be one of the
5168          * single values (0, 1, 2, 4) */
5169         auto_accept = atoi(cmd);
5170         switch (auto_accept) {
5171         case P2PS_SETUP_NONE: /* No auto-accept */
5172         case P2PS_SETUP_NEW:
5173         case P2PS_SETUP_CLIENT:
5174         case P2PS_SETUP_GROUP_OWNER:
5175                 break;
5176         default:
5177                 return -1;
5178         }
5179
5180         /* Advertisement ID is mandatory */
5181         cmd = pos;
5182         pos = os_strchr(cmd, ' ');
5183         if (pos == NULL)
5184                 return -1;
5185         *pos++ = '\0';
5186
5187         /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
5188         if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
5189                 return -1;
5190
5191         /* Only allow replacements if exist, and adds if not */
5192         if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
5193                 if (!replace)
5194                         return -1;
5195         } else {
5196                 if (replace)
5197                         return -1;
5198         }
5199
5200         /* svc_state between 0 - 0xff is mandatory */
5201         if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
5202                 return -1;
5203
5204         pos = os_strchr(pos, ' ');
5205         if (pos == NULL)
5206                 return -1;
5207
5208         /* config_methods is mandatory */
5209         pos++;
5210         if (sscanf(pos, "%x", &config_methods) != 1)
5211                 return -1;
5212
5213         if (!(config_methods &
5214               (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
5215                 return -1;
5216
5217         pos = os_strchr(pos, ' ');
5218         if (pos == NULL)
5219                 return -1;
5220
5221         pos++;
5222         adv_str = pos;
5223
5224         /* Advertisement string is mandatory */
5225         if (!pos[0] || pos[0] == ' ')
5226                 return -1;
5227
5228         /* Terminate svc string */
5229         pos = os_strchr(pos, ' ');
5230         if (pos != NULL)
5231                 *pos++ = '\0';
5232
5233         /* Service and Response Information are optional */
5234         if (pos && pos[0]) {
5235                 size_t len;
5236
5237                 /* Note the bare ' included, which cannot exist legally
5238                  * in unescaped string. */
5239                 svc_info = os_strstr(pos, "svc_info='");
5240
5241                 if (svc_info) {
5242                         svc_info += 9;
5243                         len = os_strlen(svc_info);
5244                         utf8_unescape(svc_info, len, svc_info, len);
5245                 }
5246         }
5247
5248         return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
5249                                         (u8) svc_state, (u16) config_methods,
5250                                         svc_info);
5251 }
5252
5253
5254 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
5255 {
5256         char *pos;
5257
5258         pos = os_strchr(cmd, ' ');
5259         if (pos == NULL)
5260                 return -1;
5261         *pos++ = '\0';
5262
5263         if (os_strcmp(cmd, "bonjour") == 0)
5264                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
5265         if (os_strcmp(cmd, "upnp") == 0)
5266                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
5267         if (os_strcmp(cmd, "asp") == 0)
5268                 return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
5269         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
5270         return -1;
5271 }
5272
5273
5274 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
5275                                         char *cmd)
5276 {
5277         size_t len;
5278         struct wpabuf *query;
5279         int ret;
5280
5281         len = os_strlen(cmd);
5282         if (len & 1)
5283                 return -1;
5284         len /= 2;
5285         query = wpabuf_alloc(len);
5286         if (query == NULL)
5287                 return -1;
5288         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
5289                 wpabuf_free(query);
5290                 return -1;
5291         }
5292
5293         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
5294         wpabuf_free(query);
5295         return ret;
5296 }
5297
5298
5299 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
5300 {
5301         char *pos;
5302         u8 version;
5303
5304         pos = os_strchr(cmd, ' ');
5305         if (pos == NULL)
5306                 return -1;
5307         *pos++ = '\0';
5308
5309         if (hexstr2bin(cmd, &version, 1) < 0)
5310                 return -1;
5311
5312         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
5313 }
5314
5315
5316 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
5317 {
5318         u32 adv_id;
5319
5320         if (os_strcmp(cmd, "all") == 0) {
5321                 wpas_p2p_service_flush_asp(wpa_s);
5322                 return 0;
5323         }
5324
5325         if (sscanf(cmd, "%x", &adv_id) != 1)
5326                 return -1;
5327
5328         return wpas_p2p_service_del_asp(wpa_s, adv_id);
5329 }
5330
5331
5332 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
5333 {
5334         char *pos;
5335
5336         pos = os_strchr(cmd, ' ');
5337         if (pos == NULL)
5338                 return -1;
5339         *pos++ = '\0';
5340
5341         if (os_strcmp(cmd, "bonjour") == 0)
5342                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
5343         if (os_strcmp(cmd, "upnp") == 0)
5344                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
5345         if (os_strcmp(cmd, "asp") == 0)
5346                 return p2p_ctrl_service_del_asp(wpa_s, pos);
5347         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
5348         return -1;
5349 }
5350
5351
5352 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
5353 {
5354         char *pos;
5355
5356         pos = os_strchr(cmd, ' ');
5357         if (pos == NULL)
5358                 return -1;
5359         *pos++ = '\0';
5360
5361         if (os_strcmp(cmd, "asp") == 0)
5362                 return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
5363
5364         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
5365         return -1;
5366 }
5367
5368
5369 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
5370 {
5371         u8 addr[ETH_ALEN];
5372
5373         /* <addr> */
5374
5375         if (hwaddr_aton(cmd, addr))
5376                 return -1;
5377
5378         return wpas_p2p_reject(wpa_s, addr);
5379 }
5380
5381
5382 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
5383 {
5384         char *pos;
5385         int id;
5386         struct wpa_ssid *ssid;
5387         u8 *_peer = NULL, peer[ETH_ALEN];
5388         int freq = 0, pref_freq = 0;
5389         int ht40, vht;
5390
5391         id = atoi(cmd);
5392         pos = os_strstr(cmd, " peer=");
5393         if (pos) {
5394                 pos += 6;
5395                 if (hwaddr_aton(pos, peer))
5396                         return -1;
5397                 _peer = peer;
5398         }
5399         ssid = wpa_config_get_network(wpa_s->conf, id);
5400         if (ssid == NULL || ssid->disabled != 2) {
5401                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
5402                            "for persistent P2P group",
5403                            id);
5404                 return -1;
5405         }
5406
5407         pos = os_strstr(cmd, " freq=");
5408         if (pos) {
5409                 pos += 6;
5410                 freq = atoi(pos);
5411                 if (freq <= 0)
5412                         return -1;
5413         }
5414
5415         pos = os_strstr(cmd, " pref=");
5416         if (pos) {
5417                 pos += 6;
5418                 pref_freq = atoi(pos);
5419                 if (pref_freq <= 0)
5420                         return -1;
5421         }
5422
5423         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
5424         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
5425                 vht;
5426
5427         return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
5428                                pref_freq);
5429 }
5430
5431
5432 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
5433 {
5434         char *pos;
5435         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
5436
5437         pos = os_strstr(cmd, " peer=");
5438         if (!pos)
5439                 return -1;
5440
5441         *pos = '\0';
5442         pos += 6;
5443         if (hwaddr_aton(pos, peer)) {
5444                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
5445                 return -1;
5446         }
5447
5448         pos = os_strstr(pos, " go_dev_addr=");
5449         if (pos) {
5450                 pos += 13;
5451                 if (hwaddr_aton(pos, go_dev_addr)) {
5452                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
5453                                    pos);
5454                         return -1;
5455                 }
5456                 go_dev = go_dev_addr;
5457         }
5458
5459         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
5460 }
5461
5462
5463 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
5464 {
5465         if (os_strncmp(cmd, "persistent=", 11) == 0)
5466                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
5467         if (os_strncmp(cmd, "group=", 6) == 0)
5468                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
5469
5470         return -1;
5471 }
5472
5473
5474 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
5475                                          char *cmd, int freq, int ht40,
5476                                          int vht)
5477 {
5478         int id;
5479         struct wpa_ssid *ssid;
5480
5481         id = atoi(cmd);
5482         ssid = wpa_config_get_network(wpa_s->conf, id);
5483         if (ssid == NULL || ssid->disabled != 2) {
5484                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
5485                            "for persistent P2P group",
5486                            id);
5487                 return -1;
5488         }
5489
5490         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
5491                                              NULL, 0);
5492 }
5493
5494
5495 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
5496 {
5497         int freq = 0, ht40, vht;
5498         char *pos;
5499
5500         pos = os_strstr(cmd, "freq=");
5501         if (pos)
5502                 freq = atoi(pos + 5);
5503
5504         vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
5505         ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
5506                 vht;
5507
5508         if (os_strncmp(cmd, "persistent=", 11) == 0)
5509                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
5510                                                      ht40, vht);
5511         if (os_strcmp(cmd, "persistent") == 0 ||
5512             os_strncmp(cmd, "persistent ", 11) == 0)
5513                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
5514         if (os_strncmp(cmd, "freq=", 5) == 0)
5515                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
5516         if (ht40)
5517                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
5518
5519         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
5520                    cmd);
5521         return -1;
5522 }
5523
5524
5525 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
5526                          char *buf, size_t buflen)
5527 {
5528         u8 addr[ETH_ALEN], *addr_ptr;
5529         int next, res;
5530         const struct p2p_peer_info *info;
5531         char *pos, *end;
5532         char devtype[WPS_DEV_TYPE_BUFSIZE];
5533         struct wpa_ssid *ssid;
5534         size_t i;
5535
5536         if (!wpa_s->global->p2p)
5537                 return -1;
5538
5539         if (os_strcmp(cmd, "FIRST") == 0) {
5540                 addr_ptr = NULL;
5541                 next = 0;
5542         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
5543                 if (hwaddr_aton(cmd + 5, addr) < 0)
5544                         return -1;
5545                 addr_ptr = addr;
5546                 next = 1;
5547         } else {
5548                 if (hwaddr_aton(cmd, addr) < 0)
5549                         return -1;
5550                 addr_ptr = addr;
5551                 next = 0;
5552         }
5553
5554         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
5555         if (info == NULL)
5556                 return -1;
5557
5558         pos = buf;
5559         end = buf + buflen;
5560
5561         res = os_snprintf(pos, end - pos, MACSTR "\n"
5562                           "pri_dev_type=%s\n"
5563                           "device_name=%s\n"
5564                           "manufacturer=%s\n"
5565                           "model_name=%s\n"
5566                           "model_number=%s\n"
5567                           "serial_number=%s\n"
5568                           "config_methods=0x%x\n"
5569                           "dev_capab=0x%x\n"
5570                           "group_capab=0x%x\n"
5571                           "level=%d\n",
5572                           MAC2STR(info->p2p_device_addr),
5573                           wps_dev_type_bin2str(info->pri_dev_type,
5574                                                devtype, sizeof(devtype)),
5575                           info->device_name,
5576                           info->manufacturer,
5577                           info->model_name,
5578                           info->model_number,
5579                           info->serial_number,
5580                           info->config_methods,
5581                           info->dev_capab,
5582                           info->group_capab,
5583                           info->level);
5584         if (os_snprintf_error(end - pos, res))
5585                 return pos - buf;
5586         pos += res;
5587
5588         for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
5589         {
5590                 const u8 *t;
5591                 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
5592                 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
5593                                   wps_dev_type_bin2str(t, devtype,
5594                                                        sizeof(devtype)));
5595                 if (os_snprintf_error(end - pos, res))
5596                         return pos - buf;
5597                 pos += res;
5598         }
5599
5600         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
5601         if (ssid) {
5602                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
5603                 if (os_snprintf_error(end - pos, res))
5604                         return pos - buf;
5605                 pos += res;
5606         }
5607
5608         res = p2p_get_peer_info_txt(info, pos, end - pos);
5609         if (res < 0)
5610                 return pos - buf;
5611         pos += res;
5612
5613         if (info->vendor_elems) {
5614                 res = os_snprintf(pos, end - pos, "vendor_elems=");
5615                 if (os_snprintf_error(end - pos, res))
5616                         return pos - buf;
5617                 pos += res;
5618
5619                 pos += wpa_snprintf_hex(pos, end - pos,
5620                                         wpabuf_head(info->vendor_elems),
5621                                         wpabuf_len(info->vendor_elems));
5622
5623                 res = os_snprintf(pos, end - pos, "\n");
5624                 if (os_snprintf_error(end - pos, res))
5625                         return pos - buf;
5626                 pos += res;
5627         }
5628
5629         return pos - buf;
5630 }
5631
5632
5633 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
5634                                   const char *param)
5635 {
5636         unsigned int i;
5637
5638         if (wpa_s->global->p2p == NULL)
5639                 return -1;
5640
5641         if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
5642                 return -1;
5643
5644         for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
5645                 struct wpa_freq_range *freq;
5646                 freq = &wpa_s->global->p2p_disallow_freq.range[i];
5647                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
5648                            freq->min, freq->max);
5649         }
5650
5651         wpas_p2p_update_channel_list(wpa_s);
5652         return 0;
5653 }
5654
5655
5656 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
5657 {
5658         char *param;
5659
5660         if (wpa_s->global->p2p == NULL)
5661                 return -1;
5662
5663         param = os_strchr(cmd, ' ');
5664         if (param == NULL)
5665                 return -1;
5666         *param++ = '\0';
5667
5668         if (os_strcmp(cmd, "discoverability") == 0) {
5669                 p2p_set_client_discoverability(wpa_s->global->p2p,
5670                                                atoi(param));
5671                 return 0;
5672         }
5673
5674         if (os_strcmp(cmd, "managed") == 0) {
5675                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
5676                 return 0;
5677         }
5678
5679         if (os_strcmp(cmd, "listen_channel") == 0) {
5680                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
5681                                               atoi(param), 1);
5682         }
5683
5684         if (os_strcmp(cmd, "ssid_postfix") == 0) {
5685                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
5686                                             os_strlen(param));
5687         }
5688
5689         if (os_strcmp(cmd, "noa") == 0) {
5690                 char *pos;
5691                 int count, start, duration;
5692                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
5693                 count = atoi(param);
5694                 pos = os_strchr(param, ',');
5695                 if (pos == NULL)
5696                         return -1;
5697                 pos++;
5698                 start = atoi(pos);
5699                 pos = os_strchr(pos, ',');
5700                 if (pos == NULL)
5701                         return -1;
5702                 pos++;
5703                 duration = atoi(pos);
5704                 if (count < 0 || count > 255 || start < 0 || duration < 0)
5705                         return -1;
5706                 if (count == 0 && duration > 0)
5707                         return -1;
5708                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
5709                            "start=%d duration=%d", count, start, duration);
5710                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
5711         }
5712
5713         if (os_strcmp(cmd, "ps") == 0)
5714                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
5715
5716         if (os_strcmp(cmd, "oppps") == 0)
5717                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
5718
5719         if (os_strcmp(cmd, "ctwindow") == 0)
5720                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
5721
5722         if (os_strcmp(cmd, "disabled") == 0) {
5723                 wpa_s->global->p2p_disabled = atoi(param);
5724                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
5725                            wpa_s->global->p2p_disabled ?
5726                            "disabled" : "enabled");
5727                 if (wpa_s->global->p2p_disabled) {
5728                         wpas_p2p_stop_find(wpa_s);
5729                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
5730                         p2p_flush(wpa_s->global->p2p);
5731                 }
5732                 return 0;
5733         }
5734
5735         if (os_strcmp(cmd, "conc_pref") == 0) {
5736                 if (os_strcmp(param, "sta") == 0)
5737                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
5738                 else if (os_strcmp(param, "p2p") == 0)
5739                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
5740                 else {
5741                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
5742                         return -1;
5743                 }
5744                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
5745                            "%s", param);
5746                 return 0;
5747         }
5748
5749         if (os_strcmp(cmd, "force_long_sd") == 0) {
5750                 wpa_s->force_long_sd = atoi(param);
5751                 return 0;
5752         }
5753
5754         if (os_strcmp(cmd, "peer_filter") == 0) {
5755                 u8 addr[ETH_ALEN];
5756                 if (hwaddr_aton(param, addr))
5757                         return -1;
5758                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
5759                 return 0;
5760         }
5761
5762         if (os_strcmp(cmd, "cross_connect") == 0)
5763                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
5764
5765         if (os_strcmp(cmd, "go_apsd") == 0) {
5766                 if (os_strcmp(param, "disable") == 0)
5767                         wpa_s->set_ap_uapsd = 0;
5768                 else {
5769                         wpa_s->set_ap_uapsd = 1;
5770                         wpa_s->ap_uapsd = atoi(param);
5771                 }
5772                 return 0;
5773         }
5774
5775         if (os_strcmp(cmd, "client_apsd") == 0) {
5776                 if (os_strcmp(param, "disable") == 0)
5777                         wpa_s->set_sta_uapsd = 0;
5778                 else {
5779                         int be, bk, vi, vo;
5780                         char *pos;
5781                         /* format: BE,BK,VI,VO;max SP Length */
5782                         be = atoi(param);
5783                         pos = os_strchr(param, ',');
5784                         if (pos == NULL)
5785                                 return -1;
5786                         pos++;
5787                         bk = atoi(pos);
5788                         pos = os_strchr(pos, ',');
5789                         if (pos == NULL)
5790                                 return -1;
5791                         pos++;
5792                         vi = atoi(pos);
5793                         pos = os_strchr(pos, ',');
5794                         if (pos == NULL)
5795                                 return -1;
5796                         pos++;
5797                         vo = atoi(pos);
5798                         /* ignore max SP Length for now */
5799
5800                         wpa_s->set_sta_uapsd = 1;
5801                         wpa_s->sta_uapsd = 0;
5802                         if (be)
5803                                 wpa_s->sta_uapsd |= BIT(0);
5804                         if (bk)
5805                                 wpa_s->sta_uapsd |= BIT(1);
5806                         if (vi)
5807                                 wpa_s->sta_uapsd |= BIT(2);
5808                         if (vo)
5809                                 wpa_s->sta_uapsd |= BIT(3);
5810                 }
5811                 return 0;
5812         }
5813
5814         if (os_strcmp(cmd, "disallow_freq") == 0)
5815                 return p2p_ctrl_disallow_freq(wpa_s, param);
5816
5817         if (os_strcmp(cmd, "disc_int") == 0) {
5818                 int min_disc_int, max_disc_int, max_disc_tu;
5819                 char *pos;
5820
5821                 pos = param;
5822
5823                 min_disc_int = atoi(pos);
5824                 pos = os_strchr(pos, ' ');
5825                 if (pos == NULL)
5826                         return -1;
5827                 *pos++ = '\0';
5828
5829                 max_disc_int = atoi(pos);
5830                 pos = os_strchr(pos, ' ');
5831                 if (pos == NULL)
5832                         return -1;
5833                 *pos++ = '\0';
5834
5835                 max_disc_tu = atoi(pos);
5836
5837                 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
5838                                         max_disc_int, max_disc_tu);
5839         }
5840
5841         if (os_strcmp(cmd, "per_sta_psk") == 0) {
5842                 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
5843                 return 0;
5844         }
5845
5846 #ifdef CONFIG_WPS_NFC
5847         if (os_strcmp(cmd, "nfc_tag") == 0)
5848                 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
5849 #endif /* CONFIG_WPS_NFC */
5850
5851         if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
5852                 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
5853                 return 0;
5854         }
5855
5856         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
5857                    cmd);
5858
5859         return -1;
5860 }
5861
5862
5863 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
5864 {
5865         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
5866         wpa_s->force_long_sd = 0;
5867         wpas_p2p_stop_find(wpa_s);
5868         if (wpa_s->global->p2p)
5869                 p2p_flush(wpa_s->global->p2p);
5870 }
5871
5872
5873 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
5874 {
5875         char *pos, *pos2;
5876         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
5877
5878         if (cmd[0]) {
5879                 pos = os_strchr(cmd, ' ');
5880                 if (pos == NULL)
5881                         return -1;
5882                 *pos++ = '\0';
5883                 dur1 = atoi(cmd);
5884
5885                 pos2 = os_strchr(pos, ' ');
5886                 if (pos2)
5887                         *pos2++ = '\0';
5888                 int1 = atoi(pos);
5889         } else
5890                 pos2 = NULL;
5891
5892         if (pos2) {
5893                 pos = os_strchr(pos2, ' ');
5894                 if (pos == NULL)
5895                         return -1;
5896                 *pos++ = '\0';
5897                 dur2 = atoi(pos2);
5898                 int2 = atoi(pos);
5899         }
5900
5901         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
5902 }
5903
5904
5905 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
5906 {
5907         char *pos;
5908         unsigned int period = 0, interval = 0;
5909
5910         if (cmd[0]) {
5911                 pos = os_strchr(cmd, ' ');
5912                 if (pos == NULL)
5913                         return -1;
5914                 *pos++ = '\0';
5915                 period = atoi(cmd);
5916                 interval = atoi(pos);
5917         }
5918
5919         return wpas_p2p_ext_listen(wpa_s, period, interval);
5920 }
5921
5922
5923 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
5924 {
5925         const char *pos;
5926         u8 peer[ETH_ALEN];
5927         int iface_addr = 0;
5928
5929         pos = cmd;
5930         if (os_strncmp(pos, "iface=", 6) == 0) {
5931                 iface_addr = 1;
5932                 pos += 6;
5933         }
5934         if (hwaddr_aton(pos, peer))
5935                 return -1;
5936
5937         wpas_p2p_remove_client(wpa_s, peer, iface_addr);
5938         return 0;
5939 }
5940
5941 #endif /* CONFIG_P2P */
5942
5943
5944 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
5945 {
5946         struct wpa_freq_range_list ranges;
5947         int *freqs = NULL;
5948         struct hostapd_hw_modes *mode;
5949         u16 i;
5950
5951         if (wpa_s->hw.modes == NULL)
5952                 return NULL;
5953
5954         os_memset(&ranges, 0, sizeof(ranges));
5955         if (freq_range_list_parse(&ranges, val) < 0)
5956                 return NULL;
5957
5958         for (i = 0; i < wpa_s->hw.num_modes; i++) {
5959                 int j;
5960
5961                 mode = &wpa_s->hw.modes[i];
5962                 for (j = 0; j < mode->num_channels; j++) {
5963                         unsigned int freq;
5964
5965                         if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
5966                                 continue;
5967
5968                         freq = mode->channels[j].freq;
5969                         if (!freq_range_list_includes(&ranges, freq))
5970                                 continue;
5971
5972                         int_array_add_unique(&freqs, freq);
5973                 }
5974         }
5975
5976         os_free(ranges.range);
5977         return freqs;
5978 }
5979
5980
5981 #ifdef CONFIG_INTERWORKING
5982
5983 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
5984 {
5985         int auto_sel = 0;
5986         int *freqs = NULL;
5987
5988         if (param) {
5989                 char *pos;
5990
5991                 auto_sel = os_strstr(param, "auto") != NULL;
5992
5993                 pos = os_strstr(param, "freq=");
5994                 if (pos) {
5995                         freqs = freq_range_to_channel_list(wpa_s, pos + 5);
5996                         if (freqs == NULL)
5997                                 return -1;
5998                 }
5999
6000         }
6001
6002         return interworking_select(wpa_s, auto_sel, freqs);
6003 }
6004
6005
6006 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst,
6007                                      int only_add)
6008 {
6009         u8 bssid[ETH_ALEN];
6010         struct wpa_bss *bss;
6011
6012         if (hwaddr_aton(dst, bssid)) {
6013                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
6014                 return -1;
6015         }
6016
6017         bss = wpa_bss_get_bssid(wpa_s, bssid);
6018         if (bss == NULL) {
6019                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
6020                            MAC2STR(bssid));
6021                 return -1;
6022         }
6023
6024         if (bss->ssid_len == 0) {
6025                 int found = 0;
6026
6027                 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR
6028                            " does not have SSID information", MAC2STR(bssid));
6029
6030                 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss,
6031                                          list) {
6032                         if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
6033                             bss->ssid_len > 0) {
6034                                 found = 1;
6035                                 break;
6036                         }
6037                 }
6038
6039                 if (!found)
6040                         return -1;
6041                 wpa_printf(MSG_DEBUG,
6042                            "Found another matching BSS entry with SSID");
6043         }
6044
6045         return interworking_connect(wpa_s, bss, only_add);
6046 }
6047
6048
6049 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
6050 {
6051         u8 dst_addr[ETH_ALEN];
6052         int used;
6053         char *pos;
6054 #define MAX_ANQP_INFO_ID 100
6055         u16 id[MAX_ANQP_INFO_ID];
6056         size_t num_id = 0;
6057         u32 subtypes = 0;
6058
6059         used = hwaddr_aton2(dst, dst_addr);
6060         if (used < 0)
6061                 return -1;
6062         pos = dst + used;
6063         if (*pos == ' ')
6064                 pos++;
6065         while (num_id < MAX_ANQP_INFO_ID) {
6066                 if (os_strncmp(pos, "hs20:", 5) == 0) {
6067 #ifdef CONFIG_HS20
6068                         int num = atoi(pos + 5);
6069                         if (num <= 0 || num > 31)
6070                                 return -1;
6071                         subtypes |= BIT(num);
6072 #else /* CONFIG_HS20 */
6073                         return -1;
6074 #endif /* CONFIG_HS20 */
6075                 } else {
6076                         id[num_id] = atoi(pos);
6077                         if (id[num_id])
6078                                 num_id++;
6079                 }
6080                 pos = os_strchr(pos + 1, ',');
6081                 if (pos == NULL)
6082                         break;
6083                 pos++;
6084         }
6085
6086         if (num_id == 0)
6087                 return -1;
6088
6089         return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
6090 }
6091
6092
6093 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
6094 {
6095         u8 dst_addr[ETH_ALEN];
6096         struct wpabuf *advproto, *query = NULL;
6097         int used, ret = -1;
6098         char *pos, *end;
6099         size_t len;
6100
6101         used = hwaddr_aton2(cmd, dst_addr);
6102         if (used < 0)
6103                 return -1;
6104
6105         pos = cmd + used;
6106         while (*pos == ' ')
6107                 pos++;
6108
6109         /* Advertisement Protocol ID */
6110         end = os_strchr(pos, ' ');
6111         if (end)
6112                 len = end - pos;
6113         else
6114                 len = os_strlen(pos);
6115         if (len & 0x01)
6116                 return -1;
6117         len /= 2;
6118         if (len == 0)
6119                 return -1;
6120         advproto = wpabuf_alloc(len);
6121         if (advproto == NULL)
6122                 return -1;
6123         if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
6124                 goto fail;
6125
6126         if (end) {
6127                 /* Optional Query Request */
6128                 pos = end + 1;
6129                 while (*pos == ' ')
6130                         pos++;
6131
6132                 len = os_strlen(pos);
6133                 if (len) {
6134                         if (len & 0x01)
6135                                 goto fail;
6136                         len /= 2;
6137                         if (len == 0)
6138                                 goto fail;
6139                         query = wpabuf_alloc(len);
6140                         if (query == NULL)
6141                                 goto fail;
6142                         if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
6143                                 goto fail;
6144                 }
6145         }
6146
6147         ret = gas_send_request(wpa_s, dst_addr, advproto, query);
6148
6149 fail:
6150         wpabuf_free(advproto);
6151         wpabuf_free(query);
6152
6153         return ret;
6154 }
6155
6156
6157 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
6158                             size_t buflen)
6159 {
6160         u8 addr[ETH_ALEN];
6161         int dialog_token;
6162         int used;
6163         char *pos;
6164         size_t resp_len, start, requested_len;
6165         struct wpabuf *resp;
6166         int ret;
6167
6168         used = hwaddr_aton2(cmd, addr);
6169         if (used < 0)
6170                 return -1;
6171
6172         pos = cmd + used;
6173         while (*pos == ' ')
6174                 pos++;
6175         dialog_token = atoi(pos);
6176
6177         if (wpa_s->last_gas_resp &&
6178             os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
6179             dialog_token == wpa_s->last_gas_dialog_token)
6180                 resp = wpa_s->last_gas_resp;
6181         else if (wpa_s->prev_gas_resp &&
6182                  os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
6183                  dialog_token == wpa_s->prev_gas_dialog_token)
6184                 resp = wpa_s->prev_gas_resp;
6185         else
6186                 return -1;
6187
6188         resp_len = wpabuf_len(resp);
6189         start = 0;
6190         requested_len = resp_len;
6191
6192         pos = os_strchr(pos, ' ');
6193         if (pos) {
6194                 start = atoi(pos);
6195                 if (start > resp_len)
6196                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
6197                 pos = os_strchr(pos, ',');
6198                 if (pos == NULL)
6199                         return -1;
6200                 pos++;
6201                 requested_len = atoi(pos);
6202                 if (start + requested_len > resp_len)
6203                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
6204         }
6205
6206         if (requested_len * 2 + 1 > buflen)
6207                 return os_snprintf(buf, buflen, "FAIL-Too long response");
6208
6209         ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
6210                                requested_len);
6211
6212         if (start + requested_len == resp_len) {
6213                 /*
6214                  * Free memory by dropping the response after it has been
6215                  * fetched.
6216                  */
6217                 if (resp == wpa_s->prev_gas_resp) {
6218                         wpabuf_free(wpa_s->prev_gas_resp);
6219                         wpa_s->prev_gas_resp = NULL;
6220                 } else {
6221                         wpabuf_free(wpa_s->last_gas_resp);
6222                         wpa_s->last_gas_resp = NULL;
6223                 }
6224         }
6225
6226         return ret;
6227 }
6228 #endif /* CONFIG_INTERWORKING */
6229
6230
6231 #ifdef CONFIG_HS20
6232
6233 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
6234 {
6235         u8 dst_addr[ETH_ALEN];
6236         int used;
6237         char *pos;
6238         u32 subtypes = 0;
6239
6240         used = hwaddr_aton2(dst, dst_addr);
6241         if (used < 0)
6242                 return -1;
6243         pos = dst + used;
6244         if (*pos == ' ')
6245                 pos++;
6246         for (;;) {
6247                 int num = atoi(pos);
6248                 if (num <= 0 || num > 31)
6249                         return -1;
6250                 subtypes |= BIT(num);
6251                 pos = os_strchr(pos + 1, ',');
6252                 if (pos == NULL)
6253                         break;
6254                 pos++;
6255         }
6256
6257         if (subtypes == 0)
6258                 return -1;
6259
6260         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
6261 }
6262
6263
6264 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
6265                                     const u8 *addr, const char *realm)
6266 {
6267         u8 *buf;
6268         size_t rlen, len;
6269         int ret;
6270
6271         rlen = os_strlen(realm);
6272         len = 3 + rlen;
6273         buf = os_malloc(len);
6274         if (buf == NULL)
6275                 return -1;
6276         buf[0] = 1; /* NAI Home Realm Count */
6277         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
6278         buf[2] = rlen;
6279         os_memcpy(buf + 3, realm, rlen);
6280
6281         ret = hs20_anqp_send_req(wpa_s, addr,
6282                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
6283                                  buf, len);
6284
6285         os_free(buf);
6286
6287         return ret;
6288 }
6289
6290
6291 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
6292                                         char *dst)
6293 {
6294         struct wpa_cred *cred = wpa_s->conf->cred;
6295         u8 dst_addr[ETH_ALEN];
6296         int used;
6297         u8 *buf;
6298         size_t len;
6299         int ret;
6300
6301         used = hwaddr_aton2(dst, dst_addr);
6302         if (used < 0)
6303                 return -1;
6304
6305         while (dst[used] == ' ')
6306                 used++;
6307         if (os_strncmp(dst + used, "realm=", 6) == 0)
6308                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
6309                                                 dst + used + 6);
6310
6311         len = os_strlen(dst + used);
6312
6313         if (len == 0 && cred && cred->realm)
6314                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
6315
6316         if (len & 1)
6317                 return -1;
6318         len /= 2;
6319         buf = os_malloc(len);
6320         if (buf == NULL)
6321                 return -1;
6322         if (hexstr2bin(dst + used, buf, len) < 0) {
6323                 os_free(buf);
6324                 return -1;
6325         }
6326
6327         ret = hs20_anqp_send_req(wpa_s, dst_addr,
6328                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
6329                                  buf, len);
6330         os_free(buf);
6331
6332         return ret;
6333 }
6334
6335
6336 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
6337 {
6338         u8 dst_addr[ETH_ALEN];
6339         int used;
6340         char *icon;
6341
6342         used = hwaddr_aton2(cmd, dst_addr);
6343         if (used < 0)
6344                 return -1;
6345
6346         while (cmd[used] == ' ')
6347                 used++;
6348         icon = &cmd[used];
6349
6350         wpa_s->fetch_osu_icon_in_progress = 0;
6351         return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
6352                                   (u8 *) icon, os_strlen(icon));
6353 }
6354
6355 #endif /* CONFIG_HS20 */
6356
6357
6358 #ifdef CONFIG_AUTOSCAN
6359
6360 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
6361                                               char *cmd)
6362 {
6363         enum wpa_states state = wpa_s->wpa_state;
6364         char *new_params = NULL;
6365
6366         if (os_strlen(cmd) > 0) {
6367                 new_params = os_strdup(cmd);
6368                 if (new_params == NULL)
6369                         return -1;
6370         }
6371
6372         os_free(wpa_s->conf->autoscan);
6373         wpa_s->conf->autoscan = new_params;
6374
6375         if (wpa_s->conf->autoscan == NULL)
6376                 autoscan_deinit(wpa_s);
6377         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
6378                 autoscan_init(wpa_s, 1);
6379         else if (state == WPA_SCANNING)
6380                 wpa_supplicant_reinit_autoscan(wpa_s);
6381
6382         return 0;
6383 }
6384
6385 #endif /* CONFIG_AUTOSCAN */
6386
6387
6388 #ifdef CONFIG_WNM
6389
6390 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
6391 {
6392         int enter;
6393         int intval = 0;
6394         char *pos;
6395         int ret;
6396         struct wpabuf *tfs_req = NULL;
6397
6398         if (os_strncmp(cmd, "enter", 5) == 0)
6399                 enter = 1;
6400         else if (os_strncmp(cmd, "exit", 4) == 0)
6401                 enter = 0;
6402         else
6403                 return -1;
6404
6405         pos = os_strstr(cmd, " interval=");
6406         if (pos)
6407                 intval = atoi(pos + 10);
6408
6409         pos = os_strstr(cmd, " tfs_req=");
6410         if (pos) {
6411                 char *end;
6412                 size_t len;
6413                 pos += 9;
6414                 end = os_strchr(pos, ' ');
6415                 if (end)
6416                         len = end - pos;
6417                 else
6418                         len = os_strlen(pos);
6419                 if (len & 1)
6420                         return -1;
6421                 len /= 2;
6422                 tfs_req = wpabuf_alloc(len);
6423                 if (tfs_req == NULL)
6424                         return -1;
6425                 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
6426                         wpabuf_free(tfs_req);
6427                         return -1;
6428                 }
6429         }
6430
6431         ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
6432                                            WNM_SLEEP_MODE_EXIT, intval,
6433                                            tfs_req);
6434         wpabuf_free(tfs_req);
6435
6436         return ret;
6437 }
6438
6439
6440 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
6441 {
6442         int query_reason;
6443
6444         query_reason = atoi(cmd);
6445
6446         wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
6447                    query_reason);
6448
6449         return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
6450 }
6451
6452 #endif /* CONFIG_WNM */
6453
6454
6455 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
6456                                       size_t buflen)
6457 {
6458         struct wpa_signal_info si;
6459         int ret;
6460         char *pos, *end;
6461
6462         ret = wpa_drv_signal_poll(wpa_s, &si);
6463         if (ret)
6464                 return -1;
6465
6466         pos = buf;
6467         end = buf + buflen;
6468
6469         ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
6470                           "NOISE=%d\nFREQUENCY=%u\n",
6471                           si.current_signal, si.current_txrate / 1000,
6472                           si.current_noise, si.frequency);
6473         if (os_snprintf_error(end - pos, ret))
6474                 return -1;
6475         pos += ret;
6476
6477         if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
6478                 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
6479                                   channel_width_to_string(si.chanwidth));
6480                 if (os_snprintf_error(end - pos, ret))
6481                         return -1;
6482                 pos += ret;
6483         }
6484
6485         if (si.center_frq1 > 0 && si.center_frq2 > 0) {
6486                 ret = os_snprintf(pos, end - pos,
6487                                   "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
6488                                   si.center_frq1, si.center_frq2);
6489                 if (os_snprintf_error(end - pos, ret))
6490                         return -1;
6491                 pos += ret;
6492         }
6493
6494         if (si.avg_signal) {
6495                 ret = os_snprintf(pos, end - pos,
6496                                   "AVG_RSSI=%d\n", si.avg_signal);
6497                 if (os_snprintf_error(end - pos, ret))
6498                         return -1;
6499                 pos += ret;
6500         }
6501
6502         if (si.avg_beacon_signal) {
6503                 ret = os_snprintf(pos, end - pos,
6504                                   "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal);
6505                 if (os_snprintf_error(end - pos, ret))
6506                         return -1;
6507                 pos += ret;
6508         }
6509
6510         return pos - buf;
6511 }
6512
6513
6514 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
6515                                       size_t buflen)
6516 {
6517         struct hostap_sta_driver_data sta;
6518         int ret;
6519
6520         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
6521         if (ret)
6522                 return -1;
6523
6524         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
6525                           sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
6526         if (os_snprintf_error(buflen, ret))
6527                 return -1;
6528         return ret;
6529 }
6530
6531
6532 #ifdef ANDROID
6533 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
6534                                      char *buf, size_t buflen)
6535 {
6536         int ret;
6537
6538         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
6539         if (ret == 0) {
6540                 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
6541                         struct p2p_data *p2p = wpa_s->global->p2p;
6542                         if (p2p) {
6543                                 char country[3];
6544                                 country[0] = cmd[8];
6545                                 country[1] = cmd[9];
6546                                 country[2] = 0x04;
6547                                 p2p_set_country(p2p, country);
6548                         }
6549                 }
6550                 ret = os_snprintf(buf, buflen, "%s\n", "OK");
6551                 if (os_snprintf_error(buflen, ret))
6552                         ret = -1;
6553         }
6554         return ret;
6555 }
6556 #endif /* ANDROID */
6557
6558
6559 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
6560                                      char *buf, size_t buflen)
6561 {
6562         int ret;
6563         char *pos;
6564         u8 *data = NULL;
6565         unsigned int vendor_id, subcmd;
6566         struct wpabuf *reply;
6567         size_t data_len = 0;
6568
6569         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
6570         vendor_id = strtoul(cmd, &pos, 16);
6571         if (!isblank(*pos))
6572                 return -EINVAL;
6573
6574         subcmd = strtoul(pos, &pos, 10);
6575
6576         if (*pos != '\0') {
6577                 if (!isblank(*pos++))
6578                         return -EINVAL;
6579                 data_len = os_strlen(pos);
6580         }
6581
6582         if (data_len) {
6583                 data_len /= 2;
6584                 data = os_malloc(data_len);
6585                 if (!data)
6586                         return -1;
6587
6588                 if (hexstr2bin(pos, data, data_len)) {
6589                         wpa_printf(MSG_DEBUG,
6590                                    "Vendor command: wrong parameter format");
6591                         os_free(data);
6592                         return -EINVAL;
6593                 }
6594         }
6595
6596         reply = wpabuf_alloc((buflen - 1) / 2);
6597         if (!reply) {
6598                 os_free(data);
6599                 return -1;
6600         }
6601
6602         ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
6603                                  reply);
6604
6605         if (ret == 0)
6606                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
6607                                        wpabuf_len(reply));
6608
6609         wpabuf_free(reply);
6610         os_free(data);
6611
6612         return ret;
6613 }
6614
6615
6616 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
6617 {
6618 #ifdef CONFIG_P2P
6619         struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ?
6620                 wpa_s->global->p2p_init_wpa_s : wpa_s;
6621 #endif /* CONFIG_P2P */
6622
6623         wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
6624
6625 #ifdef CONFIG_P2P
6626         wpas_p2p_cancel(p2p_wpa_s);
6627         p2p_ctrl_flush(p2p_wpa_s);
6628         wpas_p2p_group_remove(p2p_wpa_s, "*");
6629         wpas_p2p_service_flush(p2p_wpa_s);
6630         p2p_wpa_s->global->p2p_disabled = 0;
6631         p2p_wpa_s->global->p2p_per_sta_psk = 0;
6632         p2p_wpa_s->conf->num_sec_device_types = 0;
6633         p2p_wpa_s->p2p_disable_ip_addr_req = 0;
6634         os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range);
6635         p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
6636         p2p_wpa_s->global->pending_p2ps_group = 0;
6637 #endif /* CONFIG_P2P */
6638
6639 #ifdef CONFIG_WPS_TESTING
6640         wps_version_number = 0x20;
6641         wps_testing_dummy_cred = 0;
6642         wps_corrupt_pkhash = 0;
6643 #endif /* CONFIG_WPS_TESTING */
6644 #ifdef CONFIG_WPS
6645         wpa_s->wps_fragment_size = 0;
6646         wpas_wps_cancel(wpa_s);
6647         wps_registrar_flush(wpa_s->wps->registrar);
6648 #endif /* CONFIG_WPS */
6649         wpa_s->after_wps = 0;
6650         wpa_s->known_wps_freq = 0;
6651
6652 #ifdef CONFIG_TDLS
6653 #ifdef CONFIG_TDLS_TESTING
6654         extern unsigned int tdls_testing;
6655         tdls_testing = 0;
6656 #endif /* CONFIG_TDLS_TESTING */
6657         wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
6658         wpa_tdls_enable(wpa_s->wpa, 1);
6659 #endif /* CONFIG_TDLS */
6660
6661         eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
6662         wpa_supplicant_stop_countermeasures(wpa_s, NULL);
6663
6664         wpa_s->no_keep_alive = 0;
6665         wpa_s->own_disconnect_req = 0;
6666
6667         os_free(wpa_s->disallow_aps_bssid);
6668         wpa_s->disallow_aps_bssid = NULL;
6669         wpa_s->disallow_aps_bssid_count = 0;
6670         os_free(wpa_s->disallow_aps_ssid);
6671         wpa_s->disallow_aps_ssid = NULL;
6672         wpa_s->disallow_aps_ssid_count = 0;
6673
6674         wpa_s->set_sta_uapsd = 0;
6675         wpa_s->sta_uapsd = 0;
6676
6677         wpa_drv_radio_disable(wpa_s, 0);
6678         wpa_blacklist_clear(wpa_s);
6679         wpa_s->extra_blacklist_count = 0;
6680         wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
6681         wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
6682         wpa_config_flush_blobs(wpa_s->conf);
6683         wpa_s->conf->auto_interworking = 0;
6684         wpa_s->conf->okc = 0;
6685
6686         wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
6687         rsn_preauth_deinit(wpa_s->wpa);
6688
6689         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
6690         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
6691         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
6692         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
6693
6694         radio_remove_works(wpa_s, NULL, 1);
6695         wpa_s->ext_work_in_progress = 0;
6696
6697         wpa_s->next_ssid = NULL;
6698
6699 #ifdef CONFIG_INTERWORKING
6700         hs20_cancel_fetch_osu(wpa_s);
6701 #endif /* CONFIG_INTERWORKING */
6702
6703         wpa_s->ext_mgmt_frame_handling = 0;
6704         wpa_s->ext_eapol_frame_io = 0;
6705 #ifdef CONFIG_TESTING_OPTIONS
6706         wpa_s->extra_roc_dur = 0;
6707         wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
6708 #endif /* CONFIG_TESTING_OPTIONS */
6709
6710         wpa_s->disconnected = 0;
6711         os_free(wpa_s->next_scan_freqs);
6712         wpa_s->next_scan_freqs = NULL;
6713
6714         wpa_bss_flush(wpa_s);
6715         if (!dl_list_empty(&wpa_s->bss)) {
6716                 wpa_printf(MSG_DEBUG,
6717                            "BSS table not empty after flush: %u entries, current_bss=%p bssid="
6718                            MACSTR " pending_bssid=" MACSTR,
6719                            dl_list_len(&wpa_s->bss), wpa_s->current_bss,
6720                            MAC2STR(wpa_s->bssid),
6721                            MAC2STR(wpa_s->pending_bssid));
6722         }
6723
6724         eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6725 }
6726
6727
6728 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
6729                                      char *buf, size_t buflen)
6730 {
6731         struct wpa_radio_work *work;
6732         char *pos, *end;
6733         struct os_reltime now, diff;
6734
6735         pos = buf;
6736         end = buf + buflen;
6737
6738         os_get_reltime(&now);
6739
6740         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
6741         {
6742                 int ret;
6743
6744                 os_reltime_sub(&now, &work->time, &diff);
6745                 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
6746                                   work->type, work->wpa_s->ifname, work->freq,
6747                                   work->started, diff.sec, diff.usec);
6748                 if (os_snprintf_error(end - pos, ret))
6749                         break;
6750                 pos += ret;
6751         }
6752
6753         return pos - buf;
6754 }
6755
6756
6757 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
6758 {
6759         struct wpa_radio_work *work = eloop_ctx;
6760         struct wpa_external_work *ework = work->ctx;
6761
6762         wpa_dbg(work->wpa_s, MSG_DEBUG,
6763                 "Timing out external radio work %u (%s)",
6764                 ework->id, work->type);
6765         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
6766         work->wpa_s->ext_work_in_progress = 0;
6767         radio_work_done(work);
6768         os_free(ework);
6769 }
6770
6771
6772 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
6773 {
6774         struct wpa_external_work *ework = work->ctx;
6775
6776         if (deinit) {
6777                 if (work->started)
6778                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
6779                                              work, NULL);
6780
6781                 os_free(ework);
6782                 return;
6783         }
6784
6785         wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
6786                 ework->id, ework->type);
6787         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
6788         work->wpa_s->ext_work_in_progress = 1;
6789         if (!ework->timeout)
6790                 ework->timeout = 10;
6791         eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
6792                                work, NULL);
6793 }
6794
6795
6796 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
6797                                     char *buf, size_t buflen)
6798 {
6799         struct wpa_external_work *ework;
6800         char *pos, *pos2;
6801         size_t type_len;
6802         int ret;
6803         unsigned int freq = 0;
6804
6805         /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
6806
6807         ework = os_zalloc(sizeof(*ework));
6808         if (ework == NULL)
6809                 return -1;
6810
6811         pos = os_strchr(cmd, ' ');
6812         if (pos) {
6813                 type_len = pos - cmd;
6814                 pos++;
6815
6816                 pos2 = os_strstr(pos, "freq=");
6817                 if (pos2)
6818                         freq = atoi(pos2 + 5);
6819
6820                 pos2 = os_strstr(pos, "timeout=");
6821                 if (pos2)
6822                         ework->timeout = atoi(pos2 + 8);
6823         } else {
6824                 type_len = os_strlen(cmd);
6825         }
6826         if (4 + type_len >= sizeof(ework->type))
6827                 type_len = sizeof(ework->type) - 4 - 1;
6828         os_strlcpy(ework->type, "ext:", sizeof(ework->type));
6829         os_memcpy(ework->type + 4, cmd, type_len);
6830         ework->type[4 + type_len] = '\0';
6831
6832         wpa_s->ext_work_id++;
6833         if (wpa_s->ext_work_id == 0)
6834                 wpa_s->ext_work_id++;
6835         ework->id = wpa_s->ext_work_id;
6836
6837         if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
6838                            ework) < 0) {
6839                 os_free(ework);
6840                 return -1;
6841         }
6842
6843         ret = os_snprintf(buf, buflen, "%u", ework->id);
6844         if (os_snprintf_error(buflen, ret))
6845                 return -1;
6846         return ret;
6847 }
6848
6849
6850 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
6851 {
6852         struct wpa_radio_work *work;
6853         unsigned int id = atoi(cmd);
6854
6855         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
6856         {
6857                 struct wpa_external_work *ework;
6858
6859                 if (os_strncmp(work->type, "ext:", 4) != 0)
6860                         continue;
6861                 ework = work->ctx;
6862                 if (id && ework->id != id)
6863                         continue;
6864                 wpa_dbg(wpa_s, MSG_DEBUG,
6865                         "Completed external radio work %u (%s)",
6866                         ework->id, ework->type);
6867                 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
6868                 wpa_s->ext_work_in_progress = 0;
6869                 radio_work_done(work);
6870                 os_free(ework);
6871                 return 3; /* "OK\n" */
6872         }
6873
6874         return -1;
6875 }
6876
6877
6878 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
6879                                 char *buf, size_t buflen)
6880 {
6881         if (os_strcmp(cmd, "show") == 0)
6882                 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
6883         if (os_strncmp(cmd, "add ", 4) == 0)
6884                 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
6885         if (os_strncmp(cmd, "done ", 5) == 0)
6886                 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
6887         return -1;
6888 }
6889
6890
6891 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
6892 {
6893         struct wpa_radio_work *work, *tmp;
6894
6895         if (!wpa_s || !wpa_s->radio)
6896                 return;
6897
6898         dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
6899                               struct wpa_radio_work, list) {
6900                 struct wpa_external_work *ework;
6901
6902                 if (os_strncmp(work->type, "ext:", 4) != 0)
6903                         continue;
6904                 ework = work->ctx;
6905                 wpa_dbg(wpa_s, MSG_DEBUG,
6906                         "Flushing%s external radio work %u (%s)",
6907                         work->started ? " started" : "", ework->id,
6908                         ework->type);
6909                 if (work->started)
6910                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
6911                                              work, NULL);
6912                 radio_work_done(work);
6913                 os_free(ework);
6914         }
6915 }
6916
6917
6918 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
6919 {
6920         struct wpa_supplicant *wpa_s = eloop_ctx;
6921         eapol_sm_notify_ctrl_response(wpa_s->eapol);
6922 }
6923
6924
6925 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value,
6926                               unsigned int *scan_id_count, int scan_id[])
6927 {
6928         const char *pos = value;
6929
6930         while (pos) {
6931                 if (*pos == ' ' || *pos == '\0')
6932                         break;
6933                 if (*scan_id_count == MAX_SCAN_ID)
6934                         return -1;
6935                 scan_id[(*scan_id_count)++] = atoi(pos);
6936                 pos = os_strchr(pos, ',');
6937                 if (pos)
6938                         pos++;
6939         }
6940
6941         return 0;
6942 }
6943
6944
6945 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
6946                            char *reply, int reply_size, int *reply_len)
6947 {
6948         char *pos;
6949         unsigned int manual_scan_passive = 0;
6950         unsigned int manual_scan_use_id = 0;
6951         unsigned int manual_scan_only_new = 0;
6952         unsigned int scan_only = 0;
6953         unsigned int scan_id_count = 0;
6954         int scan_id[MAX_SCAN_ID];
6955         void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
6956                                  struct wpa_scan_results *scan_res);
6957         int *manual_scan_freqs = NULL;
6958
6959         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
6960                 *reply_len = -1;
6961                 return;
6962         }
6963
6964         if (radio_work_pending(wpa_s, "scan")) {
6965                 wpa_printf(MSG_DEBUG,
6966                            "Pending scan scheduled - reject new request");
6967                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
6968                 return;
6969         }
6970
6971 #ifdef CONFIG_INTERWORKING
6972         if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
6973                 wpa_printf(MSG_DEBUG,
6974                            "Interworking select in progress - reject new scan");
6975                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
6976                 return;
6977         }
6978 #endif /* CONFIG_INTERWORKING */
6979
6980         if (params) {
6981                 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
6982                         scan_only = 1;
6983
6984                 pos = os_strstr(params, "freq=");
6985                 if (pos) {
6986                         manual_scan_freqs = freq_range_to_channel_list(wpa_s,
6987                                                                        pos + 5);
6988                         if (manual_scan_freqs == NULL) {
6989                                 *reply_len = -1;
6990                                 goto done;
6991                         }
6992                 }
6993
6994                 pos = os_strstr(params, "passive=");
6995                 if (pos)
6996                         manual_scan_passive = !!atoi(pos + 8);
6997
6998                 pos = os_strstr(params, "use_id=");
6999                 if (pos)
7000                         manual_scan_use_id = atoi(pos + 7);
7001
7002                 pos = os_strstr(params, "only_new=1");
7003                 if (pos)
7004                         manual_scan_only_new = 1;
7005
7006                 pos = os_strstr(params, "scan_id=");
7007                 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count,
7008                                               scan_id) < 0) {
7009                         *reply_len = -1;
7010                         goto done;
7011                 }
7012         }
7013
7014         if (scan_only)
7015                 scan_res_handler = scan_only_handler;
7016         else if (wpa_s->scan_res_handler == scan_only_handler)
7017                 scan_res_handler = NULL;
7018         else
7019                 scan_res_handler = wpa_s->scan_res_handler;
7020
7021         if (!wpa_s->sched_scanning && !wpa_s->scanning &&
7022             ((wpa_s->wpa_state <= WPA_SCANNING) ||
7023              (wpa_s->wpa_state == WPA_COMPLETED))) {
7024                 wpa_s->manual_scan_passive = manual_scan_passive;
7025                 wpa_s->manual_scan_use_id = manual_scan_use_id;
7026                 wpa_s->manual_scan_only_new = manual_scan_only_new;
7027                 wpa_s->scan_id_count = scan_id_count;
7028                 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
7029                 wpa_s->scan_res_handler = scan_res_handler;
7030                 os_free(wpa_s->manual_scan_freqs);
7031                 wpa_s->manual_scan_freqs = manual_scan_freqs;
7032                 manual_scan_freqs = NULL;
7033
7034                 wpa_s->normal_scans = 0;
7035                 wpa_s->scan_req = MANUAL_SCAN_REQ;
7036                 wpa_s->after_wps = 0;
7037                 wpa_s->known_wps_freq = 0;
7038                 wpa_supplicant_req_scan(wpa_s, 0, 0);
7039                 if (wpa_s->manual_scan_use_id) {
7040                         wpa_s->manual_scan_id++;
7041                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
7042                                 wpa_s->manual_scan_id);
7043                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
7044                                                  wpa_s->manual_scan_id);
7045                 }
7046         } else if (wpa_s->sched_scanning) {
7047                 wpa_s->manual_scan_passive = manual_scan_passive;
7048                 wpa_s->manual_scan_use_id = manual_scan_use_id;
7049                 wpa_s->manual_scan_only_new = manual_scan_only_new;
7050                 wpa_s->scan_id_count = scan_id_count;
7051                 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int));
7052                 wpa_s->scan_res_handler = scan_res_handler;
7053                 os_free(wpa_s->manual_scan_freqs);
7054                 wpa_s->manual_scan_freqs = manual_scan_freqs;
7055                 manual_scan_freqs = NULL;
7056
7057                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
7058                 wpa_supplicant_cancel_sched_scan(wpa_s);
7059                 wpa_s->scan_req = MANUAL_SCAN_REQ;
7060                 wpa_supplicant_req_scan(wpa_s, 0, 0);
7061                 if (wpa_s->manual_scan_use_id) {
7062                         wpa_s->manual_scan_id++;
7063                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
7064                                                  wpa_s->manual_scan_id);
7065                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
7066                                 wpa_s->manual_scan_id);
7067                 }
7068         } else {
7069                 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
7070                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
7071         }
7072
7073 done:
7074         os_free(manual_scan_freqs);
7075 }
7076
7077
7078 #ifdef CONFIG_TESTING_OPTIONS
7079
7080 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
7081                                        unsigned int freq, const u8 *dst,
7082                                        const u8 *src, const u8 *bssid,
7083                                        const u8 *data, size_t data_len,
7084                                        enum offchannel_send_action_result
7085                                        result)
7086 {
7087         wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
7088                 " src=" MACSTR " bssid=" MACSTR " result=%s",
7089                 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
7090                 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
7091                 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
7092                              "NO_ACK" : "FAILED"));
7093 }
7094
7095
7096 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
7097 {
7098         char *pos, *param;
7099         size_t len;
7100         u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
7101         int res, used;
7102         int freq = 0, no_cck = 0, wait_time = 0;
7103
7104         /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
7105          *    <action=Action frame payload> */
7106
7107         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
7108
7109         pos = cmd;
7110         used = hwaddr_aton2(pos, da);
7111         if (used < 0)
7112                 return -1;
7113         pos += used;
7114         while (*pos == ' ')
7115                 pos++;
7116         used = hwaddr_aton2(pos, bssid);
7117         if (used < 0)
7118                 return -1;
7119         pos += used;
7120
7121         param = os_strstr(pos, " freq=");
7122         if (param) {
7123                 param += 6;
7124                 freq = atoi(param);
7125         }
7126
7127         param = os_strstr(pos, " no_cck=");
7128         if (param) {
7129                 param += 8;
7130                 no_cck = atoi(param);
7131         }
7132
7133         param = os_strstr(pos, " wait_time=");
7134         if (param) {
7135                 param += 11;
7136                 wait_time = atoi(param);
7137         }
7138
7139         param = os_strstr(pos, " action=");
7140         if (param == NULL)
7141                 return -1;
7142         param += 8;
7143
7144         len = os_strlen(param);
7145         if (len & 1)
7146                 return -1;
7147         len /= 2;
7148
7149         buf = os_malloc(len);
7150         if (buf == NULL)
7151                 return -1;
7152
7153         if (hexstr2bin(param, buf, len) < 0) {
7154                 os_free(buf);
7155                 return -1;
7156         }
7157
7158         res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
7159                                      buf, len, wait_time,
7160                                      wpas_ctrl_iface_mgmt_tx_cb, no_cck);
7161         os_free(buf);
7162         return res;
7163 }
7164
7165
7166 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
7167 {
7168         wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
7169         offchannel_send_action_done(wpa_s);
7170 }
7171
7172
7173 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
7174 {
7175         char *pos, *param;
7176         union wpa_event_data event;
7177         enum wpa_event_type ev;
7178
7179         /* <event name> [parameters..] */
7180
7181         wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd);
7182
7183         pos = cmd;
7184         param = os_strchr(pos, ' ');
7185         if (param)
7186                 *param++ = '\0';
7187
7188         os_memset(&event, 0, sizeof(event));
7189
7190         if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) {
7191                 ev = EVENT_INTERFACE_ENABLED;
7192         } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) {
7193                 ev = EVENT_INTERFACE_DISABLED;
7194         } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) {
7195                 ev = EVENT_AVOID_FREQUENCIES;
7196                 if (param == NULL)
7197                         param = "";
7198                 if (freq_range_list_parse(&event.freq_range, param) < 0)
7199                         return -1;
7200                 wpa_supplicant_event(wpa_s, ev, &event);
7201                 os_free(event.freq_range.range);
7202                 return 0;
7203         } else {
7204                 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
7205                         cmd);
7206                 return -1;
7207         }
7208
7209         wpa_supplicant_event(wpa_s, ev, &event);
7210
7211         return 0;
7212 }
7213
7214
7215 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd)
7216 {
7217         char *pos;
7218         u8 src[ETH_ALEN], *buf;
7219         int used;
7220         size_t len;
7221
7222         wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
7223
7224         pos = cmd;
7225         used = hwaddr_aton2(pos, src);
7226         if (used < 0)
7227                 return -1;
7228         pos += used;
7229         while (*pos == ' ')
7230                 pos++;
7231
7232         len = os_strlen(pos);
7233         if (len & 1)
7234                 return -1;
7235         len /= 2;
7236
7237         buf = os_malloc(len);
7238         if (buf == NULL)
7239                 return -1;
7240
7241         if (hexstr2bin(pos, buf, len) < 0) {
7242                 os_free(buf);
7243                 return -1;
7244         }
7245
7246         wpa_supplicant_rx_eapol(wpa_s, src, buf, len);
7247         os_free(buf);
7248
7249         return 0;
7250 }
7251
7252
7253 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
7254 {
7255         size_t i;
7256         u32 sum = 0;
7257         const u16 *pos = buf;
7258
7259         for (i = 0; i < len / 2; i++)
7260                 sum += *pos++;
7261
7262         while (sum >> 16)
7263                 sum = (sum & 0xffff) + (sum >> 16);
7264
7265         return sum ^ 0xffff;
7266 }
7267
7268
7269 #define HWSIM_PACKETLEN 1500
7270 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
7271
7272 void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
7273 {
7274         struct wpa_supplicant *wpa_s = ctx;
7275         const struct ether_header *eth;
7276         const struct iphdr *ip;
7277         const u8 *pos;
7278         unsigned int i;
7279
7280         if (len != HWSIM_PACKETLEN)
7281                 return;
7282
7283         eth = (const struct ether_header *) buf;
7284         ip = (const struct iphdr *) (eth + 1);
7285         pos = (const u8 *) (ip + 1);
7286
7287         if (ip->ihl != 5 || ip->version != 4 ||
7288             ntohs(ip->tot_len) != HWSIM_IP_LEN)
7289                 return;
7290
7291         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) {
7292                 if (*pos != (u8) i)
7293                         return;
7294                 pos++;
7295         }
7296
7297         wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
7298                 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
7299 }
7300
7301
7302 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s,
7303                                             char *cmd)
7304 {
7305         int enabled = atoi(cmd);
7306
7307         if (!enabled) {
7308                 if (wpa_s->l2_test) {
7309                         l2_packet_deinit(wpa_s->l2_test);
7310                         wpa_s->l2_test = NULL;
7311                         wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled");
7312                 }
7313                 return 0;
7314         }
7315
7316         if (wpa_s->l2_test)
7317                 return 0;
7318
7319         wpa_s->l2_test = l2_packet_init(wpa_s->ifname, wpa_s->own_addr,
7320                                         ETHERTYPE_IP, wpas_data_test_rx,
7321                                         wpa_s, 1);
7322         if (wpa_s->l2_test == NULL)
7323                 return -1;
7324
7325         wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled");
7326
7327         return 0;
7328 }
7329
7330
7331 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd)
7332 {
7333         u8 dst[ETH_ALEN], src[ETH_ALEN];
7334         char *pos;
7335         int used;
7336         long int val;
7337         u8 tos;
7338         u8 buf[HWSIM_PACKETLEN];
7339         struct ether_header *eth;
7340         struct iphdr *ip;
7341         u8 *dpos;
7342         unsigned int i;
7343
7344         if (wpa_s->l2_test == NULL)
7345                 return -1;
7346
7347         /* format: <dst> <src> <tos> */
7348
7349         pos = cmd;
7350         used = hwaddr_aton2(pos, dst);
7351         if (used < 0)
7352                 return -1;
7353         pos += used;
7354         while (*pos == ' ')
7355                 pos++;
7356         used = hwaddr_aton2(pos, src);
7357         if (used < 0)
7358                 return -1;
7359         pos += used;
7360
7361         val = strtol(pos, NULL, 0);
7362         if (val < 0 || val > 0xff)
7363                 return -1;
7364         tos = val;
7365
7366         eth = (struct ether_header *) buf;
7367         os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
7368         os_memcpy(eth->ether_shost, src, ETH_ALEN);
7369         eth->ether_type = htons(ETHERTYPE_IP);
7370         ip = (struct iphdr *) (eth + 1);
7371         os_memset(ip, 0, sizeof(*ip));
7372         ip->ihl = 5;
7373         ip->version = 4;
7374         ip->ttl = 64;
7375         ip->tos = tos;
7376         ip->tot_len = htons(HWSIM_IP_LEN);
7377         ip->protocol = 1;
7378         ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1);
7379         ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2);
7380         ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
7381         dpos = (u8 *) (ip + 1);
7382         for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
7383                 *dpos++ = i;
7384
7385         if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, buf,
7386                            HWSIM_PACKETLEN) < 0)
7387                 return -1;
7388
7389         wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR
7390                 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
7391
7392         return 0;
7393 }
7394
7395
7396 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s,
7397                                            char *cmd)
7398 {
7399         u8 *buf;
7400         struct ether_header *eth;
7401         struct l2_packet_data *l2 = NULL;
7402         size_t len;
7403         u16 ethertype;
7404         int res = -1;
7405
7406         len = os_strlen(cmd);
7407         if (len & 1 || len < ETH_HLEN * 2)
7408                 return -1;
7409         len /= 2;
7410
7411         buf = os_malloc(len);
7412         if (buf == NULL)
7413                 return -1;
7414
7415         if (hexstr2bin(cmd, buf, len) < 0)
7416                 goto done;
7417
7418         eth = (struct ether_header *) buf;
7419         ethertype = ntohs(eth->ether_type);
7420
7421         l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype,
7422                             wpas_data_test_rx, wpa_s, 1);
7423         if (l2 == NULL)
7424                 goto done;
7425
7426         res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
7427         wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res);
7428 done:
7429         if (l2)
7430                 l2_packet_deinit(l2);
7431         os_free(buf);
7432
7433         return res < 0 ? -1 : 0;
7434 }
7435
7436
7437 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
7438 {
7439 #ifdef WPA_TRACE_BFD
7440         extern char wpa_trace_fail_func[256];
7441         extern unsigned int wpa_trace_fail_after;
7442         char *pos;
7443
7444         wpa_trace_fail_after = atoi(cmd);
7445         pos = os_strchr(cmd, ':');
7446         if (pos) {
7447                 pos++;
7448                 os_strlcpy(wpa_trace_fail_func, pos,
7449                            sizeof(wpa_trace_fail_func));
7450         } else {
7451                 wpa_trace_fail_after = 0;
7452         }
7453         return 0;
7454 #else /* WPA_TRACE_BFD */
7455         return -1;
7456 #endif /* WPA_TRACE_BFD */
7457 }
7458
7459
7460 static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s,
7461                                     char *buf, size_t buflen)
7462 {
7463 #ifdef WPA_TRACE_BFD
7464         extern char wpa_trace_fail_func[256];
7465         extern unsigned int wpa_trace_fail_after;
7466
7467         return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
7468                            wpa_trace_fail_func);
7469 #else /* WPA_TRACE_BFD */
7470         return -1;
7471 #endif /* WPA_TRACE_BFD */
7472 }
7473
7474 #endif /* CONFIG_TESTING_OPTIONS */
7475
7476
7477 static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
7478 {
7479         unsigned int i;
7480         char buf[30];
7481
7482         wpa_printf(MSG_DEBUG, "Update vendor elements");
7483
7484         for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7485                 if (wpa_s->vendor_elem[i]) {
7486                         int res;
7487
7488                         res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7489                         if (!os_snprintf_error(sizeof(buf), res)) {
7490                                 wpa_hexdump_buf(MSG_DEBUG, buf,
7491                                                 wpa_s->vendor_elem[i]);
7492                         }
7493                 }
7494         }
7495
7496 #ifdef CONFIG_P2P
7497         if (wpa_s->parent == wpa_s &&
7498             wpa_s->global->p2p &&
7499             !wpa_s->global->p2p_disabled)
7500                 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7501 #endif /* CONFIG_P2P */
7502 }
7503
7504
7505 static struct wpa_supplicant *
7506 wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
7507                             enum wpa_vendor_elem_frame frame)
7508 {
7509         switch (frame) {
7510 #ifdef CONFIG_P2P
7511         case VENDOR_ELEM_PROBE_REQ_P2P:
7512         case VENDOR_ELEM_PROBE_RESP_P2P:
7513         case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7514         case VENDOR_ELEM_BEACON_P2P_GO:
7515         case VENDOR_ELEM_P2P_PD_REQ:
7516         case VENDOR_ELEM_P2P_PD_RESP:
7517         case VENDOR_ELEM_P2P_GO_NEG_REQ:
7518         case VENDOR_ELEM_P2P_GO_NEG_RESP:
7519         case VENDOR_ELEM_P2P_GO_NEG_CONF:
7520         case VENDOR_ELEM_P2P_INV_REQ:
7521         case VENDOR_ELEM_P2P_INV_RESP:
7522         case VENDOR_ELEM_P2P_ASSOC_REQ:
7523                 return wpa_s->parent;
7524 #endif /* CONFIG_P2P */
7525         default:
7526                 return wpa_s;
7527         }
7528 }
7529
7530
7531 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
7532 {
7533         char *pos = cmd;
7534         int frame;
7535         size_t len;
7536         struct wpabuf *buf;
7537         struct ieee802_11_elems elems;
7538
7539         frame = atoi(pos);
7540         if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
7541                 return -1;
7542         wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
7543
7544         pos = os_strchr(pos, ' ');
7545         if (pos == NULL)
7546                 return -1;
7547         pos++;
7548
7549         len = os_strlen(pos);
7550         if (len == 0)
7551                 return 0;
7552         if (len & 1)
7553                 return -1;
7554         len /= 2;
7555
7556         buf = wpabuf_alloc(len);
7557         if (buf == NULL)
7558                 return -1;
7559
7560         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
7561                 wpabuf_free(buf);
7562                 return -1;
7563         }
7564
7565         if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) ==
7566             ParseFailed) {
7567                 wpabuf_free(buf);
7568                 return -1;
7569         }
7570
7571         if (wpa_s->vendor_elem[frame] == NULL) {
7572                 wpa_s->vendor_elem[frame] = buf;
7573                 wpas_ctrl_vendor_elem_update(wpa_s);
7574                 return 0;
7575         }
7576
7577         if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
7578                 wpabuf_free(buf);
7579                 return -1;
7580         }
7581
7582         wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
7583         wpabuf_free(buf);
7584         wpas_ctrl_vendor_elem_update(wpa_s);
7585
7586         return 0;
7587 }
7588
7589
7590 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
7591                                      char *buf, size_t buflen)
7592 {
7593         int frame = atoi(cmd);
7594
7595         if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
7596                 return -1;
7597         wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
7598
7599         if (wpa_s->vendor_elem[frame] == NULL)
7600                 return 0;
7601
7602         return wpa_snprintf_hex(buf, buflen,
7603                                 wpabuf_head_u8(wpa_s->vendor_elem[frame]),
7604                                 wpabuf_len(wpa_s->vendor_elem[frame]));
7605 }
7606
7607
7608 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
7609 {
7610         char *pos = cmd;
7611         int frame;
7612         size_t len;
7613         u8 *buf;
7614         struct ieee802_11_elems elems;
7615         u8 *ie, *end;
7616
7617         frame = atoi(pos);
7618         if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
7619                 return -1;
7620         wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
7621
7622         pos = os_strchr(pos, ' ');
7623         if (pos == NULL)
7624                 return -1;
7625         pos++;
7626
7627         if (*pos == '*') {
7628                 wpabuf_free(wpa_s->vendor_elem[frame]);
7629                 wpa_s->vendor_elem[frame] = NULL;
7630                 wpas_ctrl_vendor_elem_update(wpa_s);
7631                 return 0;
7632         }
7633
7634         if (wpa_s->vendor_elem[frame] == NULL)
7635                 return -1;
7636
7637         len = os_strlen(pos);
7638         if (len == 0)
7639                 return 0;
7640         if (len & 1)
7641                 return -1;
7642         len /= 2;
7643
7644         buf = os_malloc(len);
7645         if (buf == NULL)
7646                 return -1;
7647
7648         if (hexstr2bin(pos, buf, len) < 0) {
7649                 os_free(buf);
7650                 return -1;
7651         }
7652
7653         if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) {
7654                 os_free(buf);
7655                 return -1;
7656         }
7657
7658         ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7659         end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7660
7661         for (; ie + 1 < end; ie += 2 + ie[1]) {
7662                 if (ie + len > end)
7663                         break;
7664                 if (os_memcmp(ie, buf, len) != 0)
7665                         continue;
7666
7667                 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7668                         wpabuf_free(wpa_s->vendor_elem[frame]);
7669                         wpa_s->vendor_elem[frame] = NULL;
7670                 } else {
7671                         os_memmove(ie, ie + len,
7672                                    end - (ie + len));
7673                         wpa_s->vendor_elem[frame]->used -= len;
7674                 }
7675                 os_free(buf);
7676                 wpas_ctrl_vendor_elem_update(wpa_s);
7677                 return 0;
7678         }
7679
7680         os_free(buf);
7681
7682         return -1;
7683 }
7684
7685
7686 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
7687 {
7688         struct wpa_supplicant *wpa_s = ctx;
7689
7690         if (neighbor_rep) {
7691                 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
7692                              "length=%u",
7693                              (unsigned int) wpabuf_len(neighbor_rep));
7694                 wpabuf_free(neighbor_rep);
7695         } else {
7696                 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
7697         }
7698 }
7699
7700
7701 static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
7702                                             char *cmd)
7703 {
7704         struct wpa_ssid ssid;
7705         struct wpa_ssid *ssid_p = NULL;
7706         int ret = 0;
7707
7708         if (os_strncmp(cmd, " ssid=", 6) == 0) {
7709                 ssid.ssid_len = os_strlen(cmd + 6);
7710                 if (ssid.ssid_len > SSID_MAX_LEN)
7711                         return -1;
7712                 ssid.ssid = (u8 *) (cmd + 6);
7713                 ssid_p = &ssid;
7714         }
7715
7716         ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p,
7717                                                  wpas_ctrl_neighbor_rep_cb,
7718                                                  wpa_s);
7719
7720         return ret;
7721 }
7722
7723
7724 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s)
7725 {
7726         eapol_sm_erp_flush(wpa_s->eapol);
7727         return 0;
7728 }
7729
7730
7731 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s,
7732                                          char *cmd)
7733 {
7734         char *token, *context = NULL;
7735         unsigned int enable = ~0, type = 0;
7736         u8 _addr[ETH_ALEN], _mask[ETH_ALEN];
7737         u8 *addr = NULL, *mask = NULL;
7738
7739         while ((token = str_token(cmd, " ", &context))) {
7740                 if (os_strcasecmp(token, "scan") == 0) {
7741                         type |= MAC_ADDR_RAND_SCAN;
7742                 } else if (os_strcasecmp(token, "sched") == 0) {
7743                         type |= MAC_ADDR_RAND_SCHED_SCAN;
7744                 } else if (os_strcasecmp(token, "pno") == 0) {
7745                         type |= MAC_ADDR_RAND_PNO;
7746                 } else if (os_strcasecmp(token, "all") == 0) {
7747                         type = wpa_s->mac_addr_rand_supported;
7748                 } else if (os_strncasecmp(token, "enable=", 7) == 0) {
7749                         enable = atoi(token + 7);
7750                 } else if (os_strncasecmp(token, "addr=", 5) == 0) {
7751                         addr = _addr;
7752                         if (hwaddr_aton(token + 5, addr)) {
7753                                 wpa_printf(MSG_INFO,
7754                                            "CTRL: Invalid MAC address: %s",
7755                                            token);
7756                                 return -1;
7757                         }
7758                 } else if (os_strncasecmp(token, "mask=", 5) == 0) {
7759                         mask = _mask;
7760                         if (hwaddr_aton(token + 5, mask)) {
7761                                 wpa_printf(MSG_INFO,
7762                                            "CTRL: Invalid MAC address mask: %s",
7763                                            token);
7764                                 return -1;
7765                         }
7766                 } else {
7767                         wpa_printf(MSG_INFO,
7768                                    "CTRL: Invalid MAC_RAND_SCAN parameter: %s",
7769                                    token);
7770                         return -1;
7771                 }
7772         }
7773
7774         if (!type) {
7775                 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified");
7776                 return -1;
7777         }
7778
7779         if ((wpa_s->mac_addr_rand_supported & type) != type) {
7780                 wpa_printf(MSG_INFO,
7781                            "CTRL: MAC_RAND_SCAN types=%u != supported=%u",
7782                            type, wpa_s->mac_addr_rand_supported);
7783                 return -1;
7784         }
7785
7786         if (enable > 1) {
7787                 wpa_printf(MSG_INFO,
7788                            "CTRL: MAC_RAND_SCAN enable=<0/1> not specified");
7789                 return -1;
7790         }
7791
7792         if (!enable) {
7793                 wpas_mac_addr_rand_scan_clear(wpa_s, type);
7794                 if (wpa_s->pno) {
7795                         if (type & MAC_ADDR_RAND_PNO) {
7796                                 wpas_stop_pno(wpa_s);
7797                                 wpas_start_pno(wpa_s);
7798                         }
7799                 } else if (wpa_s->sched_scanning &&
7800                            (type & MAC_ADDR_RAND_SCHED_SCAN)) {
7801                         /* simulate timeout to restart the sched scan */
7802                         wpa_s->sched_scan_timed_out = 1;
7803                         wpa_s->prev_sched_ssid = NULL;
7804                         wpa_supplicant_cancel_sched_scan(wpa_s);
7805                 }
7806                 return 0;
7807         }
7808
7809         if ((addr && !mask) || (!addr && mask)) {
7810                 wpa_printf(MSG_INFO,
7811                            "CTRL: MAC_RAND_SCAN invalid addr/mask combination");
7812                 return -1;
7813         }
7814
7815         if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
7816                 wpa_printf(MSG_INFO,
7817                            "CTRL: MAC_RAND_SCAN cannot allow multicast address");
7818                 return -1;
7819         }
7820
7821         if (type & MAC_ADDR_RAND_SCAN) {
7822                 wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
7823                                             addr, mask);
7824         }
7825
7826         if (type & MAC_ADDR_RAND_SCHED_SCAN) {
7827                 wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
7828                                             addr, mask);
7829
7830                 if (wpa_s->sched_scanning && !wpa_s->pno) {
7831                         /* simulate timeout to restart the sched scan */
7832                         wpa_s->sched_scan_timed_out = 1;
7833                         wpa_s->prev_sched_ssid = NULL;
7834                         wpa_supplicant_cancel_sched_scan(wpa_s);
7835                 }
7836         }
7837
7838         if (type & MAC_ADDR_RAND_PNO) {
7839                 wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
7840                                             addr, mask);
7841                 if (wpa_s->pno) {
7842                         wpas_stop_pno(wpa_s);
7843                         wpas_start_pno(wpa_s);
7844                 }
7845         }
7846
7847         return 0;
7848 }
7849
7850
7851 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
7852                                          char *buf, size_t *resp_len)
7853 {
7854         char *reply;
7855         const int reply_size = 4096;
7856         int reply_len;
7857
7858         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
7859             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
7860                 if (wpa_debug_show_keys)
7861                         wpa_dbg(wpa_s, MSG_DEBUG,
7862                                 "Control interface command '%s'", buf);
7863                 else
7864                         wpa_dbg(wpa_s, MSG_DEBUG,
7865                                 "Control interface command '%s [REMOVED]'",
7866                                 os_strncmp(buf, WPA_CTRL_RSP,
7867                                            os_strlen(WPA_CTRL_RSP)) == 0 ?
7868                                 WPA_CTRL_RSP : "SET_NETWORK");
7869         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
7870                    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) {
7871                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
7872                                       (const u8 *) buf, os_strlen(buf));
7873         } else {
7874                 int level = MSG_DEBUG;
7875                 if (os_strcmp(buf, "PING") == 0)
7876                         level = MSG_EXCESSIVE;
7877                 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
7878         }
7879
7880         reply = os_malloc(reply_size);
7881         if (reply == NULL) {
7882                 *resp_len = 1;
7883                 return NULL;
7884         }
7885
7886         os_memcpy(reply, "OK\n", 3);
7887         reply_len = 3;
7888
7889         if (os_strcmp(buf, "PING") == 0) {
7890                 os_memcpy(reply, "PONG\n", 5);
7891                 reply_len = 5;
7892         } else if (os_strcmp(buf, "IFNAME") == 0) {
7893                 reply_len = os_strlen(wpa_s->ifname);
7894                 os_memcpy(reply, wpa_s->ifname, reply_len);
7895         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
7896                 if (wpa_debug_reopen_file() < 0)
7897                         reply_len = -1;
7898         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
7899                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
7900         } else if (os_strcmp(buf, "MIB") == 0) {
7901                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
7902                 if (reply_len >= 0) {
7903                         reply_len += eapol_sm_get_mib(wpa_s->eapol,
7904                                                       reply + reply_len,
7905                                                       reply_size - reply_len);
7906                 }
7907         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
7908                 reply_len = wpa_supplicant_ctrl_iface_status(
7909                         wpa_s, buf + 6, reply, reply_size);
7910         } else if (os_strcmp(buf, "PMKSA") == 0) {
7911                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
7912                                                     reply_size);
7913         } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
7914                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
7915         } else if (os_strncmp(buf, "SET ", 4) == 0) {
7916                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
7917                         reply_len = -1;
7918         } else if (os_strncmp(buf, "DUMP", 4) == 0) {
7919                 reply_len = wpa_config_dump_values(wpa_s->conf,
7920                                                    reply, reply_size);
7921         } else if (os_strncmp(buf, "GET ", 4) == 0) {
7922                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
7923                                                           reply, reply_size);
7924         } else if (os_strcmp(buf, "LOGON") == 0) {
7925                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
7926         } else if (os_strcmp(buf, "LOGOFF") == 0) {
7927                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
7928         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
7929                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
7930                         reply_len = -1;
7931                 else
7932                         wpas_request_connection(wpa_s);
7933         } else if (os_strcmp(buf, "REATTACH") == 0) {
7934                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
7935                     !wpa_s->current_ssid)
7936                         reply_len = -1;
7937                 else {
7938                         wpa_s->reattach = 1;
7939                         wpas_request_connection(wpa_s);
7940                 }
7941         } else if (os_strcmp(buf, "RECONNECT") == 0) {
7942                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
7943                         reply_len = -1;
7944                 else if (wpa_s->disconnected)
7945                         wpas_request_connection(wpa_s);
7946 #ifdef IEEE8021X_EAPOL
7947         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
7948                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
7949                         reply_len = -1;
7950 #endif /* IEEE8021X_EAPOL */
7951 #ifdef CONFIG_PEERKEY
7952         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
7953                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
7954                         reply_len = -1;
7955 #endif /* CONFIG_PEERKEY */
7956 #ifdef CONFIG_IEEE80211R
7957         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
7958                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
7959                         reply_len = -1;
7960 #endif /* CONFIG_IEEE80211R */
7961 #ifdef CONFIG_WPS
7962         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
7963                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
7964                 if (res == -2) {
7965                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
7966                         reply_len = 17;
7967                 } else if (res)
7968                         reply_len = -1;
7969         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
7970                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
7971                 if (res == -2) {
7972                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
7973                         reply_len = 17;
7974                 } else if (res)
7975                         reply_len = -1;
7976         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
7977                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
7978                                                               reply,
7979                                                               reply_size);
7980         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
7981                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
7982                         wpa_s, buf + 14, reply, reply_size);
7983         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
7984                 if (wpas_wps_cancel(wpa_s))
7985                         reply_len = -1;
7986 #ifdef CONFIG_WPS_NFC
7987         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
7988                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
7989                         reply_len = -1;
7990         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
7991                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
7992                         reply_len = -1;
7993         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
7994                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
7995                         wpa_s, buf + 21, reply, reply_size);
7996         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
7997                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
7998                         wpa_s, buf + 14, reply, reply_size);
7999         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
8000                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
8001                                                                buf + 17))
8002                         reply_len = -1;
8003         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
8004                 reply_len = wpas_ctrl_nfc_get_handover_req(
8005                         wpa_s, buf + 21, reply, reply_size);
8006         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
8007                 reply_len = wpas_ctrl_nfc_get_handover_sel(
8008                         wpa_s, buf + 21, reply, reply_size);
8009         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
8010                 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
8011                         reply_len = -1;
8012 #endif /* CONFIG_WPS_NFC */
8013         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
8014                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
8015                         reply_len = -1;
8016 #ifdef CONFIG_AP
8017         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
8018                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
8019                         wpa_s, buf + 11, reply, reply_size);
8020 #endif /* CONFIG_AP */
8021 #ifdef CONFIG_WPS_ER
8022         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
8023                 if (wpas_wps_er_start(wpa_s, NULL))
8024                         reply_len = -1;
8025         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
8026                 if (wpas_wps_er_start(wpa_s, buf + 13))
8027                         reply_len = -1;
8028         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
8029                 wpas_wps_er_stop(wpa_s);
8030         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
8031                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
8032                         reply_len = -1;
8033         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
8034                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
8035                 if (ret == -2) {
8036                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
8037                         reply_len = 17;
8038                 } else if (ret == -3) {
8039                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
8040                         reply_len = 18;
8041                 } else if (ret == -4) {
8042                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
8043                         reply_len = 20;
8044                 } else if (ret)
8045                         reply_len = -1;
8046         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
8047                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
8048                         reply_len = -1;
8049         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
8050                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
8051                                                                 buf + 18))
8052                         reply_len = -1;
8053         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
8054                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
8055                         reply_len = -1;
8056 #ifdef CONFIG_WPS_NFC
8057         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
8058                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
8059                         wpa_s, buf + 24, reply, reply_size);
8060 #endif /* CONFIG_WPS_NFC */
8061 #endif /* CONFIG_WPS_ER */
8062 #endif /* CONFIG_WPS */
8063 #ifdef CONFIG_IBSS_RSN
8064         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
8065                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
8066                         reply_len = -1;
8067 #endif /* CONFIG_IBSS_RSN */
8068 #ifdef CONFIG_MESH
8069         } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
8070                 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
8071                         wpa_s, buf + 19, reply, reply_size);
8072         } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) {
8073                 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
8074                         wpa_s, "", reply, reply_size);
8075         } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
8076                 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
8077                         reply_len = -1;
8078         } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
8079                 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
8080                                                                 buf + 18))
8081                         reply_len = -1;
8082 #endif /* CONFIG_MESH */
8083 #ifdef CONFIG_P2P
8084         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
8085                 if (p2p_ctrl_find(wpa_s, buf + 8))
8086                         reply_len = -1;
8087         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
8088                 if (p2p_ctrl_find(wpa_s, ""))
8089                         reply_len = -1;
8090         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
8091                 wpas_p2p_stop_find(wpa_s);
8092         } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
8093                 if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
8094                         reply_len = -1;
8095         } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
8096                 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
8097                         reply_len = -1;
8098         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
8099                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
8100                                              reply_size);
8101         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
8102                 if (p2p_ctrl_listen(wpa_s, buf + 11))
8103                         reply_len = -1;
8104         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
8105                 if (p2p_ctrl_listen(wpa_s, ""))
8106                         reply_len = -1;
8107         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
8108                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
8109                         reply_len = -1;
8110         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
8111                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
8112                         reply_len = -1;
8113         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
8114                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
8115                         reply_len = -1;
8116         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
8117                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
8118                         reply_len = -1;
8119         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
8120                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
8121         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
8122                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
8123                                                    reply_size);
8124         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
8125                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
8126                         reply_len = -1;
8127         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
8128                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
8129                         reply_len = -1;
8130         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
8131                 wpas_p2p_sd_service_update(wpa_s);
8132         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
8133                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
8134                         reply_len = -1;
8135         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
8136                 wpas_p2p_service_flush(wpa_s);
8137         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
8138                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
8139                         reply_len = -1;
8140         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
8141                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
8142                         reply_len = -1;
8143         } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
8144                 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
8145                         reply_len = -1;
8146         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
8147                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
8148                         reply_len = -1;
8149         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
8150                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
8151                         reply_len = -1;
8152         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
8153                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
8154                                               reply_size);
8155         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
8156                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
8157                         reply_len = -1;
8158         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
8159                 p2p_ctrl_flush(wpa_s);
8160         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
8161                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
8162                         reply_len = -1;
8163         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
8164                 if (wpas_p2p_cancel(wpa_s))
8165                         reply_len = -1;
8166         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
8167                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
8168                         reply_len = -1;
8169         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
8170                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
8171                         reply_len = -1;
8172         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
8173                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
8174                         reply_len = -1;
8175         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
8176                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
8177                         reply_len = -1;
8178         } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
8179                 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
8180                         reply_len = -1;
8181 #endif /* CONFIG_P2P */
8182 #ifdef CONFIG_WIFI_DISPLAY
8183         } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
8184                 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
8185                         reply_len = -1;
8186         } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
8187                 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
8188                                                      reply, reply_size);
8189 #endif /* CONFIG_WIFI_DISPLAY */
8190 #ifdef CONFIG_INTERWORKING
8191         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
8192                 if (interworking_fetch_anqp(wpa_s) < 0)
8193                         reply_len = -1;
8194         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
8195                 interworking_stop_fetch_anqp(wpa_s);
8196         } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
8197                 if (ctrl_interworking_select(wpa_s, NULL) < 0)
8198                         reply_len = -1;
8199         } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
8200                 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
8201                         reply_len = -1;
8202         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
8203                 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0)
8204                         reply_len = -1;
8205         } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) {
8206                 int id;
8207
8208                 id = ctrl_interworking_connect(wpa_s, buf + 25, 1);
8209                 if (id < 0)
8210                         reply_len = -1;
8211                 else {
8212                         reply_len = os_snprintf(reply, reply_size, "%d\n", id);
8213                         if (os_snprintf_error(reply_size, reply_len))
8214                                 reply_len = -1;
8215                 }
8216         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
8217                 if (get_anqp(wpa_s, buf + 9) < 0)
8218                         reply_len = -1;
8219         } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
8220                 if (gas_request(wpa_s, buf + 12) < 0)
8221                         reply_len = -1;
8222         } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
8223                 reply_len = gas_response_get(wpa_s, buf + 17, reply,
8224                                              reply_size);
8225 #endif /* CONFIG_INTERWORKING */
8226 #ifdef CONFIG_HS20
8227         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
8228                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
8229                         reply_len = -1;
8230         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
8231                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
8232                         reply_len = -1;
8233         } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
8234                 if (hs20_icon_request(wpa_s, buf + 18) < 0)
8235                         reply_len = -1;
8236         } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
8237                 if (hs20_fetch_osu(wpa_s) < 0)
8238                         reply_len = -1;
8239         } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
8240                 hs20_cancel_fetch_osu(wpa_s);
8241 #endif /* CONFIG_HS20 */
8242         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
8243         {
8244                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
8245                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
8246                         reply_len = -1;
8247                 else {
8248                         /*
8249                          * Notify response from timeout to allow the control
8250                          * interface response to be sent first.
8251                          */
8252                         eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
8253                                                wpa_s, NULL);
8254                 }
8255         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
8256                 if (wpa_supplicant_reload_configuration(wpa_s))
8257                         reply_len = -1;
8258         } else if (os_strcmp(buf, "TERMINATE") == 0) {
8259                 wpa_supplicant_terminate_proc(wpa_s->global);
8260         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
8261                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
8262                         reply_len = -1;
8263         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
8264                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
8265                         wpa_s, buf + 9, reply, reply_size);
8266         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
8267                 reply_len = wpa_supplicant_ctrl_iface_log_level(
8268                         wpa_s, buf + 9, reply, reply_size);
8269         } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) {
8270                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
8271                         wpa_s, buf + 14, reply, reply_size);
8272         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
8273                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
8274                         wpa_s, NULL, reply, reply_size);
8275         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
8276 #ifdef CONFIG_SME
8277                 wpa_s->sme.prev_bssid_set = 0;
8278 #endif /* CONFIG_SME */
8279                 wpa_s->reassociate = 0;
8280                 wpa_s->disconnected = 1;
8281                 wpa_supplicant_cancel_sched_scan(wpa_s);
8282                 wpa_supplicant_cancel_scan(wpa_s);
8283                 wpa_supplicant_deauthenticate(wpa_s,
8284                                               WLAN_REASON_DEAUTH_LEAVING);
8285                 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
8286         } else if (os_strcmp(buf, "SCAN") == 0) {
8287                 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
8288         } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
8289                 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
8290         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
8291                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
8292                         wpa_s, reply, reply_size);
8293         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
8294                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
8295                         reply_len = -1;
8296         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
8297                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
8298                         reply_len = -1;
8299         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
8300                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
8301                         reply_len = -1;
8302         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
8303                 reply_len = wpa_supplicant_ctrl_iface_add_network(
8304                         wpa_s, reply, reply_size);
8305         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
8306                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
8307                         reply_len = -1;
8308         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
8309                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
8310                         reply_len = -1;
8311         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
8312                 reply_len = wpa_supplicant_ctrl_iface_get_network(
8313                         wpa_s, buf + 12, reply, reply_size);
8314         } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
8315                 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12))
8316                         reply_len = -1;
8317         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
8318                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
8319                         wpa_s, reply, reply_size);
8320         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
8321                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
8322                         wpa_s, reply, reply_size);
8323         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
8324                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
8325                         reply_len = -1;
8326         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
8327                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
8328                         reply_len = -1;
8329         } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
8330                 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
8331                                                                reply,
8332                                                                reply_size);
8333 #ifndef CONFIG_NO_CONFIG_WRITE
8334         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
8335                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
8336                         reply_len = -1;
8337 #endif /* CONFIG_NO_CONFIG_WRITE */
8338         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
8339                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
8340                         wpa_s, buf + 15, reply, reply_size);
8341         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
8342                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
8343                         reply_len = -1;
8344         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
8345                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
8346                         reply_len = -1;
8347         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
8348                 reply_len = wpa_supplicant_global_iface_list(
8349                         wpa_s->global, reply, reply_size);
8350         } else if (os_strcmp(buf, "INTERFACES") == 0) {
8351                 reply_len = wpa_supplicant_global_iface_interfaces(
8352                         wpa_s->global, reply, reply_size);
8353         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
8354                 reply_len = wpa_supplicant_ctrl_iface_bss(
8355                         wpa_s, buf + 4, reply, reply_size);
8356 #ifdef CONFIG_AP
8357         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
8358                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
8359         } else if (os_strncmp(buf, "STA ", 4) == 0) {
8360                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
8361                                               reply_size);
8362         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
8363                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
8364                                                    reply_size);
8365         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
8366                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
8367                         reply_len = -1;
8368         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
8369                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
8370                         reply_len = -1;
8371         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
8372                 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
8373                         reply_len = -1;
8374         } else if (os_strcmp(buf, "STOP_AP") == 0) {
8375                 if (wpas_ap_stop_ap(wpa_s))
8376                         reply_len = -1;
8377 #endif /* CONFIG_AP */
8378         } else if (os_strcmp(buf, "SUSPEND") == 0) {
8379                 wpas_notify_suspend(wpa_s->global);
8380         } else if (os_strcmp(buf, "RESUME") == 0) {
8381                 wpas_notify_resume(wpa_s->global);
8382 #ifdef CONFIG_TESTING_OPTIONS
8383         } else if (os_strcmp(buf, "DROP_SA") == 0) {
8384                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
8385 #endif /* CONFIG_TESTING_OPTIONS */
8386         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
8387                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
8388                         reply_len = -1;
8389         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
8390                 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0;
8391         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
8392                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
8393                         reply_len = -1;
8394         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
8395                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
8396                                                                buf + 17))
8397                         reply_len = -1;
8398         } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
8399                 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10);
8400 #ifdef CONFIG_TDLS
8401         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
8402                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
8403                         reply_len = -1;
8404         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
8405                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
8406                         reply_len = -1;
8407         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
8408                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
8409                         reply_len = -1;
8410         } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) {
8411                 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s,
8412                                                                buf + 17))
8413                         reply_len = -1;
8414         } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) {
8415                 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s,
8416                                                                       buf + 24))
8417                         reply_len = -1;
8418 #endif /* CONFIG_TDLS */
8419         } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) {
8420                 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size);
8421         } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) {
8422                 if (wmm_ac_ctrl_addts(wpa_s, buf + 13))
8423                         reply_len = -1;
8424         } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) {
8425                 if (wmm_ac_ctrl_delts(wpa_s, buf + 13))
8426                         reply_len = -1;
8427         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
8428                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
8429                                                        reply_size);
8430         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
8431                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
8432                                                        reply_size);
8433 #ifdef CONFIG_AUTOSCAN
8434         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
8435                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
8436                         reply_len = -1;
8437 #endif /* CONFIG_AUTOSCAN */
8438 #ifdef ANDROID
8439         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
8440                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
8441                                                       reply_size);
8442 #endif /* ANDROID */
8443         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
8444                 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
8445                                                       reply_size);
8446         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
8447                 pmksa_cache_clear_current(wpa_s->wpa);
8448                 eapol_sm_request_reauth(wpa_s->eapol);
8449 #ifdef CONFIG_WNM
8450         } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
8451                 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
8452                         reply_len = -1;
8453         } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
8454                 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
8455                                 reply_len = -1;
8456 #endif /* CONFIG_WNM */
8457         } else if (os_strcmp(buf, "FLUSH") == 0) {
8458                 wpa_supplicant_ctrl_iface_flush(wpa_s);
8459         } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
8460                 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
8461                                                  reply_size);
8462 #ifdef CONFIG_TESTING_OPTIONS
8463         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
8464                 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
8465                         reply_len = -1;
8466         } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
8467                 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
8468         } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
8469                 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
8470                         reply_len = -1;
8471         } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
8472                 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
8473                         reply_len = -1;
8474         } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
8475                 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
8476                         reply_len = -1;
8477         } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
8478                 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0)
8479                         reply_len = -1;
8480         } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
8481                 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0)
8482                         reply_len = -1;
8483         } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
8484                 if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0)
8485                         reply_len = -1;
8486         } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
8487                 reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size);
8488 #endif /* CONFIG_TESTING_OPTIONS */
8489         } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
8490                 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
8491                         reply_len = -1;
8492         } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) {
8493                 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply,
8494                                                       reply_size);
8495         } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) {
8496                 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
8497                         reply_len = -1;
8498         } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
8499                 if (wpas_ctrl_iface_send_neigbor_rep(wpa_s, buf + 20))
8500                         reply_len = -1;
8501         } else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
8502                 wpas_ctrl_iface_erp_flush(wpa_s);
8503         } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) {
8504                 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14))
8505                         reply_len = -1;
8506         } else {
8507                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
8508                 reply_len = 16;
8509         }
8510
8511         if (reply_len < 0) {
8512                 os_memcpy(reply, "FAIL\n", 5);
8513                 reply_len = 5;
8514         }
8515
8516         *resp_len = reply_len;
8517         return reply;
8518 }
8519
8520
8521 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
8522                                            char *cmd)
8523 {
8524         struct wpa_interface iface;
8525         char *pos, *extra;
8526         struct wpa_supplicant *wpa_s;
8527         unsigned int create_iface = 0;
8528         u8 mac_addr[ETH_ALEN];
8529
8530         /*
8531          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
8532          * TAB<bridge_ifname>[TAB<create>]
8533          */
8534         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
8535
8536         os_memset(&iface, 0, sizeof(iface));
8537
8538         do {
8539                 iface.ifname = pos = cmd;
8540                 pos = os_strchr(pos, '\t');
8541                 if (pos)
8542                         *pos++ = '\0';
8543                 if (iface.ifname[0] == '\0')
8544                         return -1;
8545                 if (pos == NULL)
8546                         break;
8547
8548                 iface.confname = pos;
8549                 pos = os_strchr(pos, '\t');
8550                 if (pos)
8551                         *pos++ = '\0';
8552                 if (iface.confname[0] == '\0')
8553                         iface.confname = NULL;
8554                 if (pos == NULL)
8555                         break;
8556
8557                 iface.driver = pos;
8558                 pos = os_strchr(pos, '\t');
8559                 if (pos)
8560                         *pos++ = '\0';
8561                 if (iface.driver[0] == '\0')
8562                         iface.driver = NULL;
8563                 if (pos == NULL)
8564                         break;
8565
8566                 iface.ctrl_interface = pos;
8567                 pos = os_strchr(pos, '\t');
8568                 if (pos)
8569                         *pos++ = '\0';
8570                 if (iface.ctrl_interface[0] == '\0')
8571                         iface.ctrl_interface = NULL;
8572                 if (pos == NULL)
8573                         break;
8574
8575                 iface.driver_param = pos;
8576                 pos = os_strchr(pos, '\t');
8577                 if (pos)
8578                         *pos++ = '\0';
8579                 if (iface.driver_param[0] == '\0')
8580                         iface.driver_param = NULL;
8581                 if (pos == NULL)
8582                         break;
8583
8584                 iface.bridge_ifname = pos;
8585                 pos = os_strchr(pos, '\t');
8586                 if (pos)
8587                         *pos++ = '\0';
8588                 if (iface.bridge_ifname[0] == '\0')
8589                         iface.bridge_ifname = NULL;
8590                 if (pos == NULL)
8591                         break;
8592
8593                 extra = pos;
8594                 pos = os_strchr(pos, '\t');
8595                 if (pos)
8596                         *pos++ = '\0';
8597                 if (!extra[0])
8598                         break;
8599
8600                 if (os_strcmp(extra, "create") == 0)
8601                         create_iface = 1;
8602                 else {
8603                         wpa_printf(MSG_DEBUG,
8604                                    "INTERFACE_ADD unsupported extra parameter: '%s'",
8605                                    extra);
8606                         return -1;
8607                 }
8608         } while (0);
8609
8610         if (create_iface) {
8611                 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
8612                            iface.ifname);
8613                 if (!global->ifaces)
8614                         return -1;
8615                 if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
8616                                    NULL, NULL, NULL, mac_addr, NULL) < 0) {
8617                         wpa_printf(MSG_ERROR,
8618                                    "CTRL_IFACE interface creation failed");
8619                         return -1;
8620                 }
8621
8622                 wpa_printf(MSG_DEBUG,
8623                            "CTRL_IFACE interface '%s' created with MAC addr: "
8624                            MACSTR, iface.ifname, MAC2STR(mac_addr));
8625         }
8626
8627         if (wpa_supplicant_get_iface(global, iface.ifname))
8628                 goto fail;
8629
8630         wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
8631         if (!wpa_s)
8632                 goto fail;
8633         wpa_s->added_vif = create_iface;
8634         return 0;
8635
8636 fail:
8637         if (create_iface)
8638                 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
8639         return -1;
8640 }
8641
8642
8643 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
8644                                               char *cmd)
8645 {
8646         struct wpa_supplicant *wpa_s;
8647         int ret;
8648         unsigned int delete_iface;
8649
8650         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
8651
8652         wpa_s = wpa_supplicant_get_iface(global, cmd);
8653         if (wpa_s == NULL)
8654                 return -1;
8655         delete_iface = wpa_s->added_vif;
8656         ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
8657         if (!ret && delete_iface) {
8658                 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
8659                            cmd);
8660                 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
8661         }
8662         return ret;
8663 }
8664
8665
8666 static void wpa_free_iface_info(struct wpa_interface_info *iface)
8667 {
8668         struct wpa_interface_info *prev;
8669
8670         while (iface) {
8671                 prev = iface;
8672                 iface = iface->next;
8673
8674                 os_free(prev->ifname);
8675                 os_free(prev->desc);
8676                 os_free(prev);
8677         }
8678 }
8679
8680
8681 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
8682                                             char *buf, int len)
8683 {
8684         int i, res;
8685         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
8686         char *pos, *end;
8687
8688         for (i = 0; wpa_drivers[i]; i++) {
8689                 const struct wpa_driver_ops *drv = wpa_drivers[i];
8690                 if (drv->get_interfaces == NULL)
8691                         continue;
8692                 tmp = drv->get_interfaces(global->drv_priv[i]);
8693                 if (tmp == NULL)
8694                         continue;
8695
8696                 if (last == NULL)
8697                         iface = last = tmp;
8698                 else
8699                         last->next = tmp;
8700                 while (last->next)
8701                         last = last->next;
8702         }
8703
8704         pos = buf;
8705         end = buf + len;
8706         for (tmp = iface; tmp; tmp = tmp->next) {
8707                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
8708                                   tmp->drv_name, tmp->ifname,
8709                                   tmp->desc ? tmp->desc : "");
8710                 if (os_snprintf_error(end - pos, res)) {
8711                         *pos = '\0';
8712                         break;
8713                 }
8714                 pos += res;
8715         }
8716
8717         wpa_free_iface_info(iface);
8718
8719         return pos - buf;
8720 }
8721
8722
8723 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
8724                                                   char *buf, int len)
8725 {
8726         int res;
8727         char *pos, *end;
8728         struct wpa_supplicant *wpa_s;
8729
8730         wpa_s = global->ifaces;
8731         pos = buf;
8732         end = buf + len;
8733
8734         while (wpa_s) {
8735                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
8736                 if (os_snprintf_error(end - pos, res)) {
8737                         *pos = '\0';
8738                         break;
8739                 }
8740                 pos += res;
8741                 wpa_s = wpa_s->next;
8742         }
8743         return pos - buf;
8744 }
8745
8746
8747 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
8748                                             const char *ifname,
8749                                             char *cmd, size_t *resp_len)
8750 {
8751         struct wpa_supplicant *wpa_s;
8752
8753         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8754                 if (os_strcmp(ifname, wpa_s->ifname) == 0)
8755                         break;
8756         }
8757
8758         if (wpa_s == NULL) {
8759                 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
8760                 if (resp)
8761                         *resp_len = os_strlen(resp);
8762                 else
8763                         *resp_len = 1;
8764                 return resp;
8765         }
8766
8767         return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
8768 }
8769
8770
8771 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
8772                                                char *buf, size_t *resp_len)
8773 {
8774 #ifdef CONFIG_P2P
8775         static const char * cmd[] = {
8776                 "LIST_NETWORKS",
8777                 "P2P_FIND",
8778                 "P2P_STOP_FIND",
8779                 "P2P_LISTEN",
8780                 "P2P_GROUP_ADD",
8781                 "P2P_GET_PASSPHRASE",
8782                 "P2P_SERVICE_UPDATE",
8783                 "P2P_SERVICE_FLUSH",
8784                 "P2P_FLUSH",
8785                 "P2P_CANCEL",
8786                 "P2P_PRESENCE_REQ",
8787                 "P2P_EXT_LISTEN",
8788                 NULL
8789         };
8790         static const char * prefix[] = {
8791 #ifdef ANDROID
8792                 "DRIVER ",
8793 #endif /* ANDROID */
8794                 "GET_NETWORK ",
8795                 "REMOVE_NETWORK ",
8796                 "P2P_FIND ",
8797                 "P2P_CONNECT ",
8798                 "P2P_LISTEN ",
8799                 "P2P_GROUP_REMOVE ",
8800                 "P2P_GROUP_ADD ",
8801                 "P2P_PROV_DISC ",
8802                 "P2P_SERV_DISC_REQ ",
8803                 "P2P_SERV_DISC_CANCEL_REQ ",
8804                 "P2P_SERV_DISC_RESP ",
8805                 "P2P_SERV_DISC_EXTERNAL ",
8806                 "P2P_SERVICE_ADD ",
8807                 "P2P_SERVICE_DEL ",
8808                 "P2P_SERVICE_REP ",
8809                 "P2P_REJECT ",
8810                 "P2P_INVITE ",
8811                 "P2P_PEER ",
8812                 "P2P_SET ",
8813                 "P2P_UNAUTHORIZE ",
8814                 "P2P_PRESENCE_REQ ",
8815                 "P2P_EXT_LISTEN ",
8816                 "P2P_REMOVE_CLIENT ",
8817                 "WPS_NFC_TOKEN ",
8818                 "WPS_NFC_TAG_READ ",
8819                 "NFC_GET_HANDOVER_SEL ",
8820                 "NFC_GET_HANDOVER_REQ ",
8821                 "NFC_REPORT_HANDOVER ",
8822                 "P2P_ASP_PROVISION ",
8823                 "P2P_ASP_PROVISION_RESP ",
8824                 NULL
8825         };
8826         int found = 0;
8827         int i;
8828
8829         if (global->p2p_init_wpa_s == NULL)
8830                 return NULL;
8831
8832         for (i = 0; !found && cmd[i]; i++) {
8833                 if (os_strcmp(buf, cmd[i]) == 0)
8834                         found = 1;
8835         }
8836
8837         for (i = 0; !found && prefix[i]; i++) {
8838                 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
8839                         found = 1;
8840         }
8841
8842         if (found)
8843                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
8844                                                          buf, resp_len);
8845 #endif /* CONFIG_P2P */
8846         return NULL;
8847 }
8848
8849
8850 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
8851                                                char *buf, size_t *resp_len)
8852 {
8853 #ifdef CONFIG_WIFI_DISPLAY
8854         if (global->p2p_init_wpa_s == NULL)
8855                 return NULL;
8856         if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
8857             os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
8858                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
8859                                                          buf, resp_len);
8860 #endif /* CONFIG_WIFI_DISPLAY */
8861         return NULL;
8862 }
8863
8864
8865 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
8866                                            char *buf, size_t *resp_len)
8867 {
8868         char *ret;
8869
8870         ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
8871         if (ret)
8872                 return ret;
8873
8874         ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
8875         if (ret)
8876                 return ret;
8877
8878         return NULL;
8879 }
8880
8881
8882 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
8883 {
8884         char *value;
8885
8886         value = os_strchr(cmd, ' ');
8887         if (value == NULL)
8888                 return -1;
8889         *value++ = '\0';
8890
8891         wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
8892
8893 #ifdef CONFIG_WIFI_DISPLAY
8894         if (os_strcasecmp(cmd, "wifi_display") == 0) {
8895                 wifi_display_enable(global, !!atoi(value));
8896                 return 0;
8897         }
8898 #endif /* CONFIG_WIFI_DISPLAY */
8899
8900         /* Restore cmd to its original value to allow redirection */
8901         value[-1] = ' ';
8902
8903         return -1;
8904 }
8905
8906
8907 #ifndef CONFIG_NO_CONFIG_WRITE
8908 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
8909 {
8910         int ret = 0, saved = 0;
8911         struct wpa_supplicant *wpa_s;
8912
8913         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8914                 if (!wpa_s->conf->update_config) {
8915                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
8916                         continue;
8917                 }
8918
8919                 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
8920                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
8921                         ret = 1;
8922                 } else {
8923                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
8924                         saved++;
8925                 }
8926         }
8927
8928         if (!saved && !ret) {
8929                 wpa_dbg(wpa_s, MSG_DEBUG,
8930                         "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated");
8931                 ret = 1;
8932         }
8933
8934         return ret;
8935 }
8936 #endif /* CONFIG_NO_CONFIG_WRITE */
8937
8938
8939 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
8940                                          char *buf, size_t buflen)
8941 {
8942         char *pos, *end;
8943         int ret;
8944         struct wpa_supplicant *wpa_s;
8945
8946         pos = buf;
8947         end = buf + buflen;
8948
8949 #ifdef CONFIG_P2P
8950         if (global->p2p && !global->p2p_disabled) {
8951                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
8952                                   "\n"
8953                                   "p2p_state=%s\n",
8954                                   MAC2STR(global->p2p_dev_addr),
8955                                   p2p_get_state_txt(global->p2p));
8956                 if (os_snprintf_error(end - pos, ret))
8957                         return pos - buf;
8958                 pos += ret;
8959         } else if (global->p2p) {
8960                 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
8961                 if (os_snprintf_error(end - pos, ret))
8962                         return pos - buf;
8963                 pos += ret;
8964         }
8965 #endif /* CONFIG_P2P */
8966
8967 #ifdef CONFIG_WIFI_DISPLAY
8968         ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
8969                           !!global->wifi_display);
8970         if (os_snprintf_error(end - pos, ret))
8971                 return pos - buf;
8972         pos += ret;
8973 #endif /* CONFIG_WIFI_DISPLAY */
8974
8975         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8976                 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
8977                                   "address=" MACSTR "\n",
8978                                   wpa_s->ifname, MAC2STR(wpa_s->own_addr));
8979                 if (os_snprintf_error(end - pos, ret))
8980                         return pos - buf;
8981                 pos += ret;
8982         }
8983
8984         return pos - buf;
8985 }
8986
8987
8988 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
8989                                                 char *buf, size_t *resp_len)
8990 {
8991         char *reply;
8992         const int reply_size = 2048;
8993         int reply_len;
8994         int level = MSG_DEBUG;
8995
8996         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
8997                 char *pos = os_strchr(buf + 7, ' ');
8998                 if (pos) {
8999                         *pos++ = '\0';
9000                         return wpas_global_ctrl_iface_ifname(global,
9001                                                              buf + 7, pos,
9002                                                              resp_len);
9003                 }
9004         }
9005
9006         reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
9007         if (reply)
9008                 return reply;
9009
9010         if (os_strcmp(buf, "PING") == 0)
9011                 level = MSG_EXCESSIVE;
9012         wpa_hexdump_ascii(level, "RX global ctrl_iface",
9013                           (const u8 *) buf, os_strlen(buf));
9014
9015         reply = os_malloc(reply_size);
9016         if (reply == NULL) {
9017                 *resp_len = 1;
9018                 return NULL;
9019         }
9020
9021         os_memcpy(reply, "OK\n", 3);
9022         reply_len = 3;
9023
9024         if (os_strcmp(buf, "PING") == 0) {
9025                 os_memcpy(reply, "PONG\n", 5);
9026                 reply_len = 5;
9027         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
9028                 if (wpa_supplicant_global_iface_add(global, buf + 14))
9029                         reply_len = -1;
9030         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
9031                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
9032                         reply_len = -1;
9033         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
9034                 reply_len = wpa_supplicant_global_iface_list(
9035                         global, reply, reply_size);
9036         } else if (os_strcmp(buf, "INTERFACES") == 0) {
9037                 reply_len = wpa_supplicant_global_iface_interfaces(
9038                         global, reply, reply_size);
9039         } else if (os_strcmp(buf, "TERMINATE") == 0) {
9040                 wpa_supplicant_terminate_proc(global);
9041         } else if (os_strcmp(buf, "SUSPEND") == 0) {
9042                 wpas_notify_suspend(global);
9043         } else if (os_strcmp(buf, "RESUME") == 0) {
9044                 wpas_notify_resume(global);
9045         } else if (os_strncmp(buf, "SET ", 4) == 0) {
9046                 if (wpas_global_ctrl_iface_set(global, buf + 4)) {
9047 #ifdef CONFIG_P2P
9048                         if (global->p2p_init_wpa_s) {
9049                                 os_free(reply);
9050                                 /* Check if P2P redirection would work for this
9051                                  * command. */
9052                                 return wpa_supplicant_ctrl_iface_process(
9053                                         global->p2p_init_wpa_s,
9054                                         buf, resp_len);
9055                         }
9056 #endif /* CONFIG_P2P */
9057                         reply_len = -1;
9058                 }
9059 #ifndef CONFIG_NO_CONFIG_WRITE
9060         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
9061                 if (wpas_global_ctrl_iface_save_config(global))
9062                         reply_len = -1;
9063 #endif /* CONFIG_NO_CONFIG_WRITE */
9064         } else if (os_strcmp(buf, "STATUS") == 0) {
9065                 reply_len = wpas_global_ctrl_iface_status(global, reply,
9066                                                           reply_size);
9067 #ifdef CONFIG_MODULE_TESTS
9068         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
9069                 int wpas_module_tests(void);
9070                 if (wpas_module_tests() < 0)
9071                         reply_len = -1;
9072 #endif /* CONFIG_MODULE_TESTS */
9073         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
9074                 if (wpa_debug_reopen_file() < 0)
9075                         reply_len = -1;
9076         } else {
9077                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
9078                 reply_len = 16;
9079         }
9080
9081         if (reply_len < 0) {
9082                 os_memcpy(reply, "FAIL\n", 5);
9083                 reply_len = 5;
9084         }
9085
9086         *resp_len = reply_len;
9087         return reply;
9088 }