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