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