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