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