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