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