HS 2.0: Extend ANQP_GET to accept Hotspot 2.0 subtypes
[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         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2167                 txt = "[WPS-AUTH]";
2168         else if (wps_is_selected_pin_registrar(wps_ie))
2169                 txt = "[WPS-PIN]";
2170         else
2171                 txt = "[WPS]";
2172
2173         ret = os_snprintf(pos, end - pos, "%s", txt);
2174         if (ret >= 0 && ret < end - pos)
2175                 pos += ret;
2176         wpabuf_free(wps_ie);
2177         return pos;
2178 }
2179 #endif /* CONFIG_WPS */
2180
2181
2182 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2183                                         char *pos, char *end,
2184                                         const struct wpa_bss *bss)
2185 {
2186 #ifdef CONFIG_WPS
2187         struct wpabuf *wps_ie;
2188         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2189         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2190 #else /* CONFIG_WPS */
2191         return pos;
2192 #endif /* CONFIG_WPS */
2193 }
2194
2195
2196 /* Format one result on one text line into a buffer. */
2197 static int wpa_supplicant_ctrl_iface_scan_result(
2198         struct wpa_supplicant *wpa_s,
2199         const struct wpa_bss *bss, char *buf, size_t buflen)
2200 {
2201         char *pos, *end;
2202         int ret;
2203         const u8 *ie, *ie2, *p2p;
2204
2205         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2206         if (!p2p)
2207                 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2208         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2209             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2210             0)
2211                 return 0; /* Do not show P2P listen discovery results here */
2212
2213         pos = buf;
2214         end = buf + buflen;
2215
2216         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2217                           MAC2STR(bss->bssid), bss->freq, bss->level);
2218         if (ret < 0 || ret >= end - pos)
2219                 return -1;
2220         pos += ret;
2221         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2222         if (ie)
2223                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2224         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2225         if (ie2)
2226                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2227         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2228         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2229                 ret = os_snprintf(pos, end - pos, "[WEP]");
2230                 if (ret < 0 || ret >= end - pos)
2231                         return -1;
2232                 pos += ret;
2233         }
2234         if (bss->caps & IEEE80211_CAP_IBSS) {
2235                 ret = os_snprintf(pos, end - pos, "[IBSS]");
2236                 if (ret < 0 || ret >= end - pos)
2237                         return -1;
2238                 pos += ret;
2239         }
2240         if (bss->caps & IEEE80211_CAP_ESS) {
2241                 ret = os_snprintf(pos, end - pos, "[ESS]");
2242                 if (ret < 0 || ret >= end - pos)
2243                         return -1;
2244                 pos += ret;
2245         }
2246         if (p2p) {
2247                 ret = os_snprintf(pos, end - pos, "[P2P]");
2248                 if (ret < 0 || ret >= end - pos)
2249                         return -1;
2250                 pos += ret;
2251         }
2252 #ifdef CONFIG_HS20
2253         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2254                 ret = os_snprintf(pos, end - pos, "[HS20]");
2255                 if (ret < 0 || ret >= end - pos)
2256                         return -1;
2257                 pos += ret;
2258         }
2259 #endif /* CONFIG_HS20 */
2260
2261         ret = os_snprintf(pos, end - pos, "\t%s",
2262                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
2263         if (ret < 0 || ret >= end - pos)
2264                 return -1;
2265         pos += ret;
2266
2267         ret = os_snprintf(pos, end - pos, "\n");
2268         if (ret < 0 || ret >= end - pos)
2269                 return -1;
2270         pos += ret;
2271
2272         return pos - buf;
2273 }
2274
2275
2276 static int wpa_supplicant_ctrl_iface_scan_results(
2277         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2278 {
2279         char *pos, *end;
2280         struct wpa_bss *bss;
2281         int ret;
2282
2283         pos = buf;
2284         end = buf + buflen;
2285         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2286                           "flags / ssid\n");
2287         if (ret < 0 || ret >= end - pos)
2288                 return pos - buf;
2289         pos += ret;
2290
2291         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2292                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2293                                                             end - pos);
2294                 if (ret < 0 || ret >= end - pos)
2295                         return pos - buf;
2296                 pos += ret;
2297         }
2298
2299         return pos - buf;
2300 }
2301
2302
2303 static int wpa_supplicant_ctrl_iface_select_network(
2304         struct wpa_supplicant *wpa_s, char *cmd)
2305 {
2306         int id;
2307         struct wpa_ssid *ssid;
2308
2309         /* cmd: "<network id>" or "any" */
2310         if (os_strcmp(cmd, "any") == 0) {
2311                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2312                 ssid = NULL;
2313         } else {
2314                 id = atoi(cmd);
2315                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2316
2317                 ssid = wpa_config_get_network(wpa_s->conf, id);
2318                 if (ssid == NULL) {
2319                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2320                                    "network id=%d", id);
2321                         return -1;
2322                 }
2323                 if (ssid->disabled == 2) {
2324                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2325                                    "SELECT_NETWORK with persistent P2P group");
2326                         return -1;
2327                 }
2328         }
2329
2330         wpa_supplicant_select_network(wpa_s, ssid);
2331
2332         return 0;
2333 }
2334
2335
2336 static int wpa_supplicant_ctrl_iface_enable_network(
2337         struct wpa_supplicant *wpa_s, char *cmd)
2338 {
2339         int id;
2340         struct wpa_ssid *ssid;
2341
2342         /* cmd: "<network id>" or "all" */
2343         if (os_strcmp(cmd, "all") == 0) {
2344                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2345                 ssid = NULL;
2346         } else {
2347                 id = atoi(cmd);
2348                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2349
2350                 ssid = wpa_config_get_network(wpa_s->conf, id);
2351                 if (ssid == NULL) {
2352                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2353                                    "network id=%d", id);
2354                         return -1;
2355                 }
2356                 if (ssid->disabled == 2) {
2357                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2358                                    "ENABLE_NETWORK with persistent P2P group");
2359                         return -1;
2360                 }
2361
2362                 if (os_strstr(cmd, " no-connect")) {
2363                         ssid->disabled = 0;
2364                         return 0;
2365                 }
2366         }
2367         wpa_supplicant_enable_network(wpa_s, ssid);
2368
2369         return 0;
2370 }
2371
2372
2373 static int wpa_supplicant_ctrl_iface_disable_network(
2374         struct wpa_supplicant *wpa_s, char *cmd)
2375 {
2376         int id;
2377         struct wpa_ssid *ssid;
2378
2379         /* cmd: "<network id>" or "all" */
2380         if (os_strcmp(cmd, "all") == 0) {
2381                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2382                 ssid = NULL;
2383         } else {
2384                 id = atoi(cmd);
2385                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2386
2387                 ssid = wpa_config_get_network(wpa_s->conf, id);
2388                 if (ssid == NULL) {
2389                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2390                                    "network id=%d", id);
2391                         return -1;
2392                 }
2393                 if (ssid->disabled == 2) {
2394                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2395                                    "DISABLE_NETWORK with persistent P2P "
2396                                    "group");
2397                         return -1;
2398                 }
2399         }
2400         wpa_supplicant_disable_network(wpa_s, ssid);
2401
2402         return 0;
2403 }
2404
2405
2406 static int wpa_supplicant_ctrl_iface_add_network(
2407         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2408 {
2409         struct wpa_ssid *ssid;
2410         int ret;
2411
2412         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2413
2414         ssid = wpa_config_add_network(wpa_s->conf);
2415         if (ssid == NULL)
2416                 return -1;
2417
2418         wpas_notify_network_added(wpa_s, ssid);
2419
2420         ssid->disabled = 1;
2421         wpa_config_set_network_defaults(ssid);
2422
2423         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2424         if (ret < 0 || (size_t) ret >= buflen)
2425                 return -1;
2426         return ret;
2427 }
2428
2429
2430 static int wpa_supplicant_ctrl_iface_remove_network(
2431         struct wpa_supplicant *wpa_s, char *cmd)
2432 {
2433         int id;
2434         struct wpa_ssid *ssid;
2435         int was_disabled;
2436
2437         /* cmd: "<network id>" or "all" */
2438         if (os_strcmp(cmd, "all") == 0) {
2439                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2440                 if (wpa_s->sched_scanning)
2441                         wpa_supplicant_cancel_sched_scan(wpa_s);
2442
2443                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2444                 if (wpa_s->current_ssid) {
2445 #ifdef CONFIG_SME
2446                         wpa_s->sme.prev_bssid_set = 0;
2447 #endif /* CONFIG_SME */
2448                         wpa_sm_set_config(wpa_s->wpa, NULL);
2449                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2450                         wpa_supplicant_deauthenticate(
2451                                 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2452                 }
2453                 ssid = wpa_s->conf->ssid;
2454                 while (ssid) {
2455                         struct wpa_ssid *remove_ssid = ssid;
2456                         id = ssid->id;
2457                         ssid = ssid->next;
2458                         wpas_notify_network_removed(wpa_s, remove_ssid);
2459                         wpa_config_remove_network(wpa_s->conf, id);
2460                 }
2461                 return 0;
2462         }
2463
2464         id = atoi(cmd);
2465         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2466
2467         ssid = wpa_config_get_network(wpa_s->conf, id);
2468         if (ssid)
2469                 wpas_notify_network_removed(wpa_s, ssid);
2470         if (ssid == NULL) {
2471                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2472                            "id=%d", id);
2473                 return -1;
2474         }
2475
2476         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2477 #ifdef CONFIG_SME
2478                 wpa_s->sme.prev_bssid_set = 0;
2479 #endif /* CONFIG_SME */
2480                 /*
2481                  * Invalidate the EAP session cache if the current or
2482                  * previously used network is removed.
2483                  */
2484                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2485         }
2486
2487         if (ssid == wpa_s->current_ssid) {
2488                 wpa_sm_set_config(wpa_s->wpa, NULL);
2489                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2490
2491                 wpa_supplicant_deauthenticate(wpa_s,
2492                                               WLAN_REASON_DEAUTH_LEAVING);
2493         }
2494
2495         was_disabled = ssid->disabled;
2496
2497         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2498                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2499                            "network id=%d", id);
2500                 return -1;
2501         }
2502
2503         if (!was_disabled && wpa_s->sched_scanning) {
2504                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2505                            "network from filters");
2506                 wpa_supplicant_cancel_sched_scan(wpa_s);
2507                 wpa_supplicant_req_scan(wpa_s, 0, 0);
2508         }
2509
2510         return 0;
2511 }
2512
2513
2514 static int wpa_supplicant_ctrl_iface_set_network(
2515         struct wpa_supplicant *wpa_s, char *cmd)
2516 {
2517         int id;
2518         struct wpa_ssid *ssid;
2519         char *name, *value;
2520
2521         /* cmd: "<network id> <variable name> <value>" */
2522         name = os_strchr(cmd, ' ');
2523         if (name == NULL)
2524                 return -1;
2525         *name++ = '\0';
2526
2527         value = os_strchr(name, ' ');
2528         if (value == NULL)
2529                 return -1;
2530         *value++ = '\0';
2531
2532         id = atoi(cmd);
2533         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2534                    id, name);
2535         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2536                               (u8 *) value, os_strlen(value));
2537
2538         ssid = wpa_config_get_network(wpa_s->conf, id);
2539         if (ssid == NULL) {
2540                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2541                            "id=%d", id);
2542                 return -1;
2543         }
2544
2545         if (wpa_config_set(ssid, name, value, 0) < 0) {
2546                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2547                            "variable '%s'", name);
2548                 return -1;
2549         }
2550
2551         if (os_strcmp(name, "bssid") != 0 &&
2552             os_strcmp(name, "priority") != 0)
2553                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2554
2555         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2556                 /*
2557                  * Invalidate the EAP session cache if anything in the current
2558                  * or previously used configuration changes.
2559                  */
2560                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2561         }
2562
2563         if ((os_strcmp(name, "psk") == 0 &&
2564              value[0] == '"' && ssid->ssid_len) ||
2565             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2566                 wpa_config_update_psk(ssid);
2567         else if (os_strcmp(name, "priority") == 0)
2568                 wpa_config_update_prio_list(wpa_s->conf);
2569
2570         return 0;
2571 }
2572
2573
2574 static int wpa_supplicant_ctrl_iface_get_network(
2575         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2576 {
2577         int id;
2578         size_t res;
2579         struct wpa_ssid *ssid;
2580         char *name, *value;
2581
2582         /* cmd: "<network id> <variable name>" */
2583         name = os_strchr(cmd, ' ');
2584         if (name == NULL || buflen == 0)
2585                 return -1;
2586         *name++ = '\0';
2587
2588         id = atoi(cmd);
2589         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
2590                    id, name);
2591
2592         ssid = wpa_config_get_network(wpa_s->conf, id);
2593         if (ssid == NULL) {
2594                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2595                            "id=%d", id);
2596                 return -1;
2597         }
2598
2599         value = wpa_config_get_no_key(ssid, name);
2600         if (value == NULL) {
2601                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
2602                            "variable '%s'", name);
2603                 return -1;
2604         }
2605
2606         res = os_strlcpy(buf, value, buflen);
2607         if (res >= buflen) {
2608                 os_free(value);
2609                 return -1;
2610         }
2611
2612         os_free(value);
2613
2614         return res;
2615 }
2616
2617
2618 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
2619                                                 char *buf, size_t buflen)
2620 {
2621         char *pos, *end;
2622         struct wpa_cred *cred;
2623         int ret;
2624
2625         pos = buf;
2626         end = buf + buflen;
2627         ret = os_snprintf(pos, end - pos,
2628                           "cred id / realm / username / domain / imsi\n");
2629         if (ret < 0 || ret >= end - pos)
2630                 return pos - buf;
2631         pos += ret;
2632
2633         cred = wpa_s->conf->cred;
2634         while (cred) {
2635                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
2636                                   cred->id, cred->realm ? cred->realm : "",
2637                                   cred->username ? cred->username : "",
2638                                   cred->domain ? cred->domain[0] : "",
2639                                   cred->imsi ? cred->imsi : "");
2640                 if (ret < 0 || ret >= end - pos)
2641                         return pos - buf;
2642                 pos += ret;
2643
2644                 cred = cred->next;
2645         }
2646
2647         return pos - buf;
2648 }
2649
2650
2651 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2652                                               char *buf, size_t buflen)
2653 {
2654         struct wpa_cred *cred;
2655         int ret;
2656
2657         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2658
2659         cred = wpa_config_add_cred(wpa_s->conf);
2660         if (cred == NULL)
2661                 return -1;
2662
2663         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2664         if (ret < 0 || (size_t) ret >= buflen)
2665                 return -1;
2666         return ret;
2667 }
2668
2669
2670 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
2671                                  struct wpa_cred *cred)
2672 {
2673         struct wpa_ssid *ssid;
2674         char str[20];
2675
2676         if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) {
2677                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
2678                 return -1;
2679         }
2680
2681         /* Remove any network entry created based on the removed credential */
2682         ssid = wpa_s->conf->ssid;
2683         while (ssid) {
2684                 if (ssid->parent_cred == cred) {
2685                         wpa_printf(MSG_DEBUG, "Remove network id %d since it "
2686                                    "used the removed credential", ssid->id);
2687                         os_snprintf(str, sizeof(str), "%d", ssid->id);
2688                         ssid = ssid->next;
2689                         wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
2690                 } else
2691                         ssid = ssid->next;
2692         }
2693
2694         return 0;
2695 }
2696
2697
2698 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2699                                                  char *cmd)
2700 {
2701         int id;
2702         struct wpa_cred *cred, *prev;
2703
2704         /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
2705          * "provisioning_sp=<FQDN> */
2706         if (os_strcmp(cmd, "all") == 0) {
2707                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2708                 cred = wpa_s->conf->cred;
2709                 while (cred) {
2710                         prev = cred;
2711                         cred = cred->next;
2712                         wpas_ctrl_remove_cred(wpa_s, prev);
2713                 }
2714                 return 0;
2715         }
2716
2717         if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
2718                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
2719                            cmd + 8);
2720                 cred = wpa_s->conf->cred;
2721                 while (cred) {
2722                         prev = cred;
2723                         cred = cred->next;
2724                         if (prev->domain) {
2725                                 size_t i;
2726                                 for (i = 0; i < prev->num_domain; i++) {
2727                                         if (os_strcmp(prev->domain[i], cmd + 8)
2728                                             != 0)
2729                                                 continue;
2730                                         wpas_ctrl_remove_cred(wpa_s, prev);
2731                                         break;
2732                                 }
2733                         }
2734                 }
2735                 return 0;
2736         }
2737
2738         if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
2739                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
2740                            cmd + 16);
2741                 cred = wpa_s->conf->cred;
2742                 while (cred) {
2743                         prev = cred;
2744                         cred = cred->next;
2745                         if (prev->provisioning_sp &&
2746                             os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
2747                                 wpas_ctrl_remove_cred(wpa_s, prev);
2748                 }
2749                 return 0;
2750         }
2751
2752         id = atoi(cmd);
2753         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2754
2755         cred = wpa_config_get_cred(wpa_s->conf, id);
2756         return wpas_ctrl_remove_cred(wpa_s, cred);
2757 }
2758
2759
2760 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2761                                               char *cmd)
2762 {
2763         int id;
2764         struct wpa_cred *cred;
2765         char *name, *value;
2766
2767         /* cmd: "<cred id> <variable name> <value>" */
2768         name = os_strchr(cmd, ' ');
2769         if (name == NULL)
2770                 return -1;
2771         *name++ = '\0';
2772
2773         value = os_strchr(name, ' ');
2774         if (value == NULL)
2775                 return -1;
2776         *value++ = '\0';
2777
2778         id = atoi(cmd);
2779         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2780                    id, name);
2781         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2782                               (u8 *) value, os_strlen(value));
2783
2784         cred = wpa_config_get_cred(wpa_s->conf, id);
2785         if (cred == NULL) {
2786                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2787                            id);
2788                 return -1;
2789         }
2790
2791         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2792                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2793                            "variable '%s'", name);
2794                 return -1;
2795         }
2796
2797         return 0;
2798 }
2799
2800
2801 #ifndef CONFIG_NO_CONFIG_WRITE
2802 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2803 {
2804         int ret;
2805
2806         if (!wpa_s->conf->update_config) {
2807                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2808                            "to update configuration (update_config=0)");
2809                 return -1;
2810         }
2811
2812         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2813         if (ret) {
2814                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2815                            "update configuration");
2816         } else {
2817                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2818                            " updated");
2819         }
2820
2821         return ret;
2822 }
2823 #endif /* CONFIG_NO_CONFIG_WRITE */
2824
2825
2826 struct cipher_info {
2827         unsigned int capa;
2828         const char *name;
2829         int group_only;
2830 };
2831
2832 static const struct cipher_info ciphers[] = {
2833         { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
2834         { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
2835         { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
2836         { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
2837         { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
2838         { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
2839         { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
2840         { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
2841 };
2842
2843
2844 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2845                                               struct wpa_driver_capa *capa,
2846                                               char *buf, size_t buflen)
2847 {
2848         int ret;
2849         char *pos, *end;
2850         size_t len;
2851         unsigned int i;
2852
2853         pos = buf;
2854         end = pos + buflen;
2855
2856         if (res < 0) {
2857                 if (strict)
2858                         return 0;
2859                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2860                 if (len >= buflen)
2861                         return -1;
2862                 return len;
2863         }
2864
2865         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
2866                 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
2867                         ret = os_snprintf(pos, end - pos, "%s%s",
2868                                           pos == buf ? "" : " ",
2869                                           ciphers[i].name);
2870                         if (ret < 0 || ret >= end - pos)
2871                                 return pos - buf;
2872                         pos += ret;
2873                 }
2874         }
2875
2876         return pos - buf;
2877 }
2878
2879
2880 static int ctrl_iface_get_capability_group(int res, char *strict,
2881                                            struct wpa_driver_capa *capa,
2882                                            char *buf, size_t buflen)
2883 {
2884         int ret;
2885         char *pos, *end;
2886         size_t len;
2887         unsigned int i;
2888
2889         pos = buf;
2890         end = pos + buflen;
2891
2892         if (res < 0) {
2893                 if (strict)
2894                         return 0;
2895                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2896                 if (len >= buflen)
2897                         return -1;
2898                 return len;
2899         }
2900
2901         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
2902                 if (capa->enc & ciphers[i].capa) {
2903                         ret = os_snprintf(pos, end - pos, "%s%s",
2904                                           pos == buf ? "" : " ",
2905                                           ciphers[i].name);
2906                         if (ret < 0 || ret >= end - pos)
2907                                 return pos - buf;
2908                         pos += ret;
2909                 }
2910         }
2911
2912         return pos - buf;
2913 }
2914
2915
2916 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2917                                               struct wpa_driver_capa *capa,
2918                                               char *buf, size_t buflen)
2919 {
2920         int ret;
2921         char *pos, *end;
2922         size_t len;
2923
2924         pos = buf;
2925         end = pos + buflen;
2926
2927         if (res < 0) {
2928                 if (strict)
2929                         return 0;
2930                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
2931                                  "NONE", buflen);
2932                 if (len >= buflen)
2933                         return -1;
2934                 return len;
2935         }
2936
2937         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
2938         if (ret < 0 || ret >= end - pos)
2939                 return pos - buf;
2940         pos += ret;
2941
2942         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2943                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2944                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
2945                 if (ret < 0 || ret >= end - pos)
2946                         return pos - buf;
2947                 pos += ret;
2948         }
2949
2950         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2951                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2952                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
2953                 if (ret < 0 || ret >= end - pos)
2954                         return pos - buf;
2955                 pos += ret;
2956         }
2957
2958         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2959                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
2960                 if (ret < 0 || ret >= end - pos)
2961                         return pos - buf;
2962                 pos += ret;
2963         }
2964
2965         return pos - buf;
2966 }
2967
2968
2969 static int ctrl_iface_get_capability_proto(int res, char *strict,
2970                                            struct wpa_driver_capa *capa,
2971                                            char *buf, size_t buflen)
2972 {
2973         int ret;
2974         char *pos, *end;
2975         size_t len;
2976
2977         pos = buf;
2978         end = pos + buflen;
2979
2980         if (res < 0) {
2981                 if (strict)
2982                         return 0;
2983                 len = os_strlcpy(buf, "RSN WPA", buflen);
2984                 if (len >= buflen)
2985                         return -1;
2986                 return len;
2987         }
2988
2989         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2990                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2991                 ret = os_snprintf(pos, end - pos, "%sRSN",
2992                                   pos == buf ? "" : " ");
2993                 if (ret < 0 || ret >= end - pos)
2994                         return pos - buf;
2995                 pos += ret;
2996         }
2997
2998         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2999                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
3000                 ret = os_snprintf(pos, end - pos, "%sWPA",
3001                                   pos == buf ? "" : " ");
3002                 if (ret < 0 || ret >= end - pos)
3003                         return pos - buf;
3004                 pos += ret;
3005         }
3006
3007         return pos - buf;
3008 }
3009
3010
3011 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
3012                                               struct wpa_driver_capa *capa,
3013                                               char *buf, size_t buflen)
3014 {
3015         int ret;
3016         char *pos, *end;
3017         size_t len;
3018
3019         pos = buf;
3020         end = pos + buflen;
3021
3022         if (res < 0) {
3023                 if (strict)
3024                         return 0;
3025                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
3026                 if (len >= buflen)
3027                         return -1;
3028                 return len;
3029         }
3030
3031         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
3032                 ret = os_snprintf(pos, end - pos, "%sOPEN",
3033                                   pos == buf ? "" : " ");
3034                 if (ret < 0 || ret >= end - pos)
3035                         return pos - buf;
3036                 pos += ret;
3037         }
3038
3039         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
3040                 ret = os_snprintf(pos, end - pos, "%sSHARED",
3041                                   pos == buf ? "" : " ");
3042                 if (ret < 0 || ret >= end - pos)
3043                         return pos - buf;
3044                 pos += ret;
3045         }
3046
3047         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
3048                 ret = os_snprintf(pos, end - pos, "%sLEAP",
3049                                   pos == buf ? "" : " ");
3050                 if (ret < 0 || ret >= end - pos)
3051                         return pos - buf;
3052                 pos += ret;
3053         }
3054
3055         return pos - buf;
3056 }
3057
3058
3059 static int ctrl_iface_get_capability_modes(int res, char *strict,
3060                                            struct wpa_driver_capa *capa,
3061                                            char *buf, size_t buflen)
3062 {
3063         int ret;
3064         char *pos, *end;
3065         size_t len;
3066
3067         pos = buf;
3068         end = pos + buflen;
3069
3070         if (res < 0) {
3071                 if (strict)
3072                         return 0;
3073                 len = os_strlcpy(buf, "IBSS AP", buflen);
3074                 if (len >= buflen)
3075                         return -1;
3076                 return len;
3077         }
3078
3079         if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
3080                 ret = os_snprintf(pos, end - pos, "%sIBSS",
3081                                   pos == buf ? "" : " ");
3082                 if (ret < 0 || ret >= end - pos)
3083                         return pos - buf;
3084                 pos += ret;
3085         }
3086
3087         if (capa->flags & WPA_DRIVER_FLAGS_AP) {
3088                 ret = os_snprintf(pos, end - pos, "%sAP",
3089                                   pos == buf ? "" : " ");
3090                 if (ret < 0 || ret >= end - pos)
3091                         return pos - buf;
3092                 pos += ret;
3093         }
3094
3095         return pos - buf;
3096 }
3097
3098
3099 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
3100                                               char *buf, size_t buflen)
3101 {
3102         struct hostapd_channel_data *chnl;
3103         int ret, i, j;
3104         char *pos, *end, *hmode;
3105
3106         pos = buf;
3107         end = pos + buflen;
3108
3109         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3110                 switch (wpa_s->hw.modes[j].mode) {
3111                 case HOSTAPD_MODE_IEEE80211B:
3112                         hmode = "B";
3113                         break;
3114                 case HOSTAPD_MODE_IEEE80211G:
3115                         hmode = "G";
3116                         break;
3117                 case HOSTAPD_MODE_IEEE80211A:
3118                         hmode = "A";
3119                         break;
3120                 case HOSTAPD_MODE_IEEE80211AD:
3121                         hmode = "AD";
3122                         break;
3123                 default:
3124                         continue;
3125                 }
3126                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
3127                 if (ret < 0 || ret >= end - pos)
3128                         return pos - buf;
3129                 pos += ret;
3130                 chnl = wpa_s->hw.modes[j].channels;
3131                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3132                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3133                                 continue;
3134                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
3135                         if (ret < 0 || ret >= end - pos)
3136                                 return pos - buf;
3137                         pos += ret;
3138                 }
3139                 ret = os_snprintf(pos, end - pos, "\n");
3140                 if (ret < 0 || ret >= end - pos)
3141                         return pos - buf;
3142                 pos += ret;
3143         }
3144
3145         return pos - buf;
3146 }
3147
3148
3149 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
3150                                           char *buf, size_t buflen)
3151 {
3152         struct hostapd_channel_data *chnl;
3153         int ret, i, j;
3154         char *pos, *end, *hmode;
3155
3156         pos = buf;
3157         end = pos + buflen;
3158
3159         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3160                 switch (wpa_s->hw.modes[j].mode) {
3161                 case HOSTAPD_MODE_IEEE80211B:
3162                         hmode = "B";
3163                         break;
3164                 case HOSTAPD_MODE_IEEE80211G:
3165                         hmode = "G";
3166                         break;
3167                 case HOSTAPD_MODE_IEEE80211A:
3168                         hmode = "A";
3169                         break;
3170                 case HOSTAPD_MODE_IEEE80211AD:
3171                         hmode = "AD";
3172                         break;
3173                 default:
3174                         continue;
3175                 }
3176                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
3177                                   hmode);
3178                 if (ret < 0 || ret >= end - pos)
3179                         return pos - buf;
3180                 pos += ret;
3181                 chnl = wpa_s->hw.modes[j].channels;
3182                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3183                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3184                                 continue;
3185                         ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
3186                                           chnl[i].chan, chnl[i].freq,
3187                                           chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
3188                                           " (NO_IBSS)" : "",
3189                                           chnl[i].flag & HOSTAPD_CHAN_RADAR ?
3190                                           " (DFS)" : "");
3191
3192                         if (ret < 0 || ret >= end - pos)
3193                                 return pos - buf;
3194                         pos += ret;
3195                 }
3196                 ret = os_snprintf(pos, end - pos, "\n");
3197                 if (ret < 0 || ret >= end - pos)
3198                         return pos - buf;
3199                 pos += ret;
3200         }
3201
3202         return pos - buf;
3203 }
3204
3205
3206 static int wpa_supplicant_ctrl_iface_get_capability(
3207         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
3208         size_t buflen)
3209 {
3210         struct wpa_driver_capa capa;
3211         int res;
3212         char *strict;
3213         char field[30];
3214         size_t len;
3215
3216         /* Determine whether or not strict checking was requested */
3217         len = os_strlcpy(field, _field, sizeof(field));
3218         if (len >= sizeof(field))
3219                 return -1;
3220         strict = os_strchr(field, ' ');
3221         if (strict != NULL) {
3222                 *strict++ = '\0';
3223                 if (os_strcmp(strict, "strict") != 0)
3224                         return -1;
3225         }
3226
3227         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
3228                 field, strict ? strict : "");
3229
3230         if (os_strcmp(field, "eap") == 0) {
3231                 return eap_get_names(buf, buflen);
3232         }
3233
3234         res = wpa_drv_get_capa(wpa_s, &capa);
3235
3236         if (os_strcmp(field, "pairwise") == 0)
3237                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
3238                                                           buf, buflen);
3239
3240         if (os_strcmp(field, "group") == 0)
3241                 return ctrl_iface_get_capability_group(res, strict, &capa,
3242                                                        buf, buflen);
3243
3244         if (os_strcmp(field, "key_mgmt") == 0)
3245                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3246                                                           buf, buflen);
3247
3248         if (os_strcmp(field, "proto") == 0)
3249                 return ctrl_iface_get_capability_proto(res, strict, &capa,
3250                                                        buf, buflen);
3251
3252         if (os_strcmp(field, "auth_alg") == 0)
3253                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
3254                                                           buf, buflen);
3255
3256         if (os_strcmp(field, "modes") == 0)
3257                 return ctrl_iface_get_capability_modes(res, strict, &capa,
3258                                                        buf, buflen);
3259
3260         if (os_strcmp(field, "channels") == 0)
3261                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3262
3263         if (os_strcmp(field, "freq") == 0)
3264                 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
3265
3266 #ifdef CONFIG_TDLS
3267         if (os_strcmp(field, "tdls") == 0)
3268                 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
3269 #endif /* CONFIG_TDLS */
3270
3271         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3272                    field);
3273
3274         return -1;
3275 }
3276
3277
3278 #ifdef CONFIG_INTERWORKING
3279 static char * anqp_add_hex(char *pos, char *end, const char *title,
3280                            struct wpabuf *data)
3281 {
3282         char *start = pos;
3283         size_t i;
3284         int ret;
3285         const u8 *d;
3286
3287         if (data == NULL)
3288                 return start;
3289
3290         ret = os_snprintf(pos, end - pos, "%s=", title);
3291         if (ret < 0 || ret >= end - pos)
3292                 return start;
3293         pos += ret;
3294
3295         d = wpabuf_head_u8(data);
3296         for (i = 0; i < wpabuf_len(data); i++) {
3297                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
3298                 if (ret < 0 || ret >= end - pos)
3299                         return start;
3300                 pos += ret;
3301         }
3302
3303         ret = os_snprintf(pos, end - pos, "\n");
3304         if (ret < 0 || ret >= end - pos)
3305                 return start;
3306         pos += ret;
3307
3308         return pos;
3309 }
3310 #endif /* CONFIG_INTERWORKING */
3311
3312
3313 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3314                           unsigned long mask, char *buf, size_t buflen)
3315 {
3316         size_t i;
3317         int ret;
3318         char *pos, *end;
3319         const u8 *ie, *ie2;
3320
3321         pos = buf;
3322         end = buf + buflen;
3323
3324         if (mask & WPA_BSS_MASK_ID) {
3325                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3326                 if (ret < 0 || ret >= end - pos)
3327                         return 0;
3328                 pos += ret;
3329         }
3330
3331         if (mask & WPA_BSS_MASK_BSSID) {
3332                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3333                                   MAC2STR(bss->bssid));
3334                 if (ret < 0 || ret >= end - pos)
3335                         return 0;
3336                 pos += ret;
3337         }
3338
3339         if (mask & WPA_BSS_MASK_FREQ) {
3340                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3341                 if (ret < 0 || ret >= end - pos)
3342                         return 0;
3343                 pos += ret;
3344         }
3345
3346         if (mask & WPA_BSS_MASK_BEACON_INT) {
3347                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3348                                   bss->beacon_int);
3349                 if (ret < 0 || ret >= end - pos)
3350                         return 0;
3351                 pos += ret;
3352         }
3353
3354         if (mask & WPA_BSS_MASK_CAPABILITIES) {
3355                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3356                                   bss->caps);
3357                 if (ret < 0 || ret >= end - pos)
3358                         return 0;
3359                 pos += ret;
3360         }
3361
3362         if (mask & WPA_BSS_MASK_QUAL) {
3363                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3364                 if (ret < 0 || ret >= end - pos)
3365                         return 0;
3366                 pos += ret;
3367         }
3368
3369         if (mask & WPA_BSS_MASK_NOISE) {
3370                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
3371                 if (ret < 0 || ret >= end - pos)
3372                         return 0;
3373                 pos += ret;
3374         }
3375
3376         if (mask & WPA_BSS_MASK_LEVEL) {
3377                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
3378                 if (ret < 0 || ret >= end - pos)
3379                         return 0;
3380                 pos += ret;
3381         }
3382
3383         if (mask & WPA_BSS_MASK_TSF) {
3384                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
3385                                   (unsigned long long) bss->tsf);
3386                 if (ret < 0 || ret >= end - pos)
3387                         return 0;
3388                 pos += ret;
3389         }
3390
3391         if (mask & WPA_BSS_MASK_AGE) {
3392                 struct os_reltime now;
3393
3394                 os_get_reltime(&now);
3395                 ret = os_snprintf(pos, end - pos, "age=%d\n",
3396                                   (int) (now.sec - bss->last_update.sec));
3397                 if (ret < 0 || ret >= end - pos)
3398                         return 0;
3399                 pos += ret;
3400         }
3401
3402         if (mask & WPA_BSS_MASK_IE) {
3403                 ret = os_snprintf(pos, end - pos, "ie=");
3404                 if (ret < 0 || ret >= end - pos)
3405                         return 0;
3406                 pos += ret;
3407
3408                 ie = (const u8 *) (bss + 1);
3409                 for (i = 0; i < bss->ie_len; i++) {
3410                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
3411                         if (ret < 0 || ret >= end - pos)
3412                                 return 0;
3413                         pos += ret;
3414                 }
3415
3416                 ret = os_snprintf(pos, end - pos, "\n");
3417                 if (ret < 0 || ret >= end - pos)
3418                         return 0;
3419                 pos += ret;
3420         }
3421
3422         if (mask & WPA_BSS_MASK_FLAGS) {
3423                 ret = os_snprintf(pos, end - pos, "flags=");
3424                 if (ret < 0 || ret >= end - pos)
3425                         return 0;
3426                 pos += ret;
3427
3428                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3429                 if (ie)
3430                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
3431                                                     2 + ie[1]);
3432                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3433                 if (ie2)
3434                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
3435                                                     2 + ie2[1]);
3436                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3437                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
3438                         ret = os_snprintf(pos, end - pos, "[WEP]");
3439                         if (ret < 0 || ret >= end - pos)
3440                                 return 0;
3441                         pos += ret;
3442                 }
3443                 if (bss->caps & IEEE80211_CAP_IBSS) {
3444                         ret = os_snprintf(pos, end - pos, "[IBSS]");
3445                         if (ret < 0 || ret >= end - pos)
3446                                 return 0;
3447                         pos += ret;
3448                 }
3449                 if (bss->caps & IEEE80211_CAP_ESS) {
3450                         ret = os_snprintf(pos, end - pos, "[ESS]");
3451                         if (ret < 0 || ret >= end - pos)
3452                                 return 0;
3453                         pos += ret;
3454                 }
3455                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
3456                     wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
3457                         ret = os_snprintf(pos, end - pos, "[P2P]");
3458                         if (ret < 0 || ret >= end - pos)
3459                                 return 0;
3460                         pos += ret;
3461                 }
3462 #ifdef CONFIG_HS20
3463                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
3464                         ret = os_snprintf(pos, end - pos, "[HS20]");
3465                         if (ret < 0 || ret >= end - pos)
3466                                 return 0;
3467                         pos += ret;
3468                 }
3469 #endif /* CONFIG_HS20 */
3470
3471                 ret = os_snprintf(pos, end - pos, "\n");
3472                 if (ret < 0 || ret >= end - pos)
3473                         return 0;
3474                 pos += ret;
3475         }
3476
3477         if (mask & WPA_BSS_MASK_SSID) {
3478                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
3479                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
3480                 if (ret < 0 || ret >= end - pos)
3481                         return 0;
3482                 pos += ret;
3483         }
3484
3485 #ifdef CONFIG_WPS
3486         if (mask & WPA_BSS_MASK_WPS_SCAN) {
3487                 ie = (const u8 *) (bss + 1);
3488                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
3489                 if (ret < 0 || ret >= end - pos)
3490                         return 0;
3491                 pos += ret;
3492         }
3493 #endif /* CONFIG_WPS */
3494
3495 #ifdef CONFIG_P2P
3496         if (mask & WPA_BSS_MASK_P2P_SCAN) {
3497                 ie = (const u8 *) (bss + 1);
3498                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
3499                 if (ret < 0 || ret >= end - pos)
3500                         return 0;
3501                 pos += ret;
3502         }
3503 #endif /* CONFIG_P2P */
3504
3505 #ifdef CONFIG_WIFI_DISPLAY
3506         if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
3507                 struct wpabuf *wfd;
3508                 ie = (const u8 *) (bss + 1);
3509                 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
3510                                                   WFD_IE_VENDOR_TYPE);
3511                 if (wfd) {
3512                         ret = os_snprintf(pos, end - pos, "wfd_subelems=");
3513                         if (ret < 0 || ret >= end - pos) {
3514                                 wpabuf_free(wfd);
3515                                 return 0;
3516                         }
3517                         pos += ret;
3518
3519                         pos += wpa_snprintf_hex(pos, end - pos,
3520                                                 wpabuf_head(wfd),
3521                                                 wpabuf_len(wfd));
3522                         wpabuf_free(wfd);
3523
3524                         ret = os_snprintf(pos, end - pos, "\n");
3525                         if (ret < 0 || ret >= end - pos)
3526                                 return 0;
3527                         pos += ret;
3528                 }
3529         }
3530 #endif /* CONFIG_WIFI_DISPLAY */
3531
3532 #ifdef CONFIG_INTERWORKING
3533         if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
3534                 struct wpa_bss_anqp *anqp = bss->anqp;
3535                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
3536                                    anqp->venue_name);
3537                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
3538                                    anqp->network_auth_type);
3539                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
3540                                    anqp->roaming_consortium);
3541                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
3542                                    anqp->ip_addr_type_availability);
3543                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
3544                                    anqp->nai_realm);
3545                 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
3546                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
3547                                    anqp->domain_name);
3548 #ifdef CONFIG_HS20
3549                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
3550                                    anqp->hs20_operator_friendly_name);
3551                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
3552                                    anqp->hs20_wan_metrics);
3553                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
3554                                    anqp->hs20_connection_capability);
3555                 pos = anqp_add_hex(pos, end, "hs20_operating_class",
3556                                    anqp->hs20_operating_class);
3557                 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
3558                                    anqp->hs20_osu_providers_list);
3559 #endif /* CONFIG_HS20 */
3560         }
3561 #endif /* CONFIG_INTERWORKING */
3562
3563         if (mask & WPA_BSS_MASK_DELIM) {
3564                 ret = os_snprintf(pos, end - pos, "====\n");
3565                 if (ret < 0 || ret >= end - pos)
3566                         return 0;
3567                 pos += ret;
3568         }
3569
3570         return pos - buf;
3571 }
3572
3573
3574 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
3575                                          const char *cmd, char *buf,
3576                                          size_t buflen)
3577 {
3578         u8 bssid[ETH_ALEN];
3579         size_t i;
3580         struct wpa_bss *bss;
3581         struct wpa_bss *bsslast = NULL;
3582         struct dl_list *next;
3583         int ret = 0;
3584         int len;
3585         char *ctmp;
3586         unsigned long mask = WPA_BSS_MASK_ALL;
3587
3588         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
3589                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
3590                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
3591                                             list_id);
3592                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
3593                                                list_id);
3594                 } else { /* N1-N2 */
3595                         unsigned int id1, id2;
3596
3597                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
3598                                 wpa_printf(MSG_INFO, "Wrong BSS range "
3599                                            "format");
3600                                 return 0;
3601                         }
3602
3603                         if (*(cmd + 6) == '-')
3604                                 id1 = 0;
3605                         else
3606                                 id1 = atoi(cmd + 6);
3607                         ctmp++;
3608                         if (*ctmp >= '0' && *ctmp <= '9')
3609                                 id2 = atoi(ctmp);
3610                         else
3611                                 id2 = (unsigned int) -1;
3612                         bss = wpa_bss_get_id_range(wpa_s, id1, id2);
3613                         if (id2 == (unsigned int) -1)
3614                                 bsslast = dl_list_last(&wpa_s->bss_id,
3615                                                        struct wpa_bss,
3616                                                        list_id);
3617                         else {
3618                                 bsslast = wpa_bss_get_id(wpa_s, id2);
3619                                 if (bsslast == NULL && bss && id2 > id1) {
3620                                         struct wpa_bss *tmp = bss;
3621                                         for (;;) {
3622                                                 next = tmp->list_id.next;
3623                                                 if (next == &wpa_s->bss_id)
3624                                                         break;
3625                                                 tmp = dl_list_entry(
3626                                                         next, struct wpa_bss,
3627                                                         list_id);
3628                                                 if (tmp->id > id2)
3629                                                         break;
3630                                                 bsslast = tmp;
3631                                         }
3632                                 }
3633                         }
3634                 }
3635         } else if (os_strncmp(cmd, "FIRST", 5) == 0)
3636                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
3637         else if (os_strncmp(cmd, "LAST", 4) == 0)
3638                 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
3639         else if (os_strncmp(cmd, "ID-", 3) == 0) {
3640                 i = atoi(cmd + 3);
3641                 bss = wpa_bss_get_id(wpa_s, i);
3642         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3643                 i = atoi(cmd + 5);
3644                 bss = wpa_bss_get_id(wpa_s, i);
3645                 if (bss) {
3646                         next = bss->list_id.next;
3647                         if (next == &wpa_s->bss_id)
3648                                 bss = NULL;
3649                         else
3650                                 bss = dl_list_entry(next, struct wpa_bss,
3651                                                     list_id);
3652                 }
3653 #ifdef CONFIG_P2P
3654         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
3655                 if (hwaddr_aton(cmd + 13, bssid) == 0)
3656                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
3657                 else
3658                         bss = NULL;
3659 #endif /* CONFIG_P2P */
3660         } else if (hwaddr_aton(cmd, bssid) == 0)
3661                 bss = wpa_bss_get_bssid(wpa_s, bssid);
3662         else {
3663                 struct wpa_bss *tmp;
3664                 i = atoi(cmd);
3665                 bss = NULL;
3666                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
3667                 {
3668                         if (i-- == 0) {
3669                                 bss = tmp;
3670                                 break;
3671                         }
3672                 }
3673         }
3674
3675         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
3676                 mask = strtoul(ctmp + 5, NULL, 0x10);
3677                 if (mask == 0)
3678                         mask = WPA_BSS_MASK_ALL;
3679         }
3680
3681         if (bss == NULL)
3682                 return 0;
3683
3684         if (bsslast == NULL)
3685                 bsslast = bss;
3686         do {
3687                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
3688                 ret += len;
3689                 buf += len;
3690                 buflen -= len;
3691                 if (bss == bsslast) {
3692                         if ((mask & WPA_BSS_MASK_DELIM) && len &&
3693                             (bss == dl_list_last(&wpa_s->bss_id,
3694                                                  struct wpa_bss, list_id)))
3695                                 os_snprintf(buf - 5, 5, "####\n");
3696                         break;
3697                 }
3698                 next = bss->list_id.next;
3699                 if (next == &wpa_s->bss_id)
3700                         break;
3701                 bss = dl_list_entry(next, struct wpa_bss, list_id);
3702         } while (bss && len);
3703
3704         return ret;
3705 }
3706
3707
3708 static int wpa_supplicant_ctrl_iface_ap_scan(
3709         struct wpa_supplicant *wpa_s, char *cmd)
3710 {
3711         int ap_scan = atoi(cmd);
3712         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
3713 }
3714
3715
3716 static int wpa_supplicant_ctrl_iface_scan_interval(
3717         struct wpa_supplicant *wpa_s, char *cmd)
3718 {
3719         int scan_int = atoi(cmd);
3720         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
3721 }
3722
3723
3724 static int wpa_supplicant_ctrl_iface_bss_expire_age(
3725         struct wpa_supplicant *wpa_s, char *cmd)
3726 {
3727         int expire_age = atoi(cmd);
3728         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
3729 }
3730
3731
3732 static int wpa_supplicant_ctrl_iface_bss_expire_count(
3733         struct wpa_supplicant *wpa_s, char *cmd)
3734 {
3735         int expire_count = atoi(cmd);
3736         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
3737 }
3738
3739
3740 static int wpa_supplicant_ctrl_iface_bss_flush(
3741         struct wpa_supplicant *wpa_s, char *cmd)
3742 {
3743         int flush_age = atoi(cmd);
3744
3745         if (flush_age == 0)
3746                 wpa_bss_flush(wpa_s);
3747         else
3748                 wpa_bss_flush_by_age(wpa_s, flush_age);
3749         return 0;
3750 }
3751
3752
3753 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
3754 {
3755         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
3756         /* MLME-DELETEKEYS.request */
3757         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
3758         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
3759         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
3760         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
3761 #ifdef CONFIG_IEEE80211W
3762         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
3763         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
3764 #endif /* CONFIG_IEEE80211W */
3765
3766         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
3767                         0);
3768         /* MLME-SETPROTECTION.request(None) */
3769         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
3770                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
3771                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
3772         wpa_sm_drop_sa(wpa_s->wpa);
3773 }
3774
3775
3776 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
3777                                           char *addr)
3778 {
3779 #ifdef CONFIG_NO_SCAN_PROCESSING
3780         return -1;
3781 #else /* CONFIG_NO_SCAN_PROCESSING */
3782         u8 bssid[ETH_ALEN];
3783         struct wpa_bss *bss;
3784         struct wpa_ssid *ssid = wpa_s->current_ssid;
3785
3786         if (hwaddr_aton(addr, bssid)) {
3787                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
3788                            "address '%s'", addr);
3789                 return -1;
3790         }
3791
3792         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
3793
3794         if (!ssid) {
3795                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
3796                            "configuration known for the target AP");
3797                 return -1;
3798         }
3799
3800         bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
3801         if (!bss) {
3802                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
3803                            "from BSS table");
3804                 return -1;
3805         }
3806
3807         /*
3808          * TODO: Find best network configuration block from configuration to
3809          * allow roaming to other networks
3810          */
3811
3812         wpa_s->reassociate = 1;
3813         wpa_supplicant_connect(wpa_s, bss, ssid);
3814
3815         return 0;
3816 #endif /* CONFIG_NO_SCAN_PROCESSING */
3817 }
3818
3819
3820 #ifdef CONFIG_P2P
3821 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
3822 {
3823         unsigned int timeout = atoi(cmd);
3824         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
3825         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
3826         u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
3827         char *pos;
3828         unsigned int search_delay;
3829
3830         if (os_strstr(cmd, "type=social"))
3831                 type = P2P_FIND_ONLY_SOCIAL;
3832         else if (os_strstr(cmd, "type=progressive"))
3833                 type = P2P_FIND_PROGRESSIVE;
3834
3835         pos = os_strstr(cmd, "dev_id=");
3836         if (pos) {
3837                 pos += 7;
3838                 if (hwaddr_aton(pos, dev_id))
3839                         return -1;
3840                 _dev_id = dev_id;
3841         }
3842
3843         pos = os_strstr(cmd, "dev_type=");
3844         if (pos) {
3845                 pos += 9;
3846                 if (wps_dev_type_str2bin(pos, dev_type) < 0)
3847                         return -1;
3848                 _dev_type = dev_type;
3849         }
3850
3851         pos = os_strstr(cmd, "delay=");
3852         if (pos) {
3853                 pos += 6;
3854                 search_delay = atoi(pos);
3855         } else
3856                 search_delay = wpas_p2p_search_delay(wpa_s);
3857
3858         return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
3859                              _dev_id, search_delay);
3860 }
3861
3862
3863 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
3864                             char *buf, size_t buflen)
3865 {
3866         u8 addr[ETH_ALEN];
3867         char *pos, *pos2;
3868         char *pin = NULL;
3869         enum p2p_wps_method wps_method;
3870         int new_pin;
3871         int ret;
3872         int persistent_group, persistent_id = -1;
3873         int join;
3874         int auth;
3875         int automatic;
3876         int go_intent = -1;
3877         int freq = 0;
3878         int pd;
3879         int ht40, vht;
3880
3881         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
3882          * [persistent|persistent=<network id>]
3883          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
3884          * [ht40] [vht] */
3885
3886         if (hwaddr_aton(cmd, addr))
3887                 return -1;
3888
3889         pos = cmd + 17;
3890         if (*pos != ' ')
3891                 return -1;
3892         pos++;
3893
3894         persistent_group = os_strstr(pos, " persistent") != NULL;
3895         pos2 = os_strstr(pos, " persistent=");
3896         if (pos2) {
3897                 struct wpa_ssid *ssid;
3898                 persistent_id = atoi(pos2 + 12);
3899                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3900                 if (ssid == NULL || ssid->disabled != 2 ||
3901                     ssid->mode != WPAS_MODE_P2P_GO) {
3902                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3903                                    "SSID id=%d for persistent P2P group (GO)",
3904                                    persistent_id);
3905                         return -1;
3906                 }
3907         }
3908         join = os_strstr(pos, " join") != NULL;
3909         auth = os_strstr(pos, " auth") != NULL;
3910         automatic = os_strstr(pos, " auto") != NULL;
3911         pd = os_strstr(pos, " provdisc") != NULL;
3912         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
3913         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
3914                 vht;
3915
3916         pos2 = os_strstr(pos, " go_intent=");
3917         if (pos2) {
3918                 pos2 += 11;
3919                 go_intent = atoi(pos2);
3920                 if (go_intent < 0 || go_intent > 15)
3921                         return -1;
3922         }
3923
3924         pos2 = os_strstr(pos, " freq=");
3925         if (pos2) {
3926                 pos2 += 6;
3927                 freq = atoi(pos2);
3928                 if (freq <= 0)
3929                         return -1;
3930         }
3931
3932         if (os_strncmp(pos, "pin", 3) == 0) {
3933                 /* Request random PIN (to be displayed) and enable the PIN */
3934                 wps_method = WPS_PIN_DISPLAY;
3935         } else if (os_strncmp(pos, "pbc", 3) == 0) {
3936                 wps_method = WPS_PBC;
3937         } else {
3938                 pin = pos;
3939                 pos = os_strchr(pin, ' ');
3940                 wps_method = WPS_PIN_KEYPAD;
3941                 if (pos) {
3942                         *pos++ = '\0';
3943                         if (os_strncmp(pos, "display", 7) == 0)
3944                                 wps_method = WPS_PIN_DISPLAY;
3945                 }
3946                 if (!wps_pin_str_valid(pin)) {
3947                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
3948                         return 17;
3949                 }
3950         }
3951
3952         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
3953                                    persistent_group, automatic, join,
3954                                    auth, go_intent, freq, persistent_id, pd,
3955                                    ht40, vht);
3956         if (new_pin == -2) {
3957                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
3958                 return 25;
3959         }
3960         if (new_pin == -3) {
3961                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
3962                 return 25;
3963         }
3964         if (new_pin < 0)
3965                 return -1;
3966         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
3967                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
3968                 if (ret < 0 || (size_t) ret >= buflen)
3969                         return -1;
3970                 return ret;
3971         }
3972
3973         os_memcpy(buf, "OK\n", 3);
3974         return 3;
3975 }
3976
3977
3978 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
3979 {
3980         unsigned int timeout = atoi(cmd);
3981         return wpas_p2p_listen(wpa_s, timeout);
3982 }
3983
3984
3985 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
3986 {
3987         u8 addr[ETH_ALEN];
3988         char *pos;
3989         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
3990
3991         /* <addr> <config method> [join|auto] */
3992
3993         if (hwaddr_aton(cmd, addr))
3994                 return -1;
3995
3996         pos = cmd + 17;
3997         if (*pos != ' ')
3998                 return -1;
3999         pos++;
4000
4001         if (os_strstr(pos, " join") != NULL)
4002                 use = WPAS_P2P_PD_FOR_JOIN;
4003         else if (os_strstr(pos, " auto") != NULL)
4004                 use = WPAS_P2P_PD_AUTO;
4005
4006         return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
4007 }
4008
4009
4010 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
4011                               size_t buflen)
4012 {
4013         struct wpa_ssid *ssid = wpa_s->current_ssid;
4014
4015         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
4016             ssid->passphrase == NULL)
4017                 return -1;
4018
4019         os_strlcpy(buf, ssid->passphrase, buflen);
4020         return os_strlen(buf);
4021 }
4022
4023
4024 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
4025                                   char *buf, size_t buflen)
4026 {
4027         u64 ref;
4028         int res;
4029         u8 dst_buf[ETH_ALEN], *dst;
4030         struct wpabuf *tlvs;
4031         char *pos;
4032         size_t len;
4033
4034         if (hwaddr_aton(cmd, dst_buf))
4035                 return -1;
4036         dst = dst_buf;
4037         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
4038             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
4039                 dst = NULL;
4040         pos = cmd + 17;
4041         if (*pos != ' ')
4042                 return -1;
4043         pos++;
4044
4045         if (os_strncmp(pos, "upnp ", 5) == 0) {
4046                 u8 version;
4047                 pos += 5;
4048                 if (hexstr2bin(pos, &version, 1) < 0)
4049                         return -1;
4050                 pos += 2;
4051                 if (*pos != ' ')
4052                         return -1;
4053                 pos++;
4054                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
4055 #ifdef CONFIG_WIFI_DISPLAY
4056         } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
4057                 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
4058 #endif /* CONFIG_WIFI_DISPLAY */
4059         } else {
4060                 len = os_strlen(pos);
4061                 if (len & 1)
4062                         return -1;
4063                 len /= 2;
4064                 tlvs = wpabuf_alloc(len);
4065                 if (tlvs == NULL)
4066                         return -1;
4067                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
4068                         wpabuf_free(tlvs);
4069                         return -1;
4070                 }
4071
4072                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
4073                 wpabuf_free(tlvs);
4074         }
4075         if (ref == 0)
4076                 return -1;
4077         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
4078         if (res < 0 || (unsigned) res >= buflen)
4079                 return -1;
4080         return res;
4081 }
4082
4083
4084 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
4085                                          char *cmd)
4086 {
4087         long long unsigned val;
4088         u64 req;
4089         if (sscanf(cmd, "%llx", &val) != 1)
4090                 return -1;
4091         req = val;
4092         return wpas_p2p_sd_cancel_request(wpa_s, req);
4093 }
4094
4095
4096 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
4097 {
4098         int freq;
4099         u8 dst[ETH_ALEN];
4100         u8 dialog_token;
4101         struct wpabuf *resp_tlvs;
4102         char *pos, *pos2;
4103         size_t len;
4104
4105         pos = os_strchr(cmd, ' ');
4106         if (pos == NULL)
4107                 return -1;
4108         *pos++ = '\0';
4109         freq = atoi(cmd);
4110         if (freq == 0)
4111                 return -1;
4112
4113         if (hwaddr_aton(pos, dst))
4114                 return -1;
4115         pos += 17;
4116         if (*pos != ' ')
4117                 return -1;
4118         pos++;
4119
4120         pos2 = os_strchr(pos, ' ');
4121         if (pos2 == NULL)
4122                 return -1;
4123         *pos2++ = '\0';
4124         dialog_token = atoi(pos);
4125
4126         len = os_strlen(pos2);
4127         if (len & 1)
4128                 return -1;
4129         len /= 2;
4130         resp_tlvs = wpabuf_alloc(len);
4131         if (resp_tlvs == NULL)
4132                 return -1;
4133         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
4134                 wpabuf_free(resp_tlvs);
4135                 return -1;
4136         }
4137
4138         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
4139         wpabuf_free(resp_tlvs);
4140         return 0;
4141 }
4142
4143
4144 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
4145                                        char *cmd)
4146 {
4147         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
4148                 return -1;
4149         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
4150         return 0;
4151 }
4152
4153
4154 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
4155                                         char *cmd)
4156 {
4157         char *pos;
4158         size_t len;
4159         struct wpabuf *query, *resp;
4160
4161         pos = os_strchr(cmd, ' ');
4162         if (pos == NULL)
4163                 return -1;
4164         *pos++ = '\0';
4165
4166         len = os_strlen(cmd);
4167         if (len & 1)
4168                 return -1;
4169         len /= 2;
4170         query = wpabuf_alloc(len);
4171         if (query == NULL)
4172                 return -1;
4173         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4174                 wpabuf_free(query);
4175                 return -1;
4176         }
4177
4178         len = os_strlen(pos);
4179         if (len & 1) {
4180                 wpabuf_free(query);
4181                 return -1;
4182         }
4183         len /= 2;
4184         resp = wpabuf_alloc(len);
4185         if (resp == NULL) {
4186                 wpabuf_free(query);
4187                 return -1;
4188         }
4189         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
4190                 wpabuf_free(query);
4191                 wpabuf_free(resp);
4192                 return -1;
4193         }
4194
4195         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
4196                 wpabuf_free(query);
4197                 wpabuf_free(resp);
4198                 return -1;
4199         }
4200         return 0;
4201 }
4202
4203
4204 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4205 {
4206         char *pos;
4207         u8 version;
4208
4209         pos = os_strchr(cmd, ' ');
4210         if (pos == NULL)
4211                 return -1;
4212         *pos++ = '\0';
4213
4214         if (hexstr2bin(cmd, &version, 1) < 0)
4215                 return -1;
4216
4217         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
4218 }
4219
4220
4221 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
4222 {
4223         char *pos;
4224
4225         pos = os_strchr(cmd, ' ');
4226         if (pos == NULL)
4227                 return -1;
4228         *pos++ = '\0';
4229
4230         if (os_strcmp(cmd, "bonjour") == 0)
4231                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
4232         if (os_strcmp(cmd, "upnp") == 0)
4233                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
4234         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4235         return -1;
4236 }
4237
4238
4239 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
4240                                         char *cmd)
4241 {
4242         size_t len;
4243         struct wpabuf *query;
4244         int ret;
4245
4246         len = os_strlen(cmd);
4247         if (len & 1)
4248                 return -1;
4249         len /= 2;
4250         query = wpabuf_alloc(len);
4251         if (query == NULL)
4252                 return -1;
4253         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4254                 wpabuf_free(query);
4255                 return -1;
4256         }
4257
4258         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
4259         wpabuf_free(query);
4260         return ret;
4261 }
4262
4263
4264 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4265 {
4266         char *pos;
4267         u8 version;
4268
4269         pos = os_strchr(cmd, ' ');
4270         if (pos == NULL)
4271                 return -1;
4272         *pos++ = '\0';
4273
4274         if (hexstr2bin(cmd, &version, 1) < 0)
4275                 return -1;
4276
4277         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
4278 }
4279
4280
4281 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
4282 {
4283         char *pos;
4284
4285         pos = os_strchr(cmd, ' ');
4286         if (pos == NULL)
4287                 return -1;
4288         *pos++ = '\0';
4289
4290         if (os_strcmp(cmd, "bonjour") == 0)
4291                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
4292         if (os_strcmp(cmd, "upnp") == 0)
4293                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
4294         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4295         return -1;
4296 }
4297
4298
4299 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
4300 {
4301         u8 addr[ETH_ALEN];
4302
4303         /* <addr> */
4304
4305         if (hwaddr_aton(cmd, addr))
4306                 return -1;
4307
4308         return wpas_p2p_reject(wpa_s, addr);
4309 }
4310
4311
4312 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
4313 {
4314         char *pos;
4315         int id;
4316         struct wpa_ssid *ssid;
4317         u8 *_peer = NULL, peer[ETH_ALEN];
4318         int freq = 0, pref_freq = 0;
4319         int ht40, vht;
4320
4321         id = atoi(cmd);
4322         pos = os_strstr(cmd, " peer=");
4323         if (pos) {
4324                 pos += 6;
4325                 if (hwaddr_aton(pos, peer))
4326                         return -1;
4327                 _peer = peer;
4328         }
4329         ssid = wpa_config_get_network(wpa_s->conf, id);
4330         if (ssid == NULL || ssid->disabled != 2) {
4331                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4332                            "for persistent P2P group",
4333                            id);
4334                 return -1;
4335         }
4336
4337         pos = os_strstr(cmd, " freq=");
4338         if (pos) {
4339                 pos += 6;
4340                 freq = atoi(pos);
4341                 if (freq <= 0)
4342                         return -1;
4343         }
4344
4345         pos = os_strstr(cmd, " pref=");
4346         if (pos) {
4347                 pos += 6;
4348                 pref_freq = atoi(pos);
4349                 if (pref_freq <= 0)
4350                         return -1;
4351         }
4352
4353         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
4354         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4355                 vht;
4356
4357         return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
4358                                pref_freq);
4359 }
4360
4361
4362 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
4363 {
4364         char *pos;
4365         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
4366
4367         pos = os_strstr(cmd, " peer=");
4368         if (!pos)
4369                 return -1;
4370
4371         *pos = '\0';
4372         pos += 6;
4373         if (hwaddr_aton(pos, peer)) {
4374                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
4375                 return -1;
4376         }
4377
4378         pos = os_strstr(pos, " go_dev_addr=");
4379         if (pos) {
4380                 pos += 13;
4381                 if (hwaddr_aton(pos, go_dev_addr)) {
4382                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
4383                                    pos);
4384                         return -1;
4385                 }
4386                 go_dev = go_dev_addr;
4387         }
4388
4389         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
4390 }
4391
4392
4393 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
4394 {
4395         if (os_strncmp(cmd, "persistent=", 11) == 0)
4396                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
4397         if (os_strncmp(cmd, "group=", 6) == 0)
4398                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
4399
4400         return -1;
4401 }
4402
4403
4404 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
4405                                          char *cmd, int freq, int ht40,
4406                                          int vht)
4407 {
4408         int id;
4409         struct wpa_ssid *ssid;
4410
4411         id = atoi(cmd);
4412         ssid = wpa_config_get_network(wpa_s->conf, id);
4413         if (ssid == NULL || ssid->disabled != 2) {
4414                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4415                            "for persistent P2P group",
4416                            id);
4417                 return -1;
4418         }
4419
4420         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
4421                                              NULL, 0);
4422 }
4423
4424
4425 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
4426 {
4427         int freq = 0, ht40, vht;
4428         char *pos;
4429
4430         pos = os_strstr(cmd, "freq=");
4431         if (pos)
4432                 freq = atoi(pos + 5);
4433
4434         vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
4435         ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4436                 vht;
4437
4438         if (os_strncmp(cmd, "persistent=", 11) == 0)
4439                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
4440                                                      ht40, vht);
4441         if (os_strcmp(cmd, "persistent") == 0 ||
4442             os_strncmp(cmd, "persistent ", 11) == 0)
4443                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
4444         if (os_strncmp(cmd, "freq=", 5) == 0)
4445                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
4446         if (ht40)
4447                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
4448
4449         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
4450                    cmd);
4451         return -1;
4452 }
4453
4454
4455 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
4456                          char *buf, size_t buflen)
4457 {
4458         u8 addr[ETH_ALEN], *addr_ptr;
4459         int next, res;
4460         const struct p2p_peer_info *info;
4461         char *pos, *end;
4462         char devtype[WPS_DEV_TYPE_BUFSIZE];
4463         struct wpa_ssid *ssid;
4464         size_t i;
4465
4466         if (!wpa_s->global->p2p)
4467                 return -1;
4468
4469         if (os_strcmp(cmd, "FIRST") == 0) {
4470                 addr_ptr = NULL;
4471                 next = 0;
4472         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4473                 if (hwaddr_aton(cmd + 5, addr) < 0)
4474                         return -1;
4475                 addr_ptr = addr;
4476                 next = 1;
4477         } else {
4478                 if (hwaddr_aton(cmd, addr) < 0)
4479                         return -1;
4480                 addr_ptr = addr;
4481                 next = 0;
4482         }
4483
4484         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
4485         if (info == NULL)
4486                 return -1;
4487
4488         pos = buf;
4489         end = buf + buflen;
4490
4491         res = os_snprintf(pos, end - pos, MACSTR "\n"
4492                           "pri_dev_type=%s\n"
4493                           "device_name=%s\n"
4494                           "manufacturer=%s\n"
4495                           "model_name=%s\n"
4496                           "model_number=%s\n"
4497                           "serial_number=%s\n"
4498                           "config_methods=0x%x\n"
4499                           "dev_capab=0x%x\n"
4500                           "group_capab=0x%x\n"
4501                           "level=%d\n",
4502                           MAC2STR(info->p2p_device_addr),
4503                           wps_dev_type_bin2str(info->pri_dev_type,
4504                                                devtype, sizeof(devtype)),
4505                           info->device_name,
4506                           info->manufacturer,
4507                           info->model_name,
4508                           info->model_number,
4509                           info->serial_number,
4510                           info->config_methods,
4511                           info->dev_capab,
4512                           info->group_capab,
4513                           info->level);
4514         if (res < 0 || res >= end - pos)
4515                 return pos - buf;
4516         pos += res;
4517
4518         for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
4519         {
4520                 const u8 *t;
4521                 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
4522                 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
4523                                   wps_dev_type_bin2str(t, devtype,
4524                                                        sizeof(devtype)));
4525                 if (res < 0 || res >= end - pos)
4526                         return pos - buf;
4527                 pos += res;
4528         }
4529
4530         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
4531         if (ssid) {
4532                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
4533                 if (res < 0 || res >= end - pos)
4534                         return pos - buf;
4535                 pos += res;
4536         }
4537
4538         res = p2p_get_peer_info_txt(info, pos, end - pos);
4539         if (res < 0)
4540                 return pos - buf;
4541         pos += res;
4542
4543         return pos - buf;
4544 }
4545
4546
4547 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
4548                                   const char *param)
4549 {
4550         unsigned int i;
4551
4552         if (wpa_s->global->p2p == NULL)
4553                 return -1;
4554
4555         if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
4556                 return -1;
4557
4558         for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
4559                 struct wpa_freq_range *freq;
4560                 freq = &wpa_s->global->p2p_disallow_freq.range[i];
4561                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
4562                            freq->min, freq->max);
4563         }
4564
4565         wpas_p2p_update_channel_list(wpa_s);
4566         return 0;
4567 }
4568
4569
4570 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
4571 {
4572         char *param;
4573
4574         if (wpa_s->global->p2p == NULL)
4575                 return -1;
4576
4577         param = os_strchr(cmd, ' ');
4578         if (param == NULL)
4579                 return -1;
4580         *param++ = '\0';
4581
4582         if (os_strcmp(cmd, "discoverability") == 0) {
4583                 p2p_set_client_discoverability(wpa_s->global->p2p,
4584                                                atoi(param));
4585                 return 0;
4586         }
4587
4588         if (os_strcmp(cmd, "managed") == 0) {
4589                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
4590                 return 0;
4591         }
4592
4593         if (os_strcmp(cmd, "listen_channel") == 0) {
4594                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
4595                                               atoi(param));
4596         }
4597
4598         if (os_strcmp(cmd, "ssid_postfix") == 0) {
4599                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
4600                                             os_strlen(param));
4601         }
4602
4603         if (os_strcmp(cmd, "noa") == 0) {
4604                 char *pos;
4605                 int count, start, duration;
4606                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
4607                 count = atoi(param);
4608                 pos = os_strchr(param, ',');
4609                 if (pos == NULL)
4610                         return -1;
4611                 pos++;
4612                 start = atoi(pos);
4613                 pos = os_strchr(pos, ',');
4614                 if (pos == NULL)
4615                         return -1;
4616                 pos++;
4617                 duration = atoi(pos);
4618                 if (count < 0 || count > 255 || start < 0 || duration < 0)
4619                         return -1;
4620                 if (count == 0 && duration > 0)
4621                         return -1;
4622                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
4623                            "start=%d duration=%d", count, start, duration);
4624                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
4625         }
4626
4627         if (os_strcmp(cmd, "ps") == 0)
4628                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
4629
4630         if (os_strcmp(cmd, "oppps") == 0)
4631                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
4632
4633         if (os_strcmp(cmd, "ctwindow") == 0)
4634                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
4635
4636         if (os_strcmp(cmd, "disabled") == 0) {
4637                 wpa_s->global->p2p_disabled = atoi(param);
4638                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
4639                            wpa_s->global->p2p_disabled ?
4640                            "disabled" : "enabled");
4641                 if (wpa_s->global->p2p_disabled) {
4642                         wpas_p2p_stop_find(wpa_s);
4643                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4644                         p2p_flush(wpa_s->global->p2p);
4645                 }
4646                 return 0;
4647         }
4648
4649         if (os_strcmp(cmd, "conc_pref") == 0) {
4650                 if (os_strcmp(param, "sta") == 0)
4651                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
4652                 else if (os_strcmp(param, "p2p") == 0)
4653                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
4654                 else {
4655                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
4656                         return -1;
4657                 }
4658                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
4659                            "%s", param);
4660                 return 0;
4661         }
4662
4663         if (os_strcmp(cmd, "force_long_sd") == 0) {
4664                 wpa_s->force_long_sd = atoi(param);
4665                 return 0;
4666         }
4667
4668         if (os_strcmp(cmd, "peer_filter") == 0) {
4669                 u8 addr[ETH_ALEN];
4670                 if (hwaddr_aton(param, addr))
4671                         return -1;
4672                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
4673                 return 0;
4674         }
4675
4676         if (os_strcmp(cmd, "cross_connect") == 0)
4677                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
4678
4679         if (os_strcmp(cmd, "go_apsd") == 0) {
4680                 if (os_strcmp(param, "disable") == 0)
4681                         wpa_s->set_ap_uapsd = 0;
4682                 else {
4683                         wpa_s->set_ap_uapsd = 1;
4684                         wpa_s->ap_uapsd = atoi(param);
4685                 }
4686                 return 0;
4687         }
4688
4689         if (os_strcmp(cmd, "client_apsd") == 0) {
4690                 if (os_strcmp(param, "disable") == 0)
4691                         wpa_s->set_sta_uapsd = 0;
4692                 else {
4693                         int be, bk, vi, vo;
4694                         char *pos;
4695                         /* format: BE,BK,VI,VO;max SP Length */
4696                         be = atoi(param);
4697                         pos = os_strchr(param, ',');
4698                         if (pos == NULL)
4699                                 return -1;
4700                         pos++;
4701                         bk = atoi(pos);
4702                         pos = os_strchr(pos, ',');
4703                         if (pos == NULL)
4704                                 return -1;
4705                         pos++;
4706                         vi = atoi(pos);
4707                         pos = os_strchr(pos, ',');
4708                         if (pos == NULL)
4709                                 return -1;
4710                         pos++;
4711                         vo = atoi(pos);
4712                         /* ignore max SP Length for now */
4713
4714                         wpa_s->set_sta_uapsd = 1;
4715                         wpa_s->sta_uapsd = 0;
4716                         if (be)
4717                                 wpa_s->sta_uapsd |= BIT(0);
4718                         if (bk)
4719                                 wpa_s->sta_uapsd |= BIT(1);
4720                         if (vi)
4721                                 wpa_s->sta_uapsd |= BIT(2);
4722                         if (vo)
4723                                 wpa_s->sta_uapsd |= BIT(3);
4724                 }
4725                 return 0;
4726         }
4727
4728         if (os_strcmp(cmd, "disallow_freq") == 0)
4729                 return p2p_ctrl_disallow_freq(wpa_s, param);
4730
4731         if (os_strcmp(cmd, "disc_int") == 0) {
4732                 int min_disc_int, max_disc_int, max_disc_tu;
4733                 char *pos;
4734
4735                 pos = param;
4736
4737                 min_disc_int = atoi(pos);
4738                 pos = os_strchr(pos, ' ');
4739                 if (pos == NULL)
4740                         return -1;
4741                 *pos++ = '\0';
4742
4743                 max_disc_int = atoi(pos);
4744                 pos = os_strchr(pos, ' ');
4745                 if (pos == NULL)
4746                         return -1;
4747                 *pos++ = '\0';
4748
4749                 max_disc_tu = atoi(pos);
4750
4751                 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
4752                                         max_disc_int, max_disc_tu);
4753         }
4754
4755         if (os_strcmp(cmd, "per_sta_psk") == 0) {
4756                 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
4757                 return 0;
4758         }
4759
4760 #ifdef CONFIG_WPS_NFC
4761         if (os_strcmp(cmd, "nfc_tag") == 0)
4762                 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
4763 #endif /* CONFIG_WPS_NFC */
4764
4765         if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
4766                 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
4767                 return 0;
4768         }
4769
4770         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
4771                    cmd);
4772
4773         return -1;
4774 }
4775
4776
4777 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
4778 {
4779         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4780         wpa_s->force_long_sd = 0;
4781         if (wpa_s->global->p2p)
4782                 p2p_flush(wpa_s->global->p2p);
4783 }
4784
4785
4786 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
4787 {
4788         char *pos, *pos2;
4789         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
4790
4791         if (cmd[0]) {
4792                 pos = os_strchr(cmd, ' ');
4793                 if (pos == NULL)
4794                         return -1;
4795                 *pos++ = '\0';
4796                 dur1 = atoi(cmd);
4797
4798                 pos2 = os_strchr(pos, ' ');
4799                 if (pos2)
4800                         *pos2++ = '\0';
4801                 int1 = atoi(pos);
4802         } else
4803                 pos2 = NULL;
4804
4805         if (pos2) {
4806                 pos = os_strchr(pos2, ' ');
4807                 if (pos == NULL)
4808                         return -1;
4809                 *pos++ = '\0';
4810                 dur2 = atoi(pos2);
4811                 int2 = atoi(pos);
4812         }
4813
4814         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
4815 }
4816
4817
4818 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
4819 {
4820         char *pos;
4821         unsigned int period = 0, interval = 0;
4822
4823         if (cmd[0]) {
4824                 pos = os_strchr(cmd, ' ');
4825                 if (pos == NULL)
4826                         return -1;
4827                 *pos++ = '\0';
4828                 period = atoi(cmd);
4829                 interval = atoi(pos);
4830         }
4831
4832         return wpas_p2p_ext_listen(wpa_s, period, interval);
4833 }
4834
4835
4836 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
4837 {
4838         const char *pos;
4839         u8 peer[ETH_ALEN];
4840         int iface_addr = 0;
4841
4842         pos = cmd;
4843         if (os_strncmp(pos, "iface=", 6) == 0) {
4844                 iface_addr = 1;
4845                 pos += 6;
4846         }
4847         if (hwaddr_aton(pos, peer))
4848                 return -1;
4849
4850         wpas_p2p_remove_client(wpa_s, peer, iface_addr);
4851         return 0;
4852 }
4853
4854 #endif /* CONFIG_P2P */
4855
4856
4857 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
4858 {
4859         struct wpa_freq_range_list ranges;
4860         int *freqs = NULL;
4861         struct hostapd_hw_modes *mode;
4862         u16 i;
4863
4864         if (wpa_s->hw.modes == NULL)
4865                 return NULL;
4866
4867         os_memset(&ranges, 0, sizeof(ranges));
4868         if (freq_range_list_parse(&ranges, val) < 0)
4869                 return NULL;
4870
4871         for (i = 0; i < wpa_s->hw.num_modes; i++) {
4872                 int j;
4873
4874                 mode = &wpa_s->hw.modes[i];
4875                 for (j = 0; j < mode->num_channels; j++) {
4876                         unsigned int freq;
4877
4878                         if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
4879                                 continue;
4880
4881                         freq = mode->channels[j].freq;
4882                         if (!freq_range_list_includes(&ranges, freq))
4883                                 continue;
4884
4885                         int_array_add_unique(&freqs, freq);
4886                 }
4887         }
4888
4889         os_free(ranges.range);
4890         return freqs;
4891 }
4892
4893
4894 #ifdef CONFIG_INTERWORKING
4895
4896 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
4897 {
4898         int auto_sel = 0;
4899         int *freqs = NULL;
4900
4901         if (param) {
4902                 char *pos;
4903
4904                 auto_sel = os_strstr(param, "auto") != NULL;
4905
4906                 pos = os_strstr(param, "freq=");
4907                 if (pos) {
4908                         freqs = freq_range_to_channel_list(wpa_s, pos + 5);
4909                         if (freqs == NULL)
4910                                 return -1;
4911                 }
4912
4913         }
4914
4915         return interworking_select(wpa_s, auto_sel, freqs);
4916 }
4917
4918
4919 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
4920 {
4921         u8 bssid[ETH_ALEN];
4922         struct wpa_bss *bss;
4923
4924         if (hwaddr_aton(dst, bssid)) {
4925                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
4926                 return -1;
4927         }
4928
4929         bss = wpa_bss_get_bssid(wpa_s, bssid);
4930         if (bss == NULL) {
4931                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
4932                            MAC2STR(bssid));
4933                 return -1;
4934         }
4935
4936         return interworking_connect(wpa_s, bss);
4937 }
4938
4939
4940 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
4941 {
4942         u8 dst_addr[ETH_ALEN];
4943         int used;
4944         char *pos;
4945 #define MAX_ANQP_INFO_ID 100
4946         u16 id[MAX_ANQP_INFO_ID];
4947         size_t num_id = 0;
4948         u32 subtypes = 0;
4949
4950         used = hwaddr_aton2(dst, dst_addr);
4951         if (used < 0)
4952                 return -1;
4953         pos = dst + used;
4954         while (num_id < MAX_ANQP_INFO_ID) {
4955                 if (os_strncmp(pos, "hs20:", 5) == 0) {
4956 #ifdef CONFIG_HS20
4957                         int num = atoi(pos + 5);
4958                         if (num <= 0 || num > 31)
4959                                 return -1;
4960                         subtypes |= BIT(num);
4961 #else /* CONFIG_HS20 */
4962                         return -1;
4963 #endif /* CONFIG_HS20 */
4964                 } else {
4965                         id[num_id] = atoi(pos);
4966                         if (id[num_id])
4967                                 num_id++;
4968                 }
4969                 pos = os_strchr(pos + 1, ',');
4970                 if (pos == NULL)
4971                         break;
4972                 pos++;
4973         }
4974
4975         if (num_id == 0)
4976                 return -1;
4977
4978         return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
4979 }
4980
4981
4982 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
4983 {
4984         u8 dst_addr[ETH_ALEN];
4985         struct wpabuf *advproto, *query = NULL;
4986         int used, ret = -1;
4987         char *pos, *end;
4988         size_t len;
4989
4990         used = hwaddr_aton2(cmd, dst_addr);
4991         if (used < 0)
4992                 return -1;
4993
4994         pos = cmd + used;
4995         while (*pos == ' ')
4996                 pos++;
4997
4998         /* Advertisement Protocol ID */
4999         end = os_strchr(pos, ' ');
5000         if (end)
5001                 len = end - pos;
5002         else
5003                 len = os_strlen(pos);
5004         if (len & 0x01)
5005                 return -1;
5006         len /= 2;
5007         if (len == 0)
5008                 return -1;
5009         advproto = wpabuf_alloc(len);
5010         if (advproto == NULL)
5011                 return -1;
5012         if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
5013                 goto fail;
5014
5015         if (end) {
5016                 /* Optional Query Request */
5017                 pos = end + 1;
5018                 while (*pos == ' ')
5019                         pos++;
5020
5021                 len = os_strlen(pos);
5022                 if (len) {
5023                         if (len & 0x01)
5024                                 goto fail;
5025                         len /= 2;
5026                         if (len == 0)
5027                                 goto fail;
5028                         query = wpabuf_alloc(len);
5029                         if (query == NULL)
5030                                 goto fail;
5031                         if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
5032                                 goto fail;
5033                 }
5034         }
5035
5036         ret = gas_send_request(wpa_s, dst_addr, advproto, query);
5037
5038 fail:
5039         wpabuf_free(advproto);
5040         wpabuf_free(query);
5041
5042         return ret;
5043 }
5044
5045
5046 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
5047                             size_t buflen)
5048 {
5049         u8 addr[ETH_ALEN];
5050         int dialog_token;
5051         int used;
5052         char *pos;
5053         size_t resp_len, start, requested_len;
5054         struct wpabuf *resp;
5055         int ret;
5056
5057         used = hwaddr_aton2(cmd, addr);
5058         if (used < 0)
5059                 return -1;
5060
5061         pos = cmd + used;
5062         while (*pos == ' ')
5063                 pos++;
5064         dialog_token = atoi(pos);
5065
5066         if (wpa_s->last_gas_resp &&
5067             os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
5068             dialog_token == wpa_s->last_gas_dialog_token)
5069                 resp = wpa_s->last_gas_resp;
5070         else if (wpa_s->prev_gas_resp &&
5071                  os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
5072                  dialog_token == wpa_s->prev_gas_dialog_token)
5073                 resp = wpa_s->prev_gas_resp;
5074         else
5075                 return -1;
5076
5077         resp_len = wpabuf_len(resp);
5078         start = 0;
5079         requested_len = resp_len;
5080
5081         pos = os_strchr(pos, ' ');
5082         if (pos) {
5083                 start = atoi(pos);
5084                 if (start > resp_len)
5085                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
5086                 pos = os_strchr(pos, ',');
5087                 if (pos == NULL)
5088                         return -1;
5089                 pos++;
5090                 requested_len = atoi(pos);
5091                 if (start + requested_len > resp_len)
5092                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
5093         }
5094
5095         if (requested_len * 2 + 1 > buflen)
5096                 return os_snprintf(buf, buflen, "FAIL-Too long response");
5097
5098         ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
5099                                requested_len);
5100
5101         if (start + requested_len == resp_len) {
5102                 /*
5103                  * Free memory by dropping the response after it has been
5104                  * fetched.
5105                  */
5106                 if (resp == wpa_s->prev_gas_resp) {
5107                         wpabuf_free(wpa_s->prev_gas_resp);
5108                         wpa_s->prev_gas_resp = NULL;
5109                 } else {
5110                         wpabuf_free(wpa_s->last_gas_resp);
5111                         wpa_s->last_gas_resp = NULL;
5112                 }
5113         }
5114
5115         return ret;
5116 }
5117 #endif /* CONFIG_INTERWORKING */
5118
5119
5120 #ifdef CONFIG_HS20
5121
5122 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
5123 {
5124         u8 dst_addr[ETH_ALEN];
5125         int used;
5126         char *pos;
5127         u32 subtypes = 0;
5128
5129         used = hwaddr_aton2(dst, dst_addr);
5130         if (used < 0)
5131                 return -1;
5132         pos = dst + used;
5133         for (;;) {
5134                 int num = atoi(pos);
5135                 if (num <= 0 || num > 31)
5136                         return -1;
5137                 subtypes |= BIT(num);
5138                 pos = os_strchr(pos + 1, ',');
5139                 if (pos == NULL)
5140                         break;
5141                 pos++;
5142         }
5143
5144         if (subtypes == 0)
5145                 return -1;
5146
5147         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
5148 }
5149
5150
5151 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
5152                                     const u8 *addr, const char *realm)
5153 {
5154         u8 *buf;
5155         size_t rlen, len;
5156         int ret;
5157
5158         rlen = os_strlen(realm);
5159         len = 3 + rlen;
5160         buf = os_malloc(len);
5161         if (buf == NULL)
5162                 return -1;
5163         buf[0] = 1; /* NAI Home Realm Count */
5164         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
5165         buf[2] = rlen;
5166         os_memcpy(buf + 3, realm, rlen);
5167
5168         ret = hs20_anqp_send_req(wpa_s, addr,
5169                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
5170                                  buf, len);
5171
5172         os_free(buf);
5173
5174         return ret;
5175 }
5176
5177
5178 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
5179                                         char *dst)
5180 {
5181         struct wpa_cred *cred = wpa_s->conf->cred;
5182         u8 dst_addr[ETH_ALEN];
5183         int used;
5184         u8 *buf;
5185         size_t len;
5186         int ret;
5187
5188         used = hwaddr_aton2(dst, dst_addr);
5189         if (used < 0)
5190                 return -1;
5191
5192         while (dst[used] == ' ')
5193                 used++;
5194         if (os_strncmp(dst + used, "realm=", 6) == 0)
5195                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
5196                                                 dst + used + 6);
5197
5198         len = os_strlen(dst + used);
5199
5200         if (len == 0 && cred && cred->realm)
5201                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
5202
5203         if (len % 1)
5204                 return -1;
5205         len /= 2;
5206         buf = os_malloc(len);
5207         if (buf == NULL)
5208                 return -1;
5209         if (hexstr2bin(dst + used, buf, len) < 0) {
5210                 os_free(buf);
5211                 return -1;
5212         }
5213
5214         ret = hs20_anqp_send_req(wpa_s, dst_addr,
5215                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
5216                                  buf, len);
5217         os_free(buf);
5218
5219         return ret;
5220 }
5221
5222
5223 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
5224 {
5225         u8 dst_addr[ETH_ALEN];
5226         int used;
5227         char *icon;
5228
5229         used = hwaddr_aton2(cmd, dst_addr);
5230         if (used < 0)
5231                 return -1;
5232
5233         while (cmd[used] == ' ')
5234                 used++;
5235         icon = &cmd[used];
5236
5237         wpa_s->fetch_osu_icon_in_progress = 0;
5238         return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
5239                                   (u8 *) icon, os_strlen(icon));
5240 }
5241
5242 #endif /* CONFIG_HS20 */
5243
5244
5245 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
5246         struct wpa_supplicant *wpa_s, char *cmd)
5247 {
5248         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
5249         return 0;
5250 }
5251
5252
5253 #ifdef CONFIG_AUTOSCAN
5254
5255 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
5256                                               char *cmd)
5257 {
5258         enum wpa_states state = wpa_s->wpa_state;
5259         char *new_params = NULL;
5260
5261         if (os_strlen(cmd) > 0) {
5262                 new_params = os_strdup(cmd);
5263                 if (new_params == NULL)
5264                         return -1;
5265         }
5266
5267         os_free(wpa_s->conf->autoscan);
5268         wpa_s->conf->autoscan = new_params;
5269
5270         if (wpa_s->conf->autoscan == NULL)
5271                 autoscan_deinit(wpa_s);
5272         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
5273                 autoscan_init(wpa_s, 1);
5274         else if (state == WPA_SCANNING)
5275                 wpa_supplicant_reinit_autoscan(wpa_s);
5276
5277         return 0;
5278 }
5279
5280 #endif /* CONFIG_AUTOSCAN */
5281
5282
5283 #ifdef CONFIG_WNM
5284
5285 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
5286 {
5287         int enter;
5288         int intval = 0;
5289         char *pos;
5290         int ret;
5291         struct wpabuf *tfs_req = NULL;
5292
5293         if (os_strncmp(cmd, "enter", 5) == 0)
5294                 enter = 1;
5295         else if (os_strncmp(cmd, "exit", 4) == 0)
5296                 enter = 0;
5297         else
5298                 return -1;
5299
5300         pos = os_strstr(cmd, " interval=");
5301         if (pos)
5302                 intval = atoi(pos + 10);
5303
5304         pos = os_strstr(cmd, " tfs_req=");
5305         if (pos) {
5306                 char *end;
5307                 size_t len;
5308                 pos += 9;
5309                 end = os_strchr(pos, ' ');
5310                 if (end)
5311                         len = end - pos;
5312                 else
5313                         len = os_strlen(pos);
5314                 if (len & 1)
5315                         return -1;
5316                 len /= 2;
5317                 tfs_req = wpabuf_alloc(len);
5318                 if (tfs_req == NULL)
5319                         return -1;
5320                 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
5321                         wpabuf_free(tfs_req);
5322                         return -1;
5323                 }
5324         }
5325
5326         ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
5327                                            WNM_SLEEP_MODE_EXIT, intval,
5328                                            tfs_req);
5329         wpabuf_free(tfs_req);
5330
5331         return ret;
5332 }
5333
5334
5335 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
5336 {
5337         int query_reason;
5338
5339         query_reason = atoi(cmd);
5340
5341         wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
5342                    query_reason);
5343
5344         return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
5345 }
5346
5347 #endif /* CONFIG_WNM */
5348
5349
5350 /* Get string representation of channel width */
5351 static const char * channel_width_name(enum chan_width width)
5352 {
5353         switch (width) {
5354         case CHAN_WIDTH_20_NOHT:
5355                 return "20 MHz (no HT)";
5356         case CHAN_WIDTH_20:
5357                 return "20 MHz";
5358         case CHAN_WIDTH_40:
5359                 return "40 MHz";
5360         case CHAN_WIDTH_80:
5361                 return "80 MHz";
5362         case CHAN_WIDTH_80P80:
5363                 return "80+80 MHz";
5364         case CHAN_WIDTH_160:
5365                 return "160 MHz";
5366         default:
5367                 return "unknown";
5368         }
5369 }
5370
5371
5372 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
5373                                       size_t buflen)
5374 {
5375         struct wpa_signal_info si;
5376         int ret;
5377         char *pos, *end;
5378
5379         ret = wpa_drv_signal_poll(wpa_s, &si);
5380         if (ret)
5381                 return -1;
5382
5383         pos = buf;
5384         end = buf + buflen;
5385
5386         ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
5387                           "NOISE=%d\nFREQUENCY=%u\n",
5388                           si.current_signal, si.current_txrate / 1000,
5389                           si.current_noise, si.frequency);
5390         if (ret < 0 || ret > end - pos)
5391                 return -1;
5392         pos += ret;
5393
5394         if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
5395                 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
5396                                   channel_width_name(si.chanwidth));
5397                 if (ret < 0 || ret > end - pos)
5398                         return -1;
5399                 pos += ret;
5400         }
5401
5402         if (si.center_frq1 > 0 && si.center_frq2 > 0) {
5403                 ret = os_snprintf(pos, end - pos,
5404                                   "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
5405                                   si.center_frq1, si.center_frq2);
5406                 if (ret < 0 || ret > end - pos)
5407                         return -1;
5408                 pos += ret;
5409         }
5410
5411         if (si.avg_signal) {
5412                 ret = os_snprintf(pos, end - pos,
5413                                   "AVG_RSSI=%d\n", si.avg_signal);
5414                 if (ret < 0 || ret >= end - pos)
5415                         return -1;
5416                 pos += ret;
5417         }
5418
5419         return pos - buf;
5420 }
5421
5422
5423 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
5424                                       size_t buflen)
5425 {
5426         struct hostap_sta_driver_data sta;
5427         int ret;
5428
5429         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
5430         if (ret)
5431                 return -1;
5432
5433         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
5434                           sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
5435         if (ret < 0 || (size_t) ret > buflen)
5436                 return -1;
5437         return ret;
5438 }
5439
5440
5441 #ifdef ANDROID
5442 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5443                                      char *buf, size_t buflen)
5444 {
5445         int ret;
5446
5447         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
5448         if (ret == 0) {
5449                 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
5450                         struct p2p_data *p2p = wpa_s->global->p2p;
5451                         if (p2p) {
5452                                 char country[3];
5453                                 country[0] = cmd[8];
5454                                 country[1] = cmd[9];
5455                                 country[2] = 0x04;
5456                                 p2p_set_country(p2p, country);
5457                         }
5458                 }
5459                 ret = os_snprintf(buf, buflen, "%s\n", "OK");
5460         }
5461         return ret;
5462 }
5463 #endif /* ANDROID */
5464
5465
5466 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5467                                      char *buf, size_t buflen)
5468 {
5469         int ret;
5470         char *pos;
5471         u8 *data = NULL;
5472         unsigned int vendor_id, subcmd;
5473         struct wpabuf *reply;
5474         size_t data_len = 0;
5475
5476         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
5477         vendor_id = strtoul(cmd, &pos, 16);
5478         if (!isblank(*pos))
5479                 return -EINVAL;
5480
5481         subcmd = strtoul(pos, &pos, 10);
5482
5483         if (*pos != '\0') {
5484                 if (!isblank(*pos++))
5485                         return -EINVAL;
5486                 data_len = os_strlen(pos);
5487         }
5488
5489         if (data_len) {
5490                 data_len /= 2;
5491                 data = os_malloc(data_len);
5492                 if (!data)
5493                         return -ENOBUFS;
5494
5495                 if (hexstr2bin(pos, data, data_len)) {
5496                         wpa_printf(MSG_DEBUG,
5497                                    "Vendor command: wrong parameter format");
5498                         os_free(data);
5499                         return -EINVAL;
5500                 }
5501         }
5502
5503         reply = wpabuf_alloc((buflen - 1) / 2);
5504         if (!reply) {
5505                 os_free(data);
5506                 return -ENOBUFS;
5507         }
5508
5509         ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
5510                                  reply);
5511
5512         if (ret == 0)
5513                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
5514                                        wpabuf_len(reply));
5515
5516         wpabuf_free(reply);
5517         os_free(data);
5518
5519         return ret;
5520 }
5521
5522
5523 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
5524 {
5525         wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
5526
5527 #ifdef CONFIG_P2P
5528         wpas_p2p_stop_find(wpa_s);
5529         p2p_ctrl_flush(wpa_s);
5530         wpas_p2p_group_remove(wpa_s, "*");
5531         wpas_p2p_service_flush(wpa_s);
5532         wpa_s->global->p2p_disabled = 0;
5533         wpa_s->global->p2p_per_sta_psk = 0;
5534         wpa_s->conf->num_sec_device_types = 0;
5535         wpa_s->p2p_disable_ip_addr_req = 0;
5536 #endif /* CONFIG_P2P */
5537
5538 #ifdef CONFIG_WPS_TESTING
5539         wps_version_number = 0x20;
5540         wps_testing_dummy_cred = 0;
5541         wps_corrupt_pkhash = 0;
5542 #endif /* CONFIG_WPS_TESTING */
5543 #ifdef CONFIG_WPS
5544         wpa_s->wps_fragment_size = 0;
5545         wpas_wps_cancel(wpa_s);
5546 #endif /* CONFIG_WPS */
5547         wpa_s->after_wps = 0;
5548         wpa_s->known_wps_freq = 0;
5549
5550 #ifdef CONFIG_TDLS
5551 #ifdef CONFIG_TDLS_TESTING
5552         extern unsigned int tdls_testing;
5553         tdls_testing = 0;
5554 #endif /* CONFIG_TDLS_TESTING */
5555         wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
5556         wpa_tdls_enable(wpa_s->wpa, 1);
5557 #endif /* CONFIG_TDLS */
5558
5559         eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
5560         wpa_supplicant_stop_countermeasures(wpa_s, NULL);
5561
5562         wpa_s->no_keep_alive = 0;
5563
5564         os_free(wpa_s->disallow_aps_bssid);
5565         wpa_s->disallow_aps_bssid = NULL;
5566         wpa_s->disallow_aps_bssid_count = 0;
5567         os_free(wpa_s->disallow_aps_ssid);
5568         wpa_s->disallow_aps_ssid = NULL;
5569         wpa_s->disallow_aps_ssid_count = 0;
5570
5571         wpa_s->set_sta_uapsd = 0;
5572         wpa_s->sta_uapsd = 0;
5573
5574         wpa_drv_radio_disable(wpa_s, 0);
5575
5576         wpa_bss_flush(wpa_s);
5577         wpa_blacklist_clear(wpa_s);
5578         wpa_s->extra_blacklist_count = 0;
5579         wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
5580         wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
5581         wpa_config_flush_blobs(wpa_s->conf);
5582         wpa_s->conf->auto_interworking = 0;
5583         wpa_s->conf->okc = 0;
5584
5585         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
5586         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
5587         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
5588         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
5589
5590         radio_remove_works(wpa_s, NULL, 1);
5591
5592         wpa_s->next_ssid = NULL;
5593
5594 #ifdef CONFIG_INTERWORKING
5595         hs20_cancel_fetch_osu(wpa_s);
5596 #endif /* CONFIG_INTERWORKING */
5597
5598         wpa_s->ext_mgmt_frame_handling = 0;
5599 }
5600
5601
5602 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
5603                                      char *buf, size_t buflen)
5604 {
5605         struct wpa_radio_work *work;
5606         char *pos, *end;
5607         struct os_reltime now, diff;
5608
5609         pos = buf;
5610         end = buf + buflen;
5611
5612         os_get_reltime(&now);
5613
5614         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
5615         {
5616                 int ret;
5617
5618                 os_reltime_sub(&now, &work->time, &diff);
5619                 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
5620                                   work->type, work->wpa_s->ifname, work->freq,
5621                                   work->started, diff.sec, diff.usec);
5622                 if (ret < 0 || ret >= end - pos)
5623                         break;
5624                 pos += ret;
5625         }
5626
5627         return pos - buf;
5628 }
5629
5630
5631 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
5632 {
5633         struct wpa_radio_work *work = eloop_ctx;
5634         struct wpa_external_work *ework = work->ctx;
5635
5636         wpa_dbg(work->wpa_s, MSG_DEBUG,
5637                 "Timing out external radio work %u (%s)",
5638                 ework->id, work->type);
5639         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
5640         os_free(ework);
5641         radio_work_done(work);
5642 }
5643
5644
5645 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
5646 {
5647         struct wpa_external_work *ework = work->ctx;
5648
5649         if (deinit) {
5650                 if (work->started)
5651                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
5652                                              work, NULL);
5653
5654                 os_free(ework);
5655                 return;
5656         }
5657
5658         wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
5659                 ework->id, ework->type);
5660         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
5661         if (!ework->timeout)
5662                 ework->timeout = 10;
5663         eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
5664                                work, NULL);
5665 }
5666
5667
5668 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
5669                                     char *buf, size_t buflen)
5670 {
5671         struct wpa_external_work *ework;
5672         char *pos, *pos2;
5673         size_t type_len;
5674         int ret;
5675         unsigned int freq = 0;
5676
5677         /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
5678
5679         ework = os_zalloc(sizeof(*ework));
5680         if (ework == NULL)
5681                 return -1;
5682
5683         pos = os_strchr(cmd, ' ');
5684         if (pos) {
5685                 type_len = pos - cmd;
5686                 pos++;
5687
5688                 pos2 = os_strstr(pos, "freq=");
5689                 if (pos2)
5690                         freq = atoi(pos2 + 5);
5691
5692                 pos2 = os_strstr(pos, "timeout=");
5693                 if (pos2)
5694                         ework->timeout = atoi(pos2 + 8);
5695         } else {
5696                 type_len = os_strlen(cmd);
5697         }
5698         if (4 + type_len >= sizeof(ework->type))
5699                 type_len = sizeof(ework->type) - 4 - 1;
5700         os_strlcpy(ework->type, "ext:", sizeof(ework->type));
5701         os_memcpy(ework->type + 4, cmd, type_len);
5702         ework->type[4 + type_len] = '\0';
5703
5704         wpa_s->ext_work_id++;
5705         if (wpa_s->ext_work_id == 0)
5706                 wpa_s->ext_work_id++;
5707         ework->id = wpa_s->ext_work_id;
5708
5709         if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
5710                            ework) < 0) {
5711                 os_free(ework);
5712                 return -1;
5713         }
5714
5715         ret = os_snprintf(buf, buflen, "%u", ework->id);
5716         if (ret < 0 || (size_t) ret >= buflen)
5717                 return -1;
5718         return ret;
5719 }
5720
5721
5722 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
5723 {
5724         struct wpa_radio_work *work;
5725         unsigned int id = atoi(cmd);
5726
5727         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
5728         {
5729                 struct wpa_external_work *ework;
5730
5731                 if (os_strncmp(work->type, "ext:", 4) != 0)
5732                         continue;
5733                 ework = work->ctx;
5734                 if (id && ework->id != id)
5735                         continue;
5736                 wpa_dbg(wpa_s, MSG_DEBUG,
5737                         "Completed external radio work %u (%s)",
5738                         ework->id, ework->type);
5739                 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
5740                 radio_work_done(work);
5741                 os_free(ework);
5742                 return 3; /* "OK\n" */
5743         }
5744
5745         return -1;
5746 }
5747
5748
5749 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
5750                                 char *buf, size_t buflen)
5751 {
5752         if (os_strcmp(cmd, "show") == 0)
5753                 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
5754         if (os_strncmp(cmd, "add ", 4) == 0)
5755                 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
5756         if (os_strncmp(cmd, "done ", 5) == 0)
5757                 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
5758         return -1;
5759 }
5760
5761
5762 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
5763 {
5764         struct wpa_radio_work *work, *tmp;
5765
5766         if (!wpa_s || !wpa_s->radio)
5767                 return;
5768
5769         dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
5770                               struct wpa_radio_work, list) {
5771                 struct wpa_external_work *ework;
5772
5773                 if (os_strncmp(work->type, "ext:", 4) != 0)
5774                         continue;
5775                 ework = work->ctx;
5776                 wpa_dbg(wpa_s, MSG_DEBUG,
5777                         "Flushing %sexternal radio work %u (%s)",
5778                         work->started ? " started" : "", ework->id,
5779                         ework->type);
5780                 if (work->started)
5781                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
5782                                              work, NULL);
5783                 os_free(ework);
5784                 radio_work_done(work);
5785         }
5786 }
5787
5788
5789 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
5790 {
5791         struct wpa_supplicant *wpa_s = eloop_ctx;
5792         eapol_sm_notify_ctrl_response(wpa_s->eapol);
5793 }
5794
5795
5796 static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
5797 {
5798         int *freqs = NULL;
5799
5800         freqs = freq_range_to_channel_list(wpa_s, val);
5801         if (freqs == NULL)
5802                 return -1;
5803
5804         os_free(wpa_s->manual_scan_freqs);
5805         wpa_s->manual_scan_freqs = freqs;
5806
5807         return 0;
5808 }
5809
5810
5811 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
5812                            char *reply, int reply_size, int *reply_len)
5813 {
5814         char *pos;
5815
5816         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5817                 *reply_len = -1;
5818                 return;
5819         }
5820
5821         wpa_s->manual_scan_passive = 0;
5822         wpa_s->manual_scan_use_id = 0;
5823         wpa_s->manual_scan_only_new = 0;
5824
5825         if (params) {
5826                 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
5827                         wpa_s->scan_res_handler = scan_only_handler;
5828
5829                 pos = os_strstr(params, "freq=");
5830                 if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
5831                         *reply_len = -1;
5832                         return;
5833                 }
5834
5835                 pos = os_strstr(params, "passive=");
5836                 if (pos)
5837                         wpa_s->manual_scan_passive = !!atoi(pos + 8);
5838
5839                 pos = os_strstr(params, "use_id=");
5840                 if (pos)
5841                         wpa_s->manual_scan_use_id = atoi(pos + 7);
5842
5843                 pos = os_strstr(params, "only_new=1");
5844                 if (pos)
5845                         wpa_s->manual_scan_only_new = 1;
5846         } else {
5847                 os_free(wpa_s->manual_scan_freqs);
5848                 wpa_s->manual_scan_freqs = NULL;
5849                 if (wpa_s->scan_res_handler == scan_only_handler)
5850                         wpa_s->scan_res_handler = NULL;
5851         }
5852
5853         if (!wpa_s->sched_scanning && !wpa_s->scanning &&
5854             ((wpa_s->wpa_state <= WPA_SCANNING) ||
5855              (wpa_s->wpa_state == WPA_COMPLETED))) {
5856                 wpa_s->normal_scans = 0;
5857                 wpa_s->scan_req = MANUAL_SCAN_REQ;
5858                 wpa_s->after_wps = 0;
5859                 wpa_s->known_wps_freq = 0;
5860                 wpa_supplicant_req_scan(wpa_s, 0, 0);
5861                 if (wpa_s->manual_scan_use_id) {
5862                         wpa_s->manual_scan_id++;
5863                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
5864                                 wpa_s->manual_scan_id);
5865                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
5866                                                  wpa_s->manual_scan_id);
5867                 }
5868         } else if (wpa_s->sched_scanning) {
5869                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
5870                 wpa_supplicant_cancel_sched_scan(wpa_s);
5871                 wpa_s->scan_req = MANUAL_SCAN_REQ;
5872                 wpa_supplicant_req_scan(wpa_s, 0, 0);
5873                 if (wpa_s->manual_scan_use_id) {
5874                         wpa_s->manual_scan_id++;
5875                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
5876                                                  wpa_s->manual_scan_id);
5877                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
5878                                 wpa_s->manual_scan_id);
5879                 }
5880         } else {
5881                 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
5882                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
5883         }
5884 }
5885
5886
5887 #ifdef CONFIG_TESTING_OPTIONS
5888
5889 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
5890                                        unsigned int freq, const u8 *dst,
5891                                        const u8 *src, const u8 *bssid,
5892                                        const u8 *data, size_t data_len,
5893                                        enum offchannel_send_action_result
5894                                        result)
5895 {
5896         wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
5897                 " src=" MACSTR " bssid=" MACSTR " result=%s",
5898                 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
5899                 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
5900                 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
5901                              "NO_ACK" : "FAILED"));
5902 }
5903
5904
5905 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
5906 {
5907         char *pos, *param;
5908         size_t len;
5909         u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
5910         int res, used;
5911         int freq = 0, no_cck = 0, wait_time = 0;
5912
5913         /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
5914          *    <action=Action frame payload> */
5915
5916         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
5917
5918         pos = cmd;
5919         used = hwaddr_aton2(pos, da);
5920         if (used < 0)
5921                 return -1;
5922         pos += used;
5923         while (*pos == ' ')
5924                 pos++;
5925         used = hwaddr_aton2(pos, bssid);
5926         if (used < 0)
5927                 return -1;
5928         pos += used;
5929
5930         param = os_strstr(pos, " freq=");
5931         if (param) {
5932                 param += 6;
5933                 freq = atoi(param);
5934         }
5935
5936         param = os_strstr(pos, " no_cck=");
5937         if (param) {
5938                 param += 8;
5939                 no_cck = atoi(param);
5940         }
5941
5942         param = os_strstr(pos, " wait_time=");
5943         if (param) {
5944                 param += 11;
5945                 wait_time = atoi(param);
5946         }
5947
5948         param = os_strstr(pos, " action=");
5949         if (param == NULL)
5950                 return -1;
5951         param += 8;
5952
5953         len = os_strlen(param);
5954         if (len & 1)
5955                 return -1;
5956         len /= 2;
5957
5958         buf = os_malloc(len);
5959         if (buf == NULL)
5960                 return -1;
5961
5962         if (hexstr2bin(param, buf, len) < 0) {
5963                 os_free(buf);
5964                 return -1;
5965         }
5966
5967         res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
5968                                      buf, len, wait_time,
5969                                      wpas_ctrl_iface_mgmt_tx_cb, no_cck);
5970         os_free(buf);
5971         return res;
5972 }
5973
5974
5975 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
5976 {
5977         wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
5978         offchannel_send_action_done(wpa_s);
5979 }
5980
5981 #endif /* CONFIG_TESTING_OPTIONS */
5982
5983
5984 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
5985                                          char *buf, size_t *resp_len)
5986 {
5987         char *reply;
5988         const int reply_size = 4096;
5989         int reply_len;
5990
5991         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
5992             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
5993                 if (wpa_debug_show_keys)
5994                         wpa_dbg(wpa_s, MSG_DEBUG,
5995                                 "Control interface command '%s'", buf);
5996                 else
5997                         wpa_dbg(wpa_s, MSG_DEBUG,
5998                                 "Control interface command '%s [REMOVED]'",
5999                                 os_strncmp(buf, WPA_CTRL_RSP,
6000                                            os_strlen(WPA_CTRL_RSP)) == 0 ?
6001                                 WPA_CTRL_RSP : "SET_NETWORK");
6002         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
6003                    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
6004                    os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
6005                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
6006                                       (const u8 *) buf, os_strlen(buf));
6007         } else {
6008                 int level = MSG_DEBUG;
6009                 if (os_strcmp(buf, "PING") == 0)
6010                         level = MSG_EXCESSIVE;
6011                 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
6012         }
6013
6014         reply = os_malloc(reply_size);
6015         if (reply == NULL) {
6016                 *resp_len = 1;
6017                 return NULL;
6018         }
6019
6020         os_memcpy(reply, "OK\n", 3);
6021         reply_len = 3;
6022
6023         if (os_strcmp(buf, "PING") == 0) {
6024                 os_memcpy(reply, "PONG\n", 5);
6025                 reply_len = 5;
6026         } else if (os_strcmp(buf, "IFNAME") == 0) {
6027                 reply_len = os_strlen(wpa_s->ifname);
6028                 os_memcpy(reply, wpa_s->ifname, reply_len);
6029         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
6030                 if (wpa_debug_reopen_file() < 0)
6031                         reply_len = -1;
6032         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
6033                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
6034         } else if (os_strcmp(buf, "MIB") == 0) {
6035                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
6036                 if (reply_len >= 0) {
6037                         int res;
6038                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
6039                                                reply_size - reply_len);
6040                         if (res < 0)
6041                                 reply_len = -1;
6042                         else
6043                                 reply_len += res;
6044                 }
6045         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
6046                 reply_len = wpa_supplicant_ctrl_iface_status(
6047                         wpa_s, buf + 6, reply, reply_size);
6048         } else if (os_strcmp(buf, "PMKSA") == 0) {
6049                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
6050                                                     reply_size);
6051         } else if (os_strncmp(buf, "SET ", 4) == 0) {
6052                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
6053                         reply_len = -1;
6054         } else if (os_strncmp(buf, "GET ", 4) == 0) {
6055                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
6056                                                           reply, reply_size);
6057         } else if (os_strcmp(buf, "LOGON") == 0) {
6058                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
6059         } else if (os_strcmp(buf, "LOGOFF") == 0) {
6060                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
6061         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
6062                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
6063                         reply_len = -1;
6064                 else
6065                         wpas_request_connection(wpa_s);
6066         } else if (os_strcmp(buf, "REATTACH") == 0) {
6067                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
6068                     !wpa_s->current_ssid)
6069                         reply_len = -1;
6070                 else {
6071                         wpa_s->reattach = 1;
6072                         wpas_request_connection(wpa_s);
6073                 }
6074         } else if (os_strcmp(buf, "RECONNECT") == 0) {
6075                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
6076                         reply_len = -1;
6077                 else if (wpa_s->disconnected)
6078                         wpas_request_connection(wpa_s);
6079 #ifdef IEEE8021X_EAPOL
6080         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
6081                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
6082                         reply_len = -1;
6083 #endif /* IEEE8021X_EAPOL */
6084 #ifdef CONFIG_PEERKEY
6085         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
6086                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
6087                         reply_len = -1;
6088 #endif /* CONFIG_PEERKEY */
6089 #ifdef CONFIG_IEEE80211R
6090         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
6091                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
6092                         reply_len = -1;
6093 #endif /* CONFIG_IEEE80211R */
6094 #ifdef CONFIG_WPS
6095         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
6096                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
6097                 if (res == -2) {
6098                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6099                         reply_len = 17;
6100                 } else if (res)
6101                         reply_len = -1;
6102         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
6103                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
6104                 if (res == -2) {
6105                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6106                         reply_len = 17;
6107                 } else if (res)
6108                         reply_len = -1;
6109         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
6110                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
6111                                                               reply,
6112                                                               reply_size);
6113         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
6114                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
6115                         wpa_s, buf + 14, reply, reply_size);
6116         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
6117                 if (wpas_wps_cancel(wpa_s))
6118                         reply_len = -1;
6119 #ifdef CONFIG_WPS_NFC
6120         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
6121                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
6122                         reply_len = -1;
6123         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
6124                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
6125                         reply_len = -1;
6126         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
6127                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
6128                         wpa_s, buf + 21, reply, reply_size);
6129         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
6130                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
6131                         wpa_s, buf + 14, reply, reply_size);
6132         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
6133                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
6134                                                                buf + 17))
6135                         reply_len = -1;
6136         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
6137                 reply_len = wpas_ctrl_nfc_get_handover_req(
6138                         wpa_s, buf + 21, reply, reply_size);
6139         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
6140                 reply_len = wpas_ctrl_nfc_get_handover_sel(
6141                         wpa_s, buf + 21, reply, reply_size);
6142         } else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
6143                 if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
6144                         reply_len = -1;
6145         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
6146                 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
6147                         reply_len = -1;
6148 #endif /* CONFIG_WPS_NFC */
6149         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
6150                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
6151                         reply_len = -1;
6152 #ifdef CONFIG_AP
6153         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
6154                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
6155                         wpa_s, buf + 11, reply, reply_size);
6156 #endif /* CONFIG_AP */
6157 #ifdef CONFIG_WPS_ER
6158         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
6159                 if (wpas_wps_er_start(wpa_s, NULL))
6160                         reply_len = -1;
6161         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
6162                 if (wpas_wps_er_start(wpa_s, buf + 13))
6163                         reply_len = -1;
6164         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
6165                 if (wpas_wps_er_stop(wpa_s))
6166                         reply_len = -1;
6167         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
6168                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
6169                         reply_len = -1;
6170         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
6171                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
6172                 if (ret == -2) {
6173                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6174                         reply_len = 17;
6175                 } else if (ret == -3) {
6176                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
6177                         reply_len = 18;
6178                 } else if (ret == -4) {
6179                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
6180                         reply_len = 20;
6181                 } else if (ret)
6182                         reply_len = -1;
6183         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
6184                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
6185                         reply_len = -1;
6186         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
6187                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
6188                                                                 buf + 18))
6189                         reply_len = -1;
6190         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
6191                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
6192                         reply_len = -1;
6193 #ifdef CONFIG_WPS_NFC
6194         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
6195                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
6196                         wpa_s, buf + 24, reply, reply_size);
6197 #endif /* CONFIG_WPS_NFC */
6198 #endif /* CONFIG_WPS_ER */
6199 #endif /* CONFIG_WPS */
6200 #ifdef CONFIG_IBSS_RSN
6201         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
6202                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
6203                         reply_len = -1;
6204 #endif /* CONFIG_IBSS_RSN */
6205 #ifdef CONFIG_P2P
6206         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
6207                 if (p2p_ctrl_find(wpa_s, buf + 9))
6208                         reply_len = -1;
6209         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
6210                 if (p2p_ctrl_find(wpa_s, ""))
6211                         reply_len = -1;
6212         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
6213                 wpas_p2p_stop_find(wpa_s);
6214         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
6215                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
6216                                              reply_size);
6217         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
6218                 if (p2p_ctrl_listen(wpa_s, buf + 11))
6219                         reply_len = -1;
6220         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
6221                 if (p2p_ctrl_listen(wpa_s, ""))
6222                         reply_len = -1;
6223         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
6224                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
6225                         reply_len = -1;
6226         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
6227                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
6228                         reply_len = -1;
6229         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
6230                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
6231                         reply_len = -1;
6232         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
6233                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
6234                         reply_len = -1;
6235         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
6236                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
6237         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
6238                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
6239                                                    reply_size);
6240         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
6241                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
6242                         reply_len = -1;
6243         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
6244                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
6245                         reply_len = -1;
6246         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
6247                 wpas_p2p_sd_service_update(wpa_s);
6248         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
6249                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
6250                         reply_len = -1;
6251         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
6252                 wpas_p2p_service_flush(wpa_s);
6253         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
6254                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
6255                         reply_len = -1;
6256         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
6257                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
6258                         reply_len = -1;
6259         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
6260                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
6261                         reply_len = -1;
6262         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
6263                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
6264                         reply_len = -1;
6265         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
6266                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
6267                                               reply_size);
6268         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
6269                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
6270                         reply_len = -1;
6271         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
6272                 p2p_ctrl_flush(wpa_s);
6273         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
6274                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
6275                         reply_len = -1;
6276         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
6277                 if (wpas_p2p_cancel(wpa_s))
6278                         reply_len = -1;
6279         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
6280                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
6281                         reply_len = -1;
6282         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
6283                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
6284                         reply_len = -1;
6285         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
6286                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
6287                         reply_len = -1;
6288         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
6289                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
6290                         reply_len = -1;
6291         } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
6292                 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
6293                         reply_len = -1;
6294 #endif /* CONFIG_P2P */
6295 #ifdef CONFIG_WIFI_DISPLAY
6296         } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
6297                 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
6298                         reply_len = -1;
6299         } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
6300                 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
6301                                                      reply, reply_size);
6302 #endif /* CONFIG_WIFI_DISPLAY */
6303 #ifdef CONFIG_INTERWORKING
6304         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
6305                 if (interworking_fetch_anqp(wpa_s) < 0)
6306                         reply_len = -1;
6307         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
6308                 interworking_stop_fetch_anqp(wpa_s);
6309         } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
6310                 if (ctrl_interworking_select(wpa_s, NULL) < 0)
6311                         reply_len = -1;
6312         } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
6313                 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
6314                         reply_len = -1;
6315         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
6316                 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
6317                         reply_len = -1;
6318         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
6319                 if (get_anqp(wpa_s, buf + 9) < 0)
6320                         reply_len = -1;
6321         } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
6322                 if (gas_request(wpa_s, buf + 12) < 0)
6323                         reply_len = -1;
6324         } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
6325                 reply_len = gas_response_get(wpa_s, buf + 17, reply,
6326                                              reply_size);
6327 #endif /* CONFIG_INTERWORKING */
6328 #ifdef CONFIG_HS20
6329         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
6330                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
6331                         reply_len = -1;
6332         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
6333                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
6334                         reply_len = -1;
6335         } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
6336                 if (hs20_icon_request(wpa_s, buf + 18) < 0)
6337                         reply_len = -1;
6338         } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
6339                 if (hs20_fetch_osu(wpa_s) < 0)
6340                         reply_len = -1;
6341         } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
6342                 hs20_cancel_fetch_osu(wpa_s);
6343 #endif /* CONFIG_HS20 */
6344         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
6345         {
6346                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
6347                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
6348                         reply_len = -1;
6349                 else {
6350                         /*
6351                          * Notify response from timeout to allow the control
6352                          * interface response to be sent first.
6353                          */
6354                         eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
6355                                                wpa_s, NULL);
6356                 }
6357         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
6358                 if (wpa_supplicant_reload_configuration(wpa_s))
6359                         reply_len = -1;
6360         } else if (os_strcmp(buf, "TERMINATE") == 0) {
6361                 wpa_supplicant_terminate_proc(wpa_s->global);
6362         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
6363                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
6364                         reply_len = -1;
6365         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
6366                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
6367                         wpa_s, buf + 9, reply, reply_size);
6368         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
6369                 reply_len = wpa_supplicant_ctrl_iface_log_level(
6370                         wpa_s, buf + 9, reply, reply_size);
6371         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
6372                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
6373                         wpa_s, reply, reply_size);
6374         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
6375 #ifdef CONFIG_SME
6376                 wpa_s->sme.prev_bssid_set = 0;
6377 #endif /* CONFIG_SME */
6378                 wpa_s->reassociate = 0;
6379                 wpa_s->disconnected = 1;
6380                 wpa_supplicant_cancel_sched_scan(wpa_s);
6381                 wpa_supplicant_cancel_scan(wpa_s);
6382                 wpa_supplicant_deauthenticate(wpa_s,
6383                                               WLAN_REASON_DEAUTH_LEAVING);
6384         } else if (os_strcmp(buf, "SCAN") == 0) {
6385                 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
6386         } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
6387                 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
6388         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
6389                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
6390                         wpa_s, reply, reply_size);
6391         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
6392                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
6393                         reply_len = -1;
6394         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
6395                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
6396                         reply_len = -1;
6397         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
6398                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
6399                         reply_len = -1;
6400         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
6401                 reply_len = wpa_supplicant_ctrl_iface_add_network(
6402                         wpa_s, reply, reply_size);
6403         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
6404                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
6405                         reply_len = -1;
6406         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
6407                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
6408                         reply_len = -1;
6409         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
6410                 reply_len = wpa_supplicant_ctrl_iface_get_network(
6411                         wpa_s, buf + 12, reply, reply_size);
6412         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
6413                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
6414                         wpa_s, reply, reply_size);
6415         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
6416                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
6417                         wpa_s, reply, reply_size);
6418         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
6419                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
6420                         reply_len = -1;
6421         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
6422                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
6423                         reply_len = -1;
6424 #ifndef CONFIG_NO_CONFIG_WRITE
6425         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
6426                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
6427                         reply_len = -1;
6428 #endif /* CONFIG_NO_CONFIG_WRITE */
6429         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
6430                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
6431                         wpa_s, buf + 15, reply, reply_size);
6432         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
6433                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
6434                         reply_len = -1;
6435         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
6436                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
6437                         reply_len = -1;
6438         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
6439                 reply_len = wpa_supplicant_global_iface_list(
6440                         wpa_s->global, reply, reply_size);
6441         } else if (os_strcmp(buf, "INTERFACES") == 0) {
6442                 reply_len = wpa_supplicant_global_iface_interfaces(
6443                         wpa_s->global, reply, reply_size);
6444         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
6445                 reply_len = wpa_supplicant_ctrl_iface_bss(
6446                         wpa_s, buf + 4, reply, reply_size);
6447 #ifdef CONFIG_AP
6448         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
6449                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
6450         } else if (os_strncmp(buf, "STA ", 4) == 0) {
6451                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
6452                                               reply_size);
6453         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
6454                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
6455                                                    reply_size);
6456         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
6457                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
6458                         reply_len = -1;
6459         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
6460                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
6461                         reply_len = -1;
6462         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
6463                 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
6464                         reply_len = -1;
6465 #endif /* CONFIG_AP */
6466         } else if (os_strcmp(buf, "SUSPEND") == 0) {
6467                 wpas_notify_suspend(wpa_s->global);
6468         } else if (os_strcmp(buf, "RESUME") == 0) {
6469                 wpas_notify_resume(wpa_s->global);
6470         } else if (os_strcmp(buf, "DROP_SA") == 0) {
6471                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
6472         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
6473                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
6474                         reply_len = -1;
6475         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
6476                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
6477                         reply_len = -1;
6478         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
6479                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
6480                         reply_len = -1;
6481         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
6482                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
6483                                                                buf + 17))
6484                         reply_len = -1;
6485         } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
6486                 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
6487                         reply_len = -1;
6488 #ifdef CONFIG_TDLS
6489         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
6490                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
6491                         reply_len = -1;
6492         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
6493                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
6494                         reply_len = -1;
6495         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
6496                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
6497                         reply_len = -1;
6498 #endif /* CONFIG_TDLS */
6499         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
6500                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
6501                                                        reply_size);
6502         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
6503                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
6504                                                        reply_size);
6505 #ifdef CONFIG_AUTOSCAN
6506         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
6507                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
6508                         reply_len = -1;
6509 #endif /* CONFIG_AUTOSCAN */
6510 #ifdef ANDROID
6511         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
6512                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
6513                                                       reply_size);
6514 #endif /* ANDROID */
6515         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
6516                 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
6517                                                       reply_size);
6518         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
6519                 pmksa_cache_clear_current(wpa_s->wpa);
6520                 eapol_sm_request_reauth(wpa_s->eapol);
6521 #ifdef CONFIG_WNM
6522         } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
6523                 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
6524                         reply_len = -1;
6525         } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) {
6526                 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10))
6527                                 reply_len = -1;
6528 #endif /* CONFIG_WNM */
6529         } else if (os_strcmp(buf, "FLUSH") == 0) {
6530                 wpa_supplicant_ctrl_iface_flush(wpa_s);
6531         } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
6532                 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
6533                                                  reply_size);
6534 #ifdef CONFIG_TESTING_OPTIONS
6535         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
6536                 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
6537                         reply_len = -1;
6538         } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
6539                 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
6540 #endif /* CONFIG_TESTING_OPTIONS */
6541         } else {
6542                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
6543                 reply_len = 16;
6544         }
6545
6546         if (reply_len < 0) {
6547                 os_memcpy(reply, "FAIL\n", 5);
6548                 reply_len = 5;
6549         }
6550
6551         *resp_len = reply_len;
6552         return reply;
6553 }
6554
6555
6556 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
6557                                            char *cmd)
6558 {
6559         struct wpa_interface iface;
6560         char *pos;
6561
6562         /*
6563          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
6564          * TAB<bridge_ifname>
6565          */
6566         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
6567
6568         os_memset(&iface, 0, sizeof(iface));
6569
6570         do {
6571                 iface.ifname = pos = cmd;
6572                 pos = os_strchr(pos, '\t');
6573                 if (pos)
6574                         *pos++ = '\0';
6575                 if (iface.ifname[0] == '\0')
6576                         return -1;
6577                 if (pos == NULL)
6578                         break;
6579
6580                 iface.confname = pos;
6581                 pos = os_strchr(pos, '\t');
6582                 if (pos)
6583                         *pos++ = '\0';
6584                 if (iface.confname[0] == '\0')
6585                         iface.confname = NULL;
6586                 if (pos == NULL)
6587                         break;
6588
6589                 iface.driver = pos;
6590                 pos = os_strchr(pos, '\t');
6591                 if (pos)
6592                         *pos++ = '\0';
6593                 if (iface.driver[0] == '\0')
6594                         iface.driver = NULL;
6595                 if (pos == NULL)
6596                         break;
6597
6598                 iface.ctrl_interface = pos;
6599                 pos = os_strchr(pos, '\t');
6600                 if (pos)
6601                         *pos++ = '\0';
6602                 if (iface.ctrl_interface[0] == '\0')
6603                         iface.ctrl_interface = NULL;
6604                 if (pos == NULL)
6605                         break;
6606
6607                 iface.driver_param = pos;
6608                 pos = os_strchr(pos, '\t');
6609                 if (pos)
6610                         *pos++ = '\0';
6611                 if (iface.driver_param[0] == '\0')
6612                         iface.driver_param = NULL;
6613                 if (pos == NULL)
6614                         break;
6615
6616                 iface.bridge_ifname = pos;
6617                 pos = os_strchr(pos, '\t');
6618                 if (pos)
6619                         *pos++ = '\0';
6620                 if (iface.bridge_ifname[0] == '\0')
6621                         iface.bridge_ifname = NULL;
6622                 if (pos == NULL)
6623                         break;
6624         } while (0);
6625
6626         if (wpa_supplicant_get_iface(global, iface.ifname))
6627                 return -1;
6628
6629         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
6630 }
6631
6632
6633 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
6634                                               char *cmd)
6635 {
6636         struct wpa_supplicant *wpa_s;
6637
6638         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
6639
6640         wpa_s = wpa_supplicant_get_iface(global, cmd);
6641         if (wpa_s == NULL)
6642                 return -1;
6643         return wpa_supplicant_remove_iface(global, wpa_s, 0);
6644 }
6645
6646
6647 static void wpa_free_iface_info(struct wpa_interface_info *iface)
6648 {
6649         struct wpa_interface_info *prev;
6650
6651         while (iface) {
6652                 prev = iface;
6653                 iface = iface->next;
6654
6655                 os_free(prev->ifname);
6656                 os_free(prev->desc);
6657                 os_free(prev);
6658         }
6659 }
6660
6661
6662 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
6663                                             char *buf, int len)
6664 {
6665         int i, res;
6666         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
6667         char *pos, *end;
6668
6669         for (i = 0; wpa_drivers[i]; i++) {
6670                 struct wpa_driver_ops *drv = wpa_drivers[i];
6671                 if (drv->get_interfaces == NULL)
6672                         continue;
6673                 tmp = drv->get_interfaces(global->drv_priv[i]);
6674                 if (tmp == NULL)
6675                         continue;
6676
6677                 if (last == NULL)
6678                         iface = last = tmp;
6679                 else
6680                         last->next = tmp;
6681                 while (last->next)
6682                         last = last->next;
6683         }
6684
6685         pos = buf;
6686         end = buf + len;
6687         for (tmp = iface; tmp; tmp = tmp->next) {
6688                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
6689                                   tmp->drv_name, tmp->ifname,
6690                                   tmp->desc ? tmp->desc : "");
6691                 if (res < 0 || res >= end - pos) {
6692                         *pos = '\0';
6693                         break;
6694                 }
6695                 pos += res;
6696         }
6697
6698         wpa_free_iface_info(iface);
6699
6700         return pos - buf;
6701 }
6702
6703
6704 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
6705                                                   char *buf, int len)
6706 {
6707         int res;
6708         char *pos, *end;
6709         struct wpa_supplicant *wpa_s;
6710
6711         wpa_s = global->ifaces;
6712         pos = buf;
6713         end = buf + len;
6714
6715         while (wpa_s) {
6716                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
6717                 if (res < 0 || res >= end - pos) {
6718                         *pos = '\0';
6719                         break;
6720                 }
6721                 pos += res;
6722                 wpa_s = wpa_s->next;
6723         }
6724         return pos - buf;
6725 }
6726
6727
6728 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
6729                                             const char *ifname,
6730                                             char *cmd, size_t *resp_len)
6731 {
6732         struct wpa_supplicant *wpa_s;
6733
6734         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6735                 if (os_strcmp(ifname, wpa_s->ifname) == 0)
6736                         break;
6737         }
6738
6739         if (wpa_s == NULL) {
6740                 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
6741                 if (resp)
6742                         *resp_len = os_strlen(resp);
6743                 else
6744                         *resp_len = 1;
6745                 return resp;
6746         }
6747
6748         return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
6749 }
6750
6751
6752 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
6753                                                char *buf, size_t *resp_len)
6754 {
6755 #ifdef CONFIG_P2P
6756         static const char * cmd[] = {
6757                 "LIST_NETWORKS",
6758                 "SAVE_CONFIG",
6759                 "P2P_FIND",
6760                 "P2P_STOP_FIND",
6761                 "P2P_LISTEN",
6762                 "P2P_GROUP_ADD",
6763                 "P2P_GET_PASSPHRASE",
6764                 "P2P_SERVICE_UPDATE",
6765                 "P2P_SERVICE_FLUSH",
6766                 "P2P_FLUSH",
6767                 "P2P_CANCEL",
6768                 "P2P_PRESENCE_REQ",
6769                 "P2P_EXT_LISTEN",
6770                 NULL
6771         };
6772         static const char * prefix[] = {
6773 #ifdef ANDROID
6774                 "DRIVER ",
6775 #endif /* ANDROID */
6776                 "GET_NETWORK ",
6777                 "REMOVE_NETWORK ",
6778                 "SET ",
6779                 "P2P_FIND ",
6780                 "P2P_CONNECT ",
6781                 "P2P_LISTEN ",
6782                 "P2P_GROUP_REMOVE ",
6783                 "P2P_GROUP_ADD ",
6784                 "P2P_PROV_DISC ",
6785                 "P2P_SERV_DISC_REQ ",
6786                 "P2P_SERV_DISC_CANCEL_REQ ",
6787                 "P2P_SERV_DISC_RESP ",
6788                 "P2P_SERV_DISC_EXTERNAL ",
6789                 "P2P_SERVICE_ADD ",
6790                 "P2P_SERVICE_DEL ",
6791                 "P2P_REJECT ",
6792                 "P2P_INVITE ",
6793                 "P2P_PEER ",
6794                 "P2P_SET ",
6795                 "P2P_UNAUTHORIZE ",
6796                 "P2P_PRESENCE_REQ ",
6797                 "P2P_EXT_LISTEN ",
6798                 "P2P_REMOVE_CLIENT ",
6799                 NULL
6800         };
6801         int found = 0;
6802         int i;
6803
6804         if (global->p2p_init_wpa_s == NULL)
6805                 return NULL;
6806
6807         for (i = 0; !found && cmd[i]; i++) {
6808                 if (os_strcmp(buf, cmd[i]) == 0)
6809                         found = 1;
6810         }
6811
6812         for (i = 0; !found && prefix[i]; i++) {
6813                 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
6814                         found = 1;
6815         }
6816
6817         if (found)
6818                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6819                                                          buf, resp_len);
6820 #endif /* CONFIG_P2P */
6821         return NULL;
6822 }
6823
6824
6825 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
6826                                                char *buf, size_t *resp_len)
6827 {
6828 #ifdef CONFIG_WIFI_DISPLAY
6829         if (global->p2p_init_wpa_s == NULL)
6830                 return NULL;
6831         if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
6832             os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
6833                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6834                                                          buf, resp_len);
6835 #endif /* CONFIG_WIFI_DISPLAY */
6836         return NULL;
6837 }
6838
6839
6840 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
6841                                            char *buf, size_t *resp_len)
6842 {
6843         char *ret;
6844
6845         ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
6846         if (ret)
6847                 return ret;
6848
6849         ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
6850         if (ret)
6851                 return ret;
6852
6853         return NULL;
6854 }
6855
6856
6857 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
6858 {
6859         char *value;
6860
6861         value = os_strchr(cmd, ' ');
6862         if (value == NULL)
6863                 return -1;
6864         *value++ = '\0';
6865
6866         wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
6867
6868 #ifdef CONFIG_WIFI_DISPLAY
6869         if (os_strcasecmp(cmd, "wifi_display") == 0) {
6870                 wifi_display_enable(global, !!atoi(value));
6871                 return 0;
6872         }
6873 #endif /* CONFIG_WIFI_DISPLAY */
6874
6875         return -1;
6876 }
6877
6878
6879 #ifndef CONFIG_NO_CONFIG_WRITE
6880 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
6881 {
6882         int ret = 0;
6883         struct wpa_supplicant *wpa_s;
6884
6885         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6886                 if (!wpa_s->conf->update_config) {
6887                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
6888                         continue;
6889                 }
6890
6891                 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
6892                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
6893                         ret = 1;
6894                 } else {
6895                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
6896                 }
6897         }
6898
6899         return ret;
6900 }
6901 #endif /* CONFIG_NO_CONFIG_WRITE */
6902
6903
6904 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
6905                                          char *buf, size_t buflen)
6906 {
6907         char *pos, *end;
6908         int ret;
6909         struct wpa_supplicant *wpa_s;
6910
6911         pos = buf;
6912         end = buf + buflen;
6913
6914 #ifdef CONFIG_P2P
6915         if (global->p2p && !global->p2p_disabled) {
6916                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
6917                                   "\n"
6918                                   "p2p_state=%s\n",
6919                                   MAC2STR(global->p2p_dev_addr),
6920                                   p2p_get_state_txt(global->p2p));
6921                 if (ret < 0 || ret >= end - pos)
6922                         return pos - buf;
6923                 pos += ret;
6924         } else if (global->p2p) {
6925                 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
6926                 if (ret < 0 || ret >= end - pos)
6927                         return pos - buf;
6928                 pos += ret;
6929         }
6930 #endif /* CONFIG_P2P */
6931
6932 #ifdef CONFIG_WIFI_DISPLAY
6933         ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
6934                           !!global->wifi_display);
6935         if (ret < 0 || ret >= end - pos)
6936                 return pos - buf;
6937         pos += ret;
6938 #endif /* CONFIG_WIFI_DISPLAY */
6939
6940         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6941                 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
6942                                   "address=" MACSTR "\n",
6943                                   wpa_s->ifname, MAC2STR(wpa_s->own_addr));
6944                 if (ret < 0 || ret >= end - pos)
6945                         return pos - buf;
6946                 pos += ret;
6947         }
6948
6949         return pos - buf;
6950 }
6951
6952
6953 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
6954                                                 char *buf, size_t *resp_len)
6955 {
6956         char *reply;
6957         const int reply_size = 2048;
6958         int reply_len;
6959         int level = MSG_DEBUG;
6960
6961         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
6962                 char *pos = os_strchr(buf + 7, ' ');
6963                 if (pos) {
6964                         *pos++ = '\0';
6965                         return wpas_global_ctrl_iface_ifname(global,
6966                                                              buf + 7, pos,
6967                                                              resp_len);
6968                 }
6969         }
6970
6971         reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
6972         if (reply)
6973                 return reply;
6974
6975         if (os_strcmp(buf, "PING") == 0)
6976                 level = MSG_EXCESSIVE;
6977         wpa_hexdump_ascii(level, "RX global ctrl_iface",
6978                           (const u8 *) buf, os_strlen(buf));
6979
6980         reply = os_malloc(reply_size);
6981         if (reply == NULL) {
6982                 *resp_len = 1;
6983                 return NULL;
6984         }
6985
6986         os_memcpy(reply, "OK\n", 3);
6987         reply_len = 3;
6988
6989         if (os_strcmp(buf, "PING") == 0) {
6990                 os_memcpy(reply, "PONG\n", 5);
6991                 reply_len = 5;
6992         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
6993                 if (wpa_supplicant_global_iface_add(global, buf + 14))
6994                         reply_len = -1;
6995         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
6996                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
6997                         reply_len = -1;
6998         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
6999                 reply_len = wpa_supplicant_global_iface_list(
7000                         global, reply, reply_size);
7001         } else if (os_strcmp(buf, "INTERFACES") == 0) {
7002                 reply_len = wpa_supplicant_global_iface_interfaces(
7003                         global, reply, reply_size);
7004         } else if (os_strcmp(buf, "TERMINATE") == 0) {
7005                 wpa_supplicant_terminate_proc(global);
7006         } else if (os_strcmp(buf, "SUSPEND") == 0) {
7007                 wpas_notify_suspend(global);
7008         } else if (os_strcmp(buf, "RESUME") == 0) {
7009                 wpas_notify_resume(global);
7010         } else if (os_strncmp(buf, "SET ", 4) == 0) {
7011                 if (wpas_global_ctrl_iface_set(global, buf + 4))
7012                         reply_len = -1;
7013 #ifndef CONFIG_NO_CONFIG_WRITE
7014         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
7015                 if (wpas_global_ctrl_iface_save_config(global))
7016                         reply_len = -1;
7017 #endif /* CONFIG_NO_CONFIG_WRITE */
7018         } else if (os_strcmp(buf, "STATUS") == 0) {
7019                 reply_len = wpas_global_ctrl_iface_status(global, reply,
7020                                                           reply_size);
7021 #ifdef CONFIG_MODULE_TESTS
7022         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
7023                 int wpas_module_tests(void);
7024                 if (wpas_module_tests() < 0)
7025                         reply_len = -1;
7026 #endif /* CONFIG_MODULE_TESTS */
7027         } else {
7028                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
7029                 reply_len = 16;
7030         }
7031
7032         if (reply_len < 0) {
7033                 os_memcpy(reply, "FAIL\n", 5);
7034                 reply_len = 5;
7035         }
7036
7037         *resp_len = reply_len;
7038         return reply;
7039 }