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