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