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