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