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