OSDN Git Service

am b5e8f06e: wpa_supplicant: Update to BRCM version 0.8.0-34
[android-x86/external-wpa_supplicant_8.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/version.h"
14 #include "common/ieee802_11_defs.h"
15 #include "common/wpa_ctrl.h"
16 #include "eap_peer/eap.h"
17 #include "eapol_supp/eapol_supp_sm.h"
18 #include "rsn_supp/wpa.h"
19 #include "rsn_supp/preauth.h"
20 #include "rsn_supp/pmksa_cache.h"
21 #include "l2_packet/l2_packet.h"
22 #include "wps/wps.h"
23 #include "config.h"
24 #include "wpa_supplicant_i.h"
25 #include "driver_i.h"
26 #include "wps_supplicant.h"
27 #include "ibss_rsn.h"
28 #include "ap.h"
29 #include "p2p_supplicant.h"
30 #include "p2p/p2p.h"
31 #include "hs20_supplicant.h"
32 #include "notify.h"
33 #include "bss.h"
34 #include "scan.h"
35 #include "ctrl_iface.h"
36 #include "interworking.h"
37 #include "blacklist.h"
38 #include "wpas_glue.h"
39 #include "autoscan.h"
40
41 extern struct wpa_driver_ops *wpa_drivers[];
42
43 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
44                                             char *buf, int len);
45 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
46                                                   char *buf, int len);
47
48
49 static int pno_start(struct wpa_supplicant *wpa_s)
50 {
51         int ret;
52         size_t i, num_ssid;
53         struct wpa_ssid *ssid;
54         struct wpa_driver_scan_params params;
55
56         if (wpa_s->pno)
57                 return 0;
58
59         os_memset(&params, 0, sizeof(params));
60
61         num_ssid = 0;
62         ssid = wpa_s->conf->ssid;
63         while (ssid) {
64                 if (!wpas_network_disabled(wpa_s, ssid))
65                         num_ssid++;
66                 ssid = ssid->next;
67         }
68         if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
69                 wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
70                            "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
71                 num_ssid = WPAS_MAX_SCAN_SSIDS;
72         }
73
74         if (num_ssid == 0) {
75                 wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
76                 return -1;
77         }
78
79         params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
80                                         num_ssid);
81         if (params.filter_ssids == NULL)
82                 return -1;
83         i = 0;
84         ssid = wpa_s->conf->ssid;
85         while (ssid) {
86                 if (!wpas_network_disabled(wpa_s, ssid)) {
87                         params.ssids[i].ssid = ssid->ssid;
88                         params.ssids[i].ssid_len = ssid->ssid_len;
89                         params.num_ssids++;
90                         os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
91                                   ssid->ssid_len);
92                         params.filter_ssids[i].ssid_len = ssid->ssid_len;
93                         params.num_filter_ssids++;
94                         i++;
95                         if (i == num_ssid)
96                                 break;
97                 }
98                 ssid = ssid->next;
99         }
100
101         ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
102         os_free(params.filter_ssids);
103         if (ret == 0)
104                 wpa_s->pno = 1;
105         return ret;
106 }
107
108
109 static int pno_stop(struct wpa_supplicant *wpa_s)
110 {
111         if (wpa_s->pno) {
112                 wpa_s->pno = 0;
113                 return wpa_drv_stop_sched_scan(wpa_s);
114         }
115         return 0;
116 }
117
118
119 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
120 {
121         char *pos;
122         u8 addr[ETH_ALEN], *filter = NULL, *n;
123         size_t count = 0;
124
125         pos = val;
126         while (pos) {
127                 if (*pos == '\0')
128                         break;
129                 if (hwaddr_aton(pos, addr)) {
130                         os_free(filter);
131                         return -1;
132                 }
133                 n = os_realloc(filter, (count + 1) * ETH_ALEN);
134                 if (n == NULL) {
135                         os_free(filter);
136                         return -1;
137                 }
138                 filter = n;
139                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
140                 count++;
141
142                 pos = os_strchr(pos, ' ');
143                 if (pos)
144                         pos++;
145         }
146
147         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
148         os_free(wpa_s->bssid_filter);
149         wpa_s->bssid_filter = filter;
150         wpa_s->bssid_filter_count = count;
151
152         return 0;
153 }
154
155
156 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
157                                          char *cmd)
158 {
159         char *value;
160         int ret = 0;
161
162         value = os_strchr(cmd, ' ');
163         if (value == NULL)
164                 return -1;
165         *value++ = '\0';
166
167         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
168         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
169                 eapol_sm_configure(wpa_s->eapol,
170                                    atoi(value), -1, -1, -1);
171         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
172                 eapol_sm_configure(wpa_s->eapol,
173                                    -1, atoi(value), -1, -1);
174         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
175                 eapol_sm_configure(wpa_s->eapol,
176                                    -1, -1, atoi(value), -1);
177         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
178                 eapol_sm_configure(wpa_s->eapol,
179                                    -1, -1, -1, atoi(value));
180         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
181                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
182                                      atoi(value)))
183                         ret = -1;
184         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
185                    0) {
186                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
187                                      atoi(value)))
188                         ret = -1;
189         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
190                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
191                         ret = -1;
192         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
193                 wpa_s->wps_fragment_size = atoi(value);
194 #ifdef CONFIG_WPS_TESTING
195         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
196                 long int val;
197                 val = strtol(value, NULL, 0);
198                 if (val < 0 || val > 0xff) {
199                         ret = -1;
200                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
201                                    "wps_version_number %ld", val);
202                 } else {
203                         wps_version_number = val;
204                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
205                                    "version %u.%u",
206                                    (wps_version_number & 0xf0) >> 4,
207                                    wps_version_number & 0x0f);
208                 }
209         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
210                 wps_testing_dummy_cred = atoi(value);
211                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
212                            wps_testing_dummy_cred);
213 #endif /* CONFIG_WPS_TESTING */
214         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
215                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
216                         ret = -1;
217 #ifdef CONFIG_TDLS_TESTING
218         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
219                 extern unsigned int tdls_testing;
220                 tdls_testing = strtol(value, NULL, 0);
221                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
222 #endif /* CONFIG_TDLS_TESTING */
223 #ifdef CONFIG_TDLS
224         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
225                 int disabled = atoi(value);
226                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
227                 if (disabled) {
228                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
229                                 ret = -1;
230                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
231                         ret = -1;
232                 wpa_tdls_enable(wpa_s->wpa, !disabled);
233 #endif /* CONFIG_TDLS */
234         } else if (os_strcasecmp(cmd, "pno") == 0) {
235                 if (atoi(value))
236                         ret = pno_start(wpa_s);
237                 else
238                         ret = pno_stop(wpa_s);
239         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
240                 int disabled = atoi(value);
241                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
242                         ret = -1;
243                 else if (disabled)
244                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
245         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
246                 if (os_strcmp(value, "disable") == 0)
247                         wpa_s->set_sta_uapsd = 0;
248                 else {
249                         int be, bk, vi, vo;
250                         char *pos;
251                         /* format: BE,BK,VI,VO;max SP Length */
252                         be = atoi(value);
253                         pos = os_strchr(value, ',');
254                         if (pos == NULL)
255                                 return -1;
256                         pos++;
257                         bk = atoi(pos);
258                         pos = os_strchr(pos, ',');
259                         if (pos == NULL)
260                                 return -1;
261                         pos++;
262                         vi = atoi(pos);
263                         pos = os_strchr(pos, ',');
264                         if (pos == NULL)
265                                 return -1;
266                         pos++;
267                         vo = atoi(pos);
268                         /* ignore max SP Length for now */
269
270                         wpa_s->set_sta_uapsd = 1;
271                         wpa_s->sta_uapsd = 0;
272                         if (be)
273                                 wpa_s->sta_uapsd |= BIT(0);
274                         if (bk)
275                                 wpa_s->sta_uapsd |= BIT(1);
276                         if (vi)
277                                 wpa_s->sta_uapsd |= BIT(2);
278                         if (vo)
279                                 wpa_s->sta_uapsd |= BIT(3);
280                 }
281         } else if (os_strcasecmp(cmd, "ps") == 0) {
282                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
283         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
284                 ret = set_bssid_filter(wpa_s, value);
285         } else {
286                 value[-1] = '=';
287                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
288                 if (ret == 0)
289                         wpa_supplicant_update_config(wpa_s);
290         }
291
292         return ret;
293 }
294
295
296 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
297                                          char *cmd, char *buf, size_t buflen)
298 {
299         int res = -1;
300
301         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
302
303         if (os_strcmp(cmd, "version") == 0) {
304                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
305         } else if (os_strcasecmp(cmd, "country") == 0) {
306                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
307                         res = os_snprintf(buf, buflen, "%c%c",
308                                           wpa_s->conf->country[0],
309                                           wpa_s->conf->country[1]);
310         }
311
312         if (res < 0 || (unsigned int) res >= buflen)
313                 return -1;
314         return res;
315 }
316
317
318 #ifdef IEEE8021X_EAPOL
319 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
320                                              char *addr)
321 {
322         u8 bssid[ETH_ALEN];
323         struct wpa_ssid *ssid = wpa_s->current_ssid;
324
325         if (hwaddr_aton(addr, bssid)) {
326                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
327                            "'%s'", addr);
328                 return -1;
329         }
330
331         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
332         rsn_preauth_deinit(wpa_s->wpa);
333         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
334                 return -1;
335
336         return 0;
337 }
338 #endif /* IEEE8021X_EAPOL */
339
340
341 #ifdef CONFIG_PEERKEY
342 /* MLME-STKSTART.request(peer) */
343 static int wpa_supplicant_ctrl_iface_stkstart(
344         struct wpa_supplicant *wpa_s, char *addr)
345 {
346         u8 peer[ETH_ALEN];
347
348         if (hwaddr_aton(addr, peer)) {
349                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
350                            "address '%s'", addr);
351                 return -1;
352         }
353
354         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
355                    MAC2STR(peer));
356
357         return wpa_sm_stkstart(wpa_s->wpa, peer);
358 }
359 #endif /* CONFIG_PEERKEY */
360
361
362 #ifdef CONFIG_TDLS
363
364 static int wpa_supplicant_ctrl_iface_tdls_discover(
365         struct wpa_supplicant *wpa_s, char *addr)
366 {
367         u8 peer[ETH_ALEN];
368         int ret;
369
370         if (hwaddr_aton(addr, peer)) {
371                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
372                            "address '%s'", addr);
373                 return -1;
374         }
375
376         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
377                    MAC2STR(peer));
378
379         if (wpa_tdls_is_external_setup(wpa_s->wpa))
380                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
381         else
382                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
383
384         return ret;
385 }
386
387
388 static int wpa_supplicant_ctrl_iface_tdls_setup(
389         struct wpa_supplicant *wpa_s, char *addr)
390 {
391         u8 peer[ETH_ALEN];
392         int ret;
393
394         if (hwaddr_aton(addr, peer)) {
395                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
396                            "address '%s'", addr);
397                 return -1;
398         }
399
400         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
401                    MAC2STR(peer));
402
403         ret = wpa_tdls_reneg(wpa_s->wpa, peer);
404         if (ret) {
405                 if (wpa_tdls_is_external_setup(wpa_s->wpa))
406                         ret = wpa_tdls_start(wpa_s->wpa, peer);
407                 else
408                         ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
409         }
410
411         return ret;
412 }
413
414
415 static int wpa_supplicant_ctrl_iface_tdls_teardown(
416         struct wpa_supplicant *wpa_s, char *addr)
417 {
418         u8 peer[ETH_ALEN];
419
420         if (hwaddr_aton(addr, peer)) {
421                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
422                            "address '%s'", addr);
423                 return -1;
424         }
425
426         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
427                    MAC2STR(peer));
428
429         return wpa_tdls_teardown_link(wpa_s->wpa, peer,
430                                       WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
431 }
432
433 #endif /* CONFIG_TDLS */
434
435
436 #ifdef CONFIG_IEEE80211R
437 static int wpa_supplicant_ctrl_iface_ft_ds(
438         struct wpa_supplicant *wpa_s, char *addr)
439 {
440         u8 target_ap[ETH_ALEN];
441         struct wpa_bss *bss;
442         const u8 *mdie;
443
444         if (hwaddr_aton(addr, target_ap)) {
445                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
446                            "address '%s'", addr);
447                 return -1;
448         }
449
450         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
451
452         bss = wpa_bss_get_bssid(wpa_s, target_ap);
453         if (bss)
454                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
455         else
456                 mdie = NULL;
457
458         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
459 }
460 #endif /* CONFIG_IEEE80211R */
461
462
463 #ifdef CONFIG_WPS
464 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
465                                              char *cmd)
466 {
467         u8 bssid[ETH_ALEN], *_bssid = bssid;
468 #ifdef CONFIG_P2P
469         u8 p2p_dev_addr[ETH_ALEN];
470 #endif /* CONFIG_P2P */
471 #ifdef CONFIG_AP
472         u8 *_p2p_dev_addr = NULL;
473 #endif /* CONFIG_AP */
474
475         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
476                 _bssid = NULL;
477 #ifdef CONFIG_P2P
478         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
479                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
480                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
481                                    "P2P Device Address '%s'",
482                                    cmd + 13);
483                         return -1;
484                 }
485                 _p2p_dev_addr = p2p_dev_addr;
486 #endif /* CONFIG_P2P */
487         } else if (hwaddr_aton(cmd, bssid)) {
488                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
489                            cmd);
490                 return -1;
491         }
492
493 #ifdef CONFIG_AP
494         if (wpa_s->ap_iface)
495                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
496 #endif /* CONFIG_AP */
497
498         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
499 }
500
501
502 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
503                                              char *cmd, char *buf,
504                                              size_t buflen)
505 {
506         u8 bssid[ETH_ALEN], *_bssid = bssid;
507         char *pin;
508         int ret;
509
510         pin = os_strchr(cmd, ' ');
511         if (pin)
512                 *pin++ = '\0';
513
514         if (os_strcmp(cmd, "any") == 0)
515                 _bssid = NULL;
516         else if (os_strcmp(cmd, "get") == 0) {
517                 ret = wps_generate_pin();
518                 goto done;
519         } else if (hwaddr_aton(cmd, bssid)) {
520                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
521                            cmd);
522                 return -1;
523         }
524
525 #ifdef CONFIG_AP
526         if (wpa_s->ap_iface)
527                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
528                                                  buf, buflen);
529 #endif /* CONFIG_AP */
530
531         if (pin) {
532                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
533                                          DEV_PW_DEFAULT);
534                 if (ret < 0)
535                         return -1;
536                 ret = os_snprintf(buf, buflen, "%s", pin);
537                 if (ret < 0 || (size_t) ret >= buflen)
538                         return -1;
539                 return ret;
540         }
541
542         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
543         if (ret < 0)
544                 return -1;
545
546 done:
547         /* Return the generated PIN */
548         ret = os_snprintf(buf, buflen, "%08d", ret);
549         if (ret < 0 || (size_t) ret >= buflen)
550                 return -1;
551         return ret;
552 }
553
554
555 static int wpa_supplicant_ctrl_iface_wps_check_pin(
556         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
557 {
558         char pin[9];
559         size_t len;
560         char *pos;
561         int ret;
562
563         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
564                               (u8 *) cmd, os_strlen(cmd));
565         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
566                 if (*pos < '0' || *pos > '9')
567                         continue;
568                 pin[len++] = *pos;
569                 if (len == 9) {
570                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
571                         return -1;
572                 }
573         }
574         if (len != 4 && len != 8) {
575                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
576                 return -1;
577         }
578         pin[len] = '\0';
579
580         if (len == 8) {
581                 unsigned int pin_val;
582                 pin_val = atoi(pin);
583                 if (!wps_pin_valid(pin_val)) {
584                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
585                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
586                         if (ret < 0 || (size_t) ret >= buflen)
587                                 return -1;
588                         return ret;
589                 }
590         }
591
592         ret = os_snprintf(buf, buflen, "%s", pin);
593         if (ret < 0 || (size_t) ret >= buflen)
594                 return -1;
595
596         return ret;
597 }
598
599
600 #ifdef CONFIG_WPS_OOB
601 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
602                                              char *cmd)
603 {
604         char *path, *method, *name;
605
606         path = os_strchr(cmd, ' ');
607         if (path == NULL)
608                 return -1;
609         *path++ = '\0';
610
611         method = os_strchr(path, ' ');
612         if (method == NULL)
613                 return -1;
614         *method++ = '\0';
615
616         name = os_strchr(method, ' ');
617         if (name != NULL)
618                 *name++ = '\0';
619
620         return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
621 }
622 #endif /* CONFIG_WPS_OOB */
623
624
625 #ifdef CONFIG_WPS_NFC
626
627 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
628                                              char *cmd)
629 {
630         u8 bssid[ETH_ALEN], *_bssid = bssid;
631
632         if (cmd == NULL || cmd[0] == '\0')
633                 _bssid = NULL;
634         else if (hwaddr_aton(cmd, bssid))
635                 return -1;
636
637         return wpas_wps_start_nfc(wpa_s, _bssid);
638 }
639
640
641 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
642         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
643 {
644         int ndef;
645         struct wpabuf *buf;
646         int res;
647
648         if (os_strcmp(cmd, "WPS") == 0)
649                 ndef = 0;
650         else if (os_strcmp(cmd, "NDEF") == 0)
651                 ndef = 1;
652         else
653                 return -1;
654
655         buf = wpas_wps_nfc_token(wpa_s, ndef);
656         if (buf == NULL)
657                 return -1;
658
659         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
660                                          wpabuf_len(buf));
661         reply[res++] = '\n';
662         reply[res] = '\0';
663
664         wpabuf_free(buf);
665
666         return res;
667 }
668
669
670 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
671         struct wpa_supplicant *wpa_s, char *pos)
672 {
673         size_t len;
674         struct wpabuf *buf;
675         int ret;
676
677         len = os_strlen(pos);
678         if (len & 0x01)
679                 return -1;
680         len /= 2;
681
682         buf = wpabuf_alloc(len);
683         if (buf == NULL)
684                 return -1;
685         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
686                 wpabuf_free(buf);
687                 return -1;
688         }
689
690         ret = wpas_wps_nfc_tag_read(wpa_s, buf);
691         wpabuf_free(buf);
692
693         return ret;
694 }
695
696 #endif /* CONFIG_WPS_NFC */
697
698
699 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
700                                              char *cmd)
701 {
702         u8 bssid[ETH_ALEN];
703         char *pin;
704         char *new_ssid;
705         char *new_auth;
706         char *new_encr;
707         char *new_key;
708         struct wps_new_ap_settings ap;
709
710         pin = os_strchr(cmd, ' ');
711         if (pin == NULL)
712                 return -1;
713         *pin++ = '\0';
714
715         if (hwaddr_aton(cmd, bssid)) {
716                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
717                            cmd);
718                 return -1;
719         }
720
721         new_ssid = os_strchr(pin, ' ');
722         if (new_ssid == NULL)
723                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
724         *new_ssid++ = '\0';
725
726         new_auth = os_strchr(new_ssid, ' ');
727         if (new_auth == NULL)
728                 return -1;
729         *new_auth++ = '\0';
730
731         new_encr = os_strchr(new_auth, ' ');
732         if (new_encr == NULL)
733                 return -1;
734         *new_encr++ = '\0';
735
736         new_key = os_strchr(new_encr, ' ');
737         if (new_key == NULL)
738                 return -1;
739         *new_key++ = '\0';
740
741         os_memset(&ap, 0, sizeof(ap));
742         ap.ssid_hex = new_ssid;
743         ap.auth = new_auth;
744         ap.encr = new_encr;
745         ap.key_hex = new_key;
746         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
747 }
748
749
750 #ifdef CONFIG_AP
751 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
752                                                 char *cmd, char *buf,
753                                                 size_t buflen)
754 {
755         int timeout = 300;
756         char *pos;
757         const char *pin_txt;
758
759         if (!wpa_s->ap_iface)
760                 return -1;
761
762         pos = os_strchr(cmd, ' ');
763         if (pos)
764                 *pos++ = '\0';
765
766         if (os_strcmp(cmd, "disable") == 0) {
767                 wpas_wps_ap_pin_disable(wpa_s);
768                 return os_snprintf(buf, buflen, "OK\n");
769         }
770
771         if (os_strcmp(cmd, "random") == 0) {
772                 if (pos)
773                         timeout = atoi(pos);
774                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
775                 if (pin_txt == NULL)
776                         return -1;
777                 return os_snprintf(buf, buflen, "%s", pin_txt);
778         }
779
780         if (os_strcmp(cmd, "get") == 0) {
781                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
782                 if (pin_txt == NULL)
783                         return -1;
784                 return os_snprintf(buf, buflen, "%s", pin_txt);
785         }
786
787         if (os_strcmp(cmd, "set") == 0) {
788                 char *pin;
789                 if (pos == NULL)
790                         return -1;
791                 pin = pos;
792                 pos = os_strchr(pos, ' ');
793                 if (pos) {
794                         *pos++ = '\0';
795                         timeout = atoi(pos);
796                 }
797                 if (os_strlen(pin) > buflen)
798                         return -1;
799                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
800                         return -1;
801                 return os_snprintf(buf, buflen, "%s", pin);
802         }
803
804         return -1;
805 }
806 #endif /* CONFIG_AP */
807
808
809 #ifdef CONFIG_WPS_ER
810 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
811                                                 char *cmd)
812 {
813         char *uuid = cmd, *pin, *pos;
814         u8 addr_buf[ETH_ALEN], *addr = NULL;
815         pin = os_strchr(uuid, ' ');
816         if (pin == NULL)
817                 return -1;
818         *pin++ = '\0';
819         pos = os_strchr(pin, ' ');
820         if (pos) {
821                 *pos++ = '\0';
822                 if (hwaddr_aton(pos, addr_buf) == 0)
823                         addr = addr_buf;
824         }
825         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
826 }
827
828
829 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
830                                                   char *cmd)
831 {
832         char *uuid = cmd, *pin;
833         pin = os_strchr(uuid, ' ');
834         if (pin == NULL)
835                 return -1;
836         *pin++ = '\0';
837         return wpas_wps_er_learn(wpa_s, uuid, pin);
838 }
839
840
841 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
842         struct wpa_supplicant *wpa_s, char *cmd)
843 {
844         char *uuid = cmd, *id;
845         id = os_strchr(uuid, ' ');
846         if (id == NULL)
847                 return -1;
848         *id++ = '\0';
849         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
850 }
851
852
853 static int wpa_supplicant_ctrl_iface_wps_er_config(
854         struct wpa_supplicant *wpa_s, char *cmd)
855 {
856         char *pin;
857         char *new_ssid;
858         char *new_auth;
859         char *new_encr;
860         char *new_key;
861         struct wps_new_ap_settings ap;
862
863         pin = os_strchr(cmd, ' ');
864         if (pin == NULL)
865                 return -1;
866         *pin++ = '\0';
867
868         new_ssid = os_strchr(pin, ' ');
869         if (new_ssid == NULL)
870                 return -1;
871         *new_ssid++ = '\0';
872
873         new_auth = os_strchr(new_ssid, ' ');
874         if (new_auth == NULL)
875                 return -1;
876         *new_auth++ = '\0';
877
878         new_encr = os_strchr(new_auth, ' ');
879         if (new_encr == NULL)
880                 return -1;
881         *new_encr++ = '\0';
882
883         new_key = os_strchr(new_encr, ' ');
884         if (new_key == NULL)
885                 return -1;
886         *new_key++ = '\0';
887
888         os_memset(&ap, 0, sizeof(ap));
889         ap.ssid_hex = new_ssid;
890         ap.auth = new_auth;
891         ap.encr = new_encr;
892         ap.key_hex = new_key;
893         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
894 }
895
896
897 #ifdef CONFIG_WPS_NFC
898 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
899         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
900 {
901         int ndef;
902         struct wpabuf *buf;
903         int res;
904         char *uuid;
905
906         uuid = os_strchr(cmd, ' ');
907         if (uuid == NULL)
908                 return -1;
909         *uuid++ = '\0';
910
911         if (os_strcmp(cmd, "WPS") == 0)
912                 ndef = 0;
913         else if (os_strcmp(cmd, "NDEF") == 0)
914                 ndef = 1;
915         else
916                 return -1;
917
918         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
919         if (buf == NULL)
920                 return -1;
921
922         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
923                                          wpabuf_len(buf));
924         reply[res++] = '\n';
925         reply[res] = '\0';
926
927         wpabuf_free(buf);
928
929         return res;
930 }
931 #endif /* CONFIG_WPS_NFC */
932 #endif /* CONFIG_WPS_ER */
933
934 #endif /* CONFIG_WPS */
935
936
937 #ifdef CONFIG_IBSS_RSN
938 static int wpa_supplicant_ctrl_iface_ibss_rsn(
939         struct wpa_supplicant *wpa_s, char *addr)
940 {
941         u8 peer[ETH_ALEN];
942
943         if (hwaddr_aton(addr, peer)) {
944                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
945                            "address '%s'", addr);
946                 return -1;
947         }
948
949         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
950                    MAC2STR(peer));
951
952         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
953 }
954 #endif /* CONFIG_IBSS_RSN */
955
956
957 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
958                                               char *rsp)
959 {
960 #ifdef IEEE8021X_EAPOL
961         char *pos, *id_pos;
962         int id;
963         struct wpa_ssid *ssid;
964
965         pos = os_strchr(rsp, '-');
966         if (pos == NULL)
967                 return -1;
968         *pos++ = '\0';
969         id_pos = pos;
970         pos = os_strchr(pos, ':');
971         if (pos == NULL)
972                 return -1;
973         *pos++ = '\0';
974         id = atoi(id_pos);
975         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
976         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
977                               (u8 *) pos, os_strlen(pos));
978
979         ssid = wpa_config_get_network(wpa_s->conf, id);
980         if (ssid == NULL) {
981                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
982                            "to update", id);
983                 return -1;
984         }
985
986         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
987                                                          pos);
988 #else /* IEEE8021X_EAPOL */
989         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
990         return -1;
991 #endif /* IEEE8021X_EAPOL */
992 }
993
994
995 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
996                                             const char *params,
997                                             char *buf, size_t buflen)
998 {
999         char *pos, *end, tmp[30];
1000         int res, verbose, wps, ret;
1001
1002         verbose = os_strcmp(params, "-VERBOSE") == 0;
1003         wps = os_strcmp(params, "-WPS") == 0;
1004         pos = buf;
1005         end = buf + buflen;
1006         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1007                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1008                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1009                                   MAC2STR(wpa_s->bssid));
1010                 if (ret < 0 || ret >= end - pos)
1011                         return pos - buf;
1012                 pos += ret;
1013                 if (ssid) {
1014                         u8 *_ssid = ssid->ssid;
1015                         size_t ssid_len = ssid->ssid_len;
1016                         u8 ssid_buf[MAX_SSID_LEN];
1017                         if (ssid_len == 0) {
1018                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1019                                 if (_res < 0)
1020                                         ssid_len = 0;
1021                                 else
1022                                         ssid_len = _res;
1023                                 _ssid = ssid_buf;
1024                         }
1025                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1026                                           wpa_ssid_txt(_ssid, ssid_len),
1027                                           ssid->id);
1028                         if (ret < 0 || ret >= end - pos)
1029                                 return pos - buf;
1030                         pos += ret;
1031
1032                         if (wps && ssid->passphrase &&
1033                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1034                             (ssid->mode == WPAS_MODE_AP ||
1035                              ssid->mode == WPAS_MODE_P2P_GO)) {
1036                                 ret = os_snprintf(pos, end - pos,
1037                                                   "passphrase=%s\n",
1038                                                   ssid->passphrase);
1039                                 if (ret < 0 || ret >= end - pos)
1040                                         return pos - buf;
1041                                 pos += ret;
1042                         }
1043                         if (ssid->id_str) {
1044                                 ret = os_snprintf(pos, end - pos,
1045                                                   "id_str=%s\n",
1046                                                   ssid->id_str);
1047                                 if (ret < 0 || ret >= end - pos)
1048                                         return pos - buf;
1049                                 pos += ret;
1050                         }
1051
1052                         switch (ssid->mode) {
1053                         case WPAS_MODE_INFRA:
1054                                 ret = os_snprintf(pos, end - pos,
1055                                                   "mode=station\n");
1056                                 break;
1057                         case WPAS_MODE_IBSS:
1058                                 ret = os_snprintf(pos, end - pos,
1059                                                   "mode=IBSS\n");
1060                                 break;
1061                         case WPAS_MODE_AP:
1062                                 ret = os_snprintf(pos, end - pos,
1063                                                   "mode=AP\n");
1064                                 break;
1065                         case WPAS_MODE_P2P_GO:
1066                                 ret = os_snprintf(pos, end - pos,
1067                                                   "mode=P2P GO\n");
1068                                 break;
1069                         case WPAS_MODE_P2P_GROUP_FORMATION:
1070                                 ret = os_snprintf(pos, end - pos,
1071                                                   "mode=P2P GO - group "
1072                                                   "formation\n");
1073                                 break;
1074                         default:
1075                                 ret = 0;
1076                                 break;
1077                         }
1078                         if (ret < 0 || ret >= end - pos)
1079                                 return pos - buf;
1080                         pos += ret;
1081                 }
1082
1083 #ifdef CONFIG_AP
1084                 if (wpa_s->ap_iface) {
1085                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1086                                                             end - pos,
1087                                                             verbose);
1088                 } else
1089 #endif /* CONFIG_AP */
1090                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1091         }
1092         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1093                           wpa_supplicant_state_txt(wpa_s->wpa_state));
1094         if (ret < 0 || ret >= end - pos)
1095                 return pos - buf;
1096         pos += ret;
1097
1098         if (wpa_s->l2 &&
1099             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1100                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1101                 if (ret < 0 || ret >= end - pos)
1102                         return pos - buf;
1103                 pos += ret;
1104         }
1105
1106 #ifdef CONFIG_P2P
1107         if (wpa_s->global->p2p) {
1108                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1109                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1110                 if (ret < 0 || ret >= end - pos)
1111                         return pos - buf;
1112                 pos += ret;
1113         }
1114 #endif /* CONFIG_P2P */
1115
1116         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1117                           MAC2STR(wpa_s->own_addr));
1118         if (ret < 0 || ret >= end - pos)
1119                 return pos - buf;
1120         pos += ret;
1121
1122 #ifdef CONFIG_HS20
1123         if (wpa_s->current_bss &&
1124             wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE)) {
1125                 ret = os_snprintf(pos, end - pos, "hs20=1\n");
1126                 if (ret < 0 || ret >= end - pos)
1127                         return pos - buf;
1128                 pos += ret;
1129         }
1130 #endif /* CONFIG_HS20 */
1131
1132         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1133             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1134                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1135                                           verbose);
1136                 if (res >= 0)
1137                         pos += res;
1138         }
1139
1140         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1141         if (res >= 0)
1142                 pos += res;
1143
1144 #ifdef ANDROID
1145         wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1146                      "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1147                      wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1148                      wpa_s->wpa_state,
1149                      MAC2STR(wpa_s->bssid),
1150                      wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1151                      wpa_ssid_txt(wpa_s->current_ssid->ssid,
1152                      wpa_s->current_ssid->ssid_len) : "");
1153         if (wpa_s->wpa_state == WPA_COMPLETED) {
1154                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1155                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- connection to "
1156                         MACSTR " completed %s [id=%d id_str=%s]",
1157                         MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ?
1158                         "(reauth)" : "(auth)",
1159                         ssid ? ssid->id : -1,
1160                         ssid && ssid->id_str ? ssid->id_str : "");
1161         }
1162 #endif /* ANDROID */
1163
1164         return pos - buf;
1165 }
1166
1167
1168 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
1169                                            char *cmd)
1170 {
1171         char *pos;
1172         int id;
1173         struct wpa_ssid *ssid;
1174         u8 bssid[ETH_ALEN];
1175
1176         /* cmd: "<network id> <BSSID>" */
1177         pos = os_strchr(cmd, ' ');
1178         if (pos == NULL)
1179                 return -1;
1180         *pos++ = '\0';
1181         id = atoi(cmd);
1182         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
1183         if (hwaddr_aton(pos, bssid)) {
1184                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
1185                 return -1;
1186         }
1187
1188         ssid = wpa_config_get_network(wpa_s->conf, id);
1189         if (ssid == NULL) {
1190                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1191                            "to update", id);
1192                 return -1;
1193         }
1194
1195         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
1196         ssid->bssid_set = !is_zero_ether_addr(bssid);
1197
1198         return 0;
1199 }
1200
1201
1202 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1203                                                char *cmd, char *buf,
1204                                                size_t buflen)
1205 {
1206         u8 bssid[ETH_ALEN];
1207         struct wpa_blacklist *e;
1208         char *pos, *end;
1209         int ret;
1210
1211         /* cmd: "BLACKLIST [<BSSID>]" */
1212         if (*cmd == '\0') {
1213                 pos = buf;
1214                 end = buf + buflen;
1215                 e = wpa_s->blacklist;
1216                 while (e) {
1217                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
1218                                           MAC2STR(e->bssid));
1219                         if (ret < 0 || ret >= end - pos)
1220                                 return pos - buf;
1221                         pos += ret;
1222                         e = e->next;
1223                 }
1224                 return pos - buf;
1225         }
1226
1227         cmd++;
1228         if (os_strncmp(cmd, "clear", 5) == 0) {
1229                 wpa_blacklist_clear(wpa_s);
1230                 os_memcpy(buf, "OK\n", 3);
1231                 return 3;
1232         }
1233
1234         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1235         if (hwaddr_aton(cmd, bssid)) {
1236                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
1237                 return -1;
1238         }
1239
1240         /*
1241          * Add the BSSID twice, so its count will be 2, causing it to be
1242          * skipped when processing scan results.
1243          */
1244         ret = wpa_blacklist_add(wpa_s, bssid);
1245         if (ret != 0)
1246                 return -1;
1247         ret = wpa_blacklist_add(wpa_s, bssid);
1248         if (ret != 0)
1249                 return -1;
1250         os_memcpy(buf, "OK\n", 3);
1251         return 3;
1252 }
1253
1254
1255 extern int wpa_debug_level;
1256 extern int wpa_debug_timestamp;
1257
1258 static const char * debug_level_str(int level)
1259 {
1260         switch (level) {
1261         case MSG_EXCESSIVE:
1262                 return "EXCESSIVE";
1263         case MSG_MSGDUMP:
1264                 return "MSGDUMP";
1265         case MSG_DEBUG:
1266                 return "DEBUG";
1267         case MSG_INFO:
1268                 return "INFO";
1269         case MSG_WARNING:
1270                 return "WARNING";
1271         case MSG_ERROR:
1272                 return "ERROR";
1273         default:
1274                 return "?";
1275         }
1276 }
1277
1278
1279 static int str_to_debug_level(const char *s)
1280 {
1281         if (os_strcasecmp(s, "EXCESSIVE") == 0)
1282                 return MSG_EXCESSIVE;
1283         if (os_strcasecmp(s, "MSGDUMP") == 0)
1284                 return MSG_MSGDUMP;
1285         if (os_strcasecmp(s, "DEBUG") == 0)
1286                 return MSG_DEBUG;
1287         if (os_strcasecmp(s, "INFO") == 0)
1288                 return MSG_INFO;
1289         if (os_strcasecmp(s, "WARNING") == 0)
1290                 return MSG_WARNING;
1291         if (os_strcasecmp(s, "ERROR") == 0)
1292                 return MSG_ERROR;
1293         return -1;
1294 }
1295
1296
1297 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
1298                                                char *cmd, char *buf,
1299                                                size_t buflen)
1300 {
1301         char *pos, *end, *stamp;
1302         int ret;
1303
1304         if (cmd == NULL) {
1305                 return -1;
1306         }
1307
1308         /* cmd: "LOG_LEVEL [<level>]" */
1309         if (*cmd == '\0') {
1310                 pos = buf;
1311                 end = buf + buflen;
1312                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1313                                   "Timestamp: %d\n",
1314                                   debug_level_str(wpa_debug_level),
1315                                   wpa_debug_timestamp);
1316                 if (ret < 0 || ret >= end - pos)
1317                         ret = 0;
1318
1319                 return ret;
1320         }
1321
1322         while (*cmd == ' ')
1323                 cmd++;
1324
1325         stamp = os_strchr(cmd, ' ');
1326         if (stamp) {
1327                 *stamp++ = '\0';
1328                 while (*stamp == ' ') {
1329                         stamp++;
1330                 }
1331         }
1332
1333         if (cmd && os_strlen(cmd)) {
1334                 int level = str_to_debug_level(cmd);
1335                 if (level < 0)
1336                         return -1;
1337                 wpa_debug_level = level;
1338         }
1339
1340         if (stamp && os_strlen(stamp))
1341                 wpa_debug_timestamp = atoi(stamp);
1342
1343         os_memcpy(buf, "OK\n", 3);
1344         return 3;
1345 }
1346
1347
1348 static int wpa_supplicant_ctrl_iface_list_networks(
1349         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1350 {
1351         char *pos, *end;
1352         struct wpa_ssid *ssid;
1353         int ret;
1354
1355         pos = buf;
1356         end = buf + buflen;
1357         ret = os_snprintf(pos, end - pos,
1358                           "network id / ssid / bssid / flags\n");
1359         if (ret < 0 || ret >= end - pos)
1360                 return pos - buf;
1361         pos += ret;
1362
1363         ssid = wpa_s->conf->ssid;
1364         while (ssid) {
1365                 ret = os_snprintf(pos, end - pos, "%d\t%s",
1366                                   ssid->id,
1367                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1368                 if (ret < 0 || ret >= end - pos)
1369                         return pos - buf;
1370                 pos += ret;
1371                 if (ssid->bssid_set) {
1372                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1373                                           MAC2STR(ssid->bssid));
1374                 } else {
1375                         ret = os_snprintf(pos, end - pos, "\tany");
1376                 }
1377                 if (ret < 0 || ret >= end - pos)
1378                         return pos - buf;
1379                 pos += ret;
1380                 ret = os_snprintf(pos, end - pos, "\t%s%s%s",
1381                                   ssid == wpa_s->current_ssid ?
1382                                   "[CURRENT]" : "",
1383                                   ssid->disabled ? "[DISABLED]" : "",
1384                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1385                                   "");
1386                 if (ret < 0 || ret >= end - pos)
1387                         return pos - buf;
1388                 pos += ret;
1389                 ret = os_snprintf(pos, end - pos, "\n");
1390                 if (ret < 0 || ret >= end - pos)
1391                         return pos - buf;
1392                 pos += ret;
1393
1394                 ssid = ssid->next;
1395         }
1396
1397         return pos - buf;
1398 }
1399
1400
1401 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1402 {
1403         int first = 1, ret;
1404         ret = os_snprintf(pos, end - pos, "-");
1405         if (ret < 0 || ret >= end - pos)
1406                 return pos;
1407         pos += ret;
1408         if (cipher & WPA_CIPHER_NONE) {
1409                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
1410                 if (ret < 0 || ret >= end - pos)
1411                         return pos;
1412                 pos += ret;
1413                 first = 0;
1414         }
1415         if (cipher & WPA_CIPHER_WEP40) {
1416                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
1417                 if (ret < 0 || ret >= end - pos)
1418                         return pos;
1419                 pos += ret;
1420                 first = 0;
1421         }
1422         if (cipher & WPA_CIPHER_WEP104) {
1423                 ret = os_snprintf(pos, end - pos, "%sWEP104",
1424                                   first ? "" : "+");
1425                 if (ret < 0 || ret >= end - pos)
1426                         return pos;
1427                 pos += ret;
1428                 first = 0;
1429         }
1430         if (cipher & WPA_CIPHER_TKIP) {
1431                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
1432                 if (ret < 0 || ret >= end - pos)
1433                         return pos;
1434                 pos += ret;
1435                 first = 0;
1436         }
1437         if (cipher & WPA_CIPHER_CCMP) {
1438                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
1439                 if (ret < 0 || ret >= end - pos)
1440                         return pos;
1441                 pos += ret;
1442                 first = 0;
1443         }
1444         return pos;
1445 }
1446
1447
1448 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1449                                     const u8 *ie, size_t ie_len)
1450 {
1451         struct wpa_ie_data data;
1452         int first, ret;
1453
1454         ret = os_snprintf(pos, end - pos, "[%s-", proto);
1455         if (ret < 0 || ret >= end - pos)
1456                 return pos;
1457         pos += ret;
1458
1459         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1460                 ret = os_snprintf(pos, end - pos, "?]");
1461                 if (ret < 0 || ret >= end - pos)
1462                         return pos;
1463                 pos += ret;
1464                 return pos;
1465         }
1466
1467         first = 1;
1468         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1469                 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1470                 if (ret < 0 || ret >= end - pos)
1471                         return pos;
1472                 pos += ret;
1473                 first = 0;
1474         }
1475         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1476                 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1477                 if (ret < 0 || ret >= end - pos)
1478                         return pos;
1479                 pos += ret;
1480                 first = 0;
1481         }
1482         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1483                 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1484                 if (ret < 0 || ret >= end - pos)
1485                         return pos;
1486                 pos += ret;
1487                 first = 0;
1488         }
1489 #ifdef CONFIG_IEEE80211R
1490         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1491                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1492                                   first ? "" : "+");
1493                 if (ret < 0 || ret >= end - pos)
1494                         return pos;
1495                 pos += ret;
1496                 first = 0;
1497         }
1498         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1499                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1500                                   first ? "" : "+");
1501                 if (ret < 0 || ret >= end - pos)
1502                         return pos;
1503                 pos += ret;
1504                 first = 0;
1505         }
1506 #endif /* CONFIG_IEEE80211R */
1507 #ifdef CONFIG_IEEE80211W
1508         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1509                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1510                                   first ? "" : "+");
1511                 if (ret < 0 || ret >= end - pos)
1512                         return pos;
1513                 pos += ret;
1514                 first = 0;
1515         }
1516         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1517                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1518                                   first ? "" : "+");
1519                 if (ret < 0 || ret >= end - pos)
1520                         return pos;
1521                 pos += ret;
1522                 first = 0;
1523         }
1524 #endif /* CONFIG_IEEE80211W */
1525
1526         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1527
1528         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1529                 ret = os_snprintf(pos, end - pos, "-preauth");
1530                 if (ret < 0 || ret >= end - pos)
1531                         return pos;
1532                 pos += ret;
1533         }
1534
1535         ret = os_snprintf(pos, end - pos, "]");
1536         if (ret < 0 || ret >= end - pos)
1537                 return pos;
1538         pos += ret;
1539
1540         return pos;
1541 }
1542
1543
1544 #ifdef CONFIG_WPS
1545 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1546                                             char *pos, char *end,
1547                                             struct wpabuf *wps_ie)
1548 {
1549         int ret;
1550         const char *txt;
1551
1552         if (wps_ie == NULL)
1553                 return pos;
1554         if (wps_is_selected_pbc_registrar(wps_ie))
1555                 txt = "[WPS-PBC]";
1556 #ifdef CONFIG_WPS2
1557         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1558                 txt = "[WPS-AUTH]";
1559 #endif /* CONFIG_WPS2 */
1560         else if (wps_is_selected_pin_registrar(wps_ie))
1561                 txt = "[WPS-PIN]";
1562         else
1563                 txt = "[WPS]";
1564
1565         ret = os_snprintf(pos, end - pos, "%s", txt);
1566         if (ret >= 0 && ret < end - pos)
1567                 pos += ret;
1568         wpabuf_free(wps_ie);
1569         return pos;
1570 }
1571 #endif /* CONFIG_WPS */
1572
1573
1574 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1575                                         char *pos, char *end,
1576                                         const struct wpa_bss *bss)
1577 {
1578 #ifdef CONFIG_WPS
1579         struct wpabuf *wps_ie;
1580         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1581         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1582 #else /* CONFIG_WPS */
1583         return pos;
1584 #endif /* CONFIG_WPS */
1585 }
1586
1587
1588 /* Format one result on one text line into a buffer. */
1589 static int wpa_supplicant_ctrl_iface_scan_result(
1590         struct wpa_supplicant *wpa_s,
1591         const struct wpa_bss *bss, char *buf, size_t buflen)
1592 {
1593         char *pos, *end;
1594         int ret;
1595         const u8 *ie, *ie2, *p2p;
1596
1597         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
1598         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
1599             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
1600             0)
1601                 return 0; /* Do not show P2P listen discovery results here */
1602
1603         pos = buf;
1604         end = buf + buflen;
1605
1606         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1607                           MAC2STR(bss->bssid), bss->freq, bss->level);
1608         if (ret < 0 || ret >= end - pos)
1609                 return -1;
1610         pos += ret;
1611         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1612         if (ie)
1613                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1614         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1615         if (ie2)
1616                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1617         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1618         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1619                 ret = os_snprintf(pos, end - pos, "[WEP]");
1620                 if (ret < 0 || ret >= end - pos)
1621                         return -1;
1622                 pos += ret;
1623         }
1624         if (bss->caps & IEEE80211_CAP_IBSS) {
1625                 ret = os_snprintf(pos, end - pos, "[IBSS]");
1626                 if (ret < 0 || ret >= end - pos)
1627                         return -1;
1628                 pos += ret;
1629         }
1630         if (bss->caps & IEEE80211_CAP_ESS) {
1631                 ret = os_snprintf(pos, end - pos, "[ESS]");
1632                 if (ret < 0 || ret >= end - pos)
1633                         return -1;
1634                 pos += ret;
1635         }
1636         if (p2p) {
1637                 ret = os_snprintf(pos, end - pos, "[P2P]");
1638                 if (ret < 0 || ret >= end - pos)
1639                         return -1;
1640                 pos += ret;
1641         }
1642 #ifdef CONFIG_HS20
1643         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
1644                 ret = os_snprintf(pos, end - pos, "[HS20]");
1645                 if (ret < 0 || ret >= end - pos)
1646                         return -1;
1647                 pos += ret;
1648         }
1649 #endif /* CONFIG_HS20 */
1650
1651         ret = os_snprintf(pos, end - pos, "\t%s",
1652                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
1653         if (ret < 0 || ret >= end - pos)
1654                 return -1;
1655         pos += ret;
1656
1657         ret = os_snprintf(pos, end - pos, "\n");
1658         if (ret < 0 || ret >= end - pos)
1659                 return -1;
1660         pos += ret;
1661
1662         return pos - buf;
1663 }
1664
1665
1666 static int wpa_supplicant_ctrl_iface_scan_results(
1667         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1668 {
1669         char *pos, *end;
1670         struct wpa_bss *bss;
1671         int ret;
1672
1673         pos = buf;
1674         end = buf + buflen;
1675         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
1676                           "flags / ssid\n");
1677         if (ret < 0 || ret >= end - pos)
1678                 return pos - buf;
1679         pos += ret;
1680
1681         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1682                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
1683                                                             end - pos);
1684                 if (ret < 0 || ret >= end - pos)
1685                         return pos - buf;
1686                 pos += ret;
1687         }
1688
1689         return pos - buf;
1690 }
1691
1692
1693 static int wpa_supplicant_ctrl_iface_select_network(
1694         struct wpa_supplicant *wpa_s, char *cmd)
1695 {
1696         int id;
1697         struct wpa_ssid *ssid;
1698
1699         /* cmd: "<network id>" or "any" */
1700         if (os_strcmp(cmd, "any") == 0) {
1701                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
1702                 ssid = NULL;
1703         } else {
1704                 id = atoi(cmd);
1705                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
1706
1707                 ssid = wpa_config_get_network(wpa_s->conf, id);
1708                 if (ssid == NULL) {
1709                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1710                                    "network id=%d", id);
1711                         return -1;
1712                 }
1713                 if (ssid->disabled == 2) {
1714                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1715                                    "SELECT_NETWORK with persistent P2P group");
1716                         return -1;
1717                 }
1718         }
1719
1720         wpa_supplicant_select_network(wpa_s, ssid);
1721
1722         return 0;
1723 }
1724
1725
1726 static int wpa_supplicant_ctrl_iface_enable_network(
1727         struct wpa_supplicant *wpa_s, char *cmd)
1728 {
1729         int id;
1730         struct wpa_ssid *ssid;
1731
1732         /* cmd: "<network id>" or "all" */
1733         if (os_strcmp(cmd, "all") == 0) {
1734                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1735                 ssid = NULL;
1736         } else {
1737                 id = atoi(cmd);
1738                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1739
1740                 ssid = wpa_config_get_network(wpa_s->conf, id);
1741                 if (ssid == NULL) {
1742                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1743                                    "network id=%d", id);
1744                         return -1;
1745                 }
1746                 if (ssid->disabled == 2) {
1747                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1748                                    "ENABLE_NETWORK with persistent P2P group");
1749                         return -1;
1750                 }
1751
1752                 if (os_strstr(cmd, " no-connect")) {
1753                         ssid->disabled = 0;
1754                         return 0;
1755                 }
1756         }
1757         wpa_supplicant_enable_network(wpa_s, ssid);
1758
1759         return 0;
1760 }
1761
1762
1763 static int wpa_supplicant_ctrl_iface_disable_network(
1764         struct wpa_supplicant *wpa_s, char *cmd)
1765 {
1766         int id;
1767         struct wpa_ssid *ssid;
1768
1769         /* cmd: "<network id>" or "all" */
1770         if (os_strcmp(cmd, "all") == 0) {
1771                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1772                 ssid = NULL;
1773         } else {
1774                 id = atoi(cmd);
1775                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1776
1777                 ssid = wpa_config_get_network(wpa_s->conf, id);
1778                 if (ssid == NULL) {
1779                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1780                                    "network id=%d", id);
1781                         return -1;
1782                 }
1783                 if (ssid->disabled == 2) {
1784                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1785                                    "DISABLE_NETWORK with persistent P2P "
1786                                    "group");
1787                         return -1;
1788                 }
1789         }
1790         wpa_supplicant_disable_network(wpa_s, ssid);
1791
1792         return 0;
1793 }
1794
1795
1796 static int wpa_supplicant_ctrl_iface_add_network(
1797         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1798 {
1799         struct wpa_ssid *ssid;
1800         int ret;
1801
1802         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1803
1804         ssid = wpa_config_add_network(wpa_s->conf);
1805         if (ssid == NULL)
1806                 return -1;
1807
1808         wpas_notify_network_added(wpa_s, ssid);
1809
1810         ssid->disabled = 1;
1811         wpa_config_set_network_defaults(ssid);
1812
1813         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1814         if (ret < 0 || (size_t) ret >= buflen)
1815                 return -1;
1816         return ret;
1817 }
1818
1819
1820 static int wpa_supplicant_ctrl_iface_remove_network(
1821         struct wpa_supplicant *wpa_s, char *cmd)
1822 {
1823         int id;
1824         struct wpa_ssid *ssid;
1825
1826         /* cmd: "<network id>" or "all" */
1827         if (os_strcmp(cmd, "all") == 0) {
1828                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1829                 ssid = wpa_s->conf->ssid;
1830                 while (ssid) {
1831                         struct wpa_ssid *remove_ssid = ssid;
1832                         id = ssid->id;
1833                         ssid = ssid->next;
1834                         wpas_notify_network_removed(wpa_s, remove_ssid);
1835                         wpa_config_remove_network(wpa_s->conf, id);
1836                 }
1837                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1838                 if (wpa_s->current_ssid) {
1839 #ifdef CONFIG_SME
1840                         wpa_s->sme.prev_bssid_set = 0;
1841 #endif /* CONFIG_SME */
1842                         wpa_sm_set_config(wpa_s->wpa, NULL);
1843                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1844                         wpa_supplicant_disassociate(wpa_s,
1845                                                     WLAN_REASON_DEAUTH_LEAVING);
1846                 }
1847                 return 0;
1848         }
1849
1850         id = atoi(cmd);
1851         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1852
1853         ssid = wpa_config_get_network(wpa_s->conf, id);
1854         if (ssid)
1855                 wpas_notify_network_removed(wpa_s, ssid);
1856         if (ssid == NULL ||
1857             wpa_config_remove_network(wpa_s->conf, id) < 0) {
1858                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1859                            "id=%d", id);
1860                 return -1;
1861         }
1862
1863         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
1864 #ifdef CONFIG_SME
1865                 wpa_s->sme.prev_bssid_set = 0;
1866 #endif /* CONFIG_SME */
1867                 /*
1868                  * Invalidate the EAP session cache if the current or
1869                  * previously used network is removed.
1870                  */
1871                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1872         }
1873
1874         if (ssid == wpa_s->current_ssid) {
1875                 wpa_sm_set_config(wpa_s->wpa, NULL);
1876                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1877
1878                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1879         }
1880
1881         return 0;
1882 }
1883
1884
1885 static int wpa_supplicant_ctrl_iface_set_network(
1886         struct wpa_supplicant *wpa_s, char *cmd)
1887 {
1888         int id;
1889         struct wpa_ssid *ssid;
1890         char *name, *value;
1891
1892         /* cmd: "<network id> <variable name> <value>" */
1893         name = os_strchr(cmd, ' ');
1894         if (name == NULL)
1895                 return -1;
1896         *name++ = '\0';
1897
1898         value = os_strchr(name, ' ');
1899         if (value == NULL)
1900                 return -1;
1901         *value++ = '\0';
1902
1903         id = atoi(cmd);
1904         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1905                    id, name);
1906         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1907                               (u8 *) value, os_strlen(value));
1908
1909         ssid = wpa_config_get_network(wpa_s->conf, id);
1910         if (ssid == NULL) {
1911                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1912                            "id=%d", id);
1913                 return -1;
1914         }
1915
1916         if (wpa_config_set(ssid, name, value, 0) < 0) {
1917                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1918                            "variable '%s'", name);
1919                 return -1;
1920         }
1921
1922         wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1923
1924         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
1925                 /*
1926                  * Invalidate the EAP session cache if anything in the current
1927                  * or previously used configuration changes.
1928                  */
1929                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1930         }
1931
1932         if ((os_strcmp(name, "psk") == 0 &&
1933              value[0] == '"' && ssid->ssid_len) ||
1934             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1935                 wpa_config_update_psk(ssid);
1936         else if (os_strcmp(name, "priority") == 0)
1937                 wpa_config_update_prio_list(wpa_s->conf);
1938
1939         return 0;
1940 }
1941
1942
1943 static int wpa_supplicant_ctrl_iface_get_network(
1944         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1945 {
1946         int id;
1947         size_t res;
1948         struct wpa_ssid *ssid;
1949         char *name, *value;
1950
1951         /* cmd: "<network id> <variable name>" */
1952         name = os_strchr(cmd, ' ');
1953         if (name == NULL || buflen == 0)
1954                 return -1;
1955         *name++ = '\0';
1956
1957         id = atoi(cmd);
1958         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1959                    id, name);
1960
1961         ssid = wpa_config_get_network(wpa_s->conf, id);
1962         if (ssid == NULL) {
1963                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1964                            "id=%d", id);
1965                 return -1;
1966         }
1967
1968         value = wpa_config_get_no_key(ssid, name);
1969         if (value == NULL) {
1970                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1971                            "variable '%s'", name);
1972                 return -1;
1973         }
1974
1975         res = os_strlcpy(buf, value, buflen);
1976         if (res >= buflen) {
1977                 os_free(value);
1978                 return -1;
1979         }
1980
1981         os_free(value);
1982
1983         return res;
1984 }
1985
1986
1987 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
1988                                                 char *buf, size_t buflen)
1989 {
1990         char *pos, *end;
1991         struct wpa_cred *cred;
1992         int ret;
1993
1994         pos = buf;
1995         end = buf + buflen;
1996         ret = os_snprintf(pos, end - pos,
1997                           "cred id / realm / username / domain / imsi\n");
1998         if (ret < 0 || ret >= end - pos)
1999                 return pos - buf;
2000         pos += ret;
2001
2002         cred = wpa_s->conf->cred;
2003         while (cred) {
2004                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
2005                                   cred->id, cred->realm ? cred->realm : "",
2006                                   cred->username ? cred->username : "",
2007                                   cred->domain ? cred->domain : "",
2008                                   cred->imsi ? cred->imsi : "");
2009                 if (ret < 0 || ret >= end - pos)
2010                         return pos - buf;
2011                 pos += ret;
2012
2013                 cred = cred->next;
2014         }
2015
2016         return pos - buf;
2017 }
2018
2019
2020 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2021                                               char *buf, size_t buflen)
2022 {
2023         struct wpa_cred *cred;
2024         int ret;
2025
2026         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2027
2028         cred = wpa_config_add_cred(wpa_s->conf);
2029         if (cred == NULL)
2030                 return -1;
2031
2032         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2033         if (ret < 0 || (size_t) ret >= buflen)
2034                 return -1;
2035         return ret;
2036 }
2037
2038
2039 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2040                                                  char *cmd)
2041 {
2042         int id;
2043         struct wpa_cred *cred;
2044
2045         /* cmd: "<cred id>" or "all" */
2046         if (os_strcmp(cmd, "all") == 0) {
2047                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2048                 cred = wpa_s->conf->cred;
2049                 while (cred) {
2050                         id = cred->id;
2051                         cred = cred->next;
2052                         wpa_config_remove_cred(wpa_s->conf, id);
2053                 }
2054                 return 0;
2055         }
2056
2057         id = atoi(cmd);
2058         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2059
2060         cred = wpa_config_get_cred(wpa_s->conf, id);
2061         if (cred == NULL ||
2062             wpa_config_remove_cred(wpa_s->conf, id) < 0) {
2063                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2064                            id);
2065                 return -1;
2066         }
2067
2068         return 0;
2069 }
2070
2071
2072 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2073                                               char *cmd)
2074 {
2075         int id;
2076         struct wpa_cred *cred;
2077         char *name, *value;
2078
2079         /* cmd: "<cred id> <variable name> <value>" */
2080         name = os_strchr(cmd, ' ');
2081         if (name == NULL)
2082                 return -1;
2083         *name++ = '\0';
2084
2085         value = os_strchr(name, ' ');
2086         if (value == NULL)
2087                 return -1;
2088         *value++ = '\0';
2089
2090         id = atoi(cmd);
2091         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2092                    id, name);
2093         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2094                               (u8 *) value, os_strlen(value));
2095
2096         cred = wpa_config_get_cred(wpa_s->conf, id);
2097         if (cred == NULL) {
2098                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2099                            id);
2100                 return -1;
2101         }
2102
2103         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2104                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2105                            "variable '%s'", name);
2106                 return -1;
2107         }
2108
2109         return 0;
2110 }
2111
2112
2113 #ifndef CONFIG_NO_CONFIG_WRITE
2114 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2115 {
2116         int ret;
2117
2118         if (!wpa_s->conf->update_config) {
2119                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2120                            "to update configuration (update_config=0)");
2121                 return -1;
2122         }
2123
2124         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2125         if (ret) {
2126                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2127                            "update configuration");
2128         } else {
2129                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2130                            " updated");
2131         }
2132
2133         return ret;
2134 }
2135 #endif /* CONFIG_NO_CONFIG_WRITE */
2136
2137
2138 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2139                                               struct wpa_driver_capa *capa,
2140                                               char *buf, size_t buflen)
2141 {
2142         int ret, first = 1;
2143         char *pos, *end;
2144         size_t len;
2145
2146         pos = buf;
2147         end = pos + buflen;
2148
2149         if (res < 0) {
2150                 if (strict)
2151                         return 0;
2152                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2153                 if (len >= buflen)
2154                         return -1;
2155                 return len;
2156         }
2157
2158         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2159                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2160                 if (ret < 0 || ret >= end - pos)
2161                         return pos - buf;
2162                 pos += ret;
2163                 first = 0;
2164         }
2165
2166         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2167                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2168                 if (ret < 0 || ret >= end - pos)
2169                         return pos - buf;
2170                 pos += ret;
2171                 first = 0;
2172         }
2173
2174         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2175                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
2176                 if (ret < 0 || ret >= end - pos)
2177                         return pos - buf;
2178                 pos += ret;
2179                 first = 0;
2180         }
2181
2182         return pos - buf;
2183 }
2184
2185
2186 static int ctrl_iface_get_capability_group(int res, char *strict,
2187                                            struct wpa_driver_capa *capa,
2188                                            char *buf, size_t buflen)
2189 {
2190         int ret, first = 1;
2191         char *pos, *end;
2192         size_t len;
2193
2194         pos = buf;
2195         end = pos + buflen;
2196
2197         if (res < 0) {
2198                 if (strict)
2199                         return 0;
2200                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2201                 if (len >= buflen)
2202                         return -1;
2203                 return len;
2204         }
2205
2206         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2207                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2208                 if (ret < 0 || ret >= end - pos)
2209                         return pos - buf;
2210                 pos += ret;
2211                 first = 0;
2212         }
2213
2214         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2215                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2216                 if (ret < 0 || ret >= end - pos)
2217                         return pos - buf;
2218                 pos += ret;
2219                 first = 0;
2220         }
2221
2222         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2223                 ret = os_snprintf(pos, end - pos, "%sWEP104",
2224                                   first ? "" : " ");
2225                 if (ret < 0 || ret >= end - pos)
2226                         return pos - buf;
2227                 pos += ret;
2228                 first = 0;
2229         }
2230
2231         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2232                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
2233                 if (ret < 0 || ret >= end - pos)
2234                         return pos - buf;
2235                 pos += ret;
2236                 first = 0;
2237         }
2238
2239         return pos - buf;
2240 }
2241
2242
2243 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2244                                               struct wpa_driver_capa *capa,
2245                                               char *buf, size_t buflen)
2246 {
2247         int ret;
2248         char *pos, *end;
2249         size_t len;
2250
2251         pos = buf;
2252         end = pos + buflen;
2253
2254         if (res < 0) {
2255                 if (strict)
2256                         return 0;
2257                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
2258                                  "NONE", buflen);
2259                 if (len >= buflen)
2260                         return -1;
2261                 return len;
2262         }
2263
2264         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
2265         if (ret < 0 || ret >= end - pos)
2266                 return pos - buf;
2267         pos += ret;
2268
2269         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2270                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2271                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
2272                 if (ret < 0 || ret >= end - pos)
2273                         return pos - buf;
2274                 pos += ret;
2275         }
2276
2277         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2278                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2279                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
2280                 if (ret < 0 || ret >= end - pos)
2281                         return pos - buf;
2282                 pos += ret;
2283         }
2284
2285         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2286                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
2287                 if (ret < 0 || ret >= end - pos)
2288                         return pos - buf;
2289                 pos += ret;
2290         }
2291
2292         return pos - buf;
2293 }
2294
2295
2296 static int ctrl_iface_get_capability_proto(int res, char *strict,
2297                                            struct wpa_driver_capa *capa,
2298                                            char *buf, size_t buflen)
2299 {
2300         int ret, first = 1;
2301         char *pos, *end;
2302         size_t len;
2303
2304         pos = buf;
2305         end = pos + buflen;
2306
2307         if (res < 0) {
2308                 if (strict)
2309                         return 0;
2310                 len = os_strlcpy(buf, "RSN WPA", buflen);
2311                 if (len >= buflen)
2312                         return -1;
2313                 return len;
2314         }
2315
2316         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2317                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2318                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
2319                 if (ret < 0 || ret >= end - pos)
2320                         return pos - buf;
2321                 pos += ret;
2322                 first = 0;
2323         }
2324
2325         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2326                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2327                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
2328                 if (ret < 0 || ret >= end - pos)
2329                         return pos - buf;
2330                 pos += ret;
2331                 first = 0;
2332         }
2333
2334         return pos - buf;
2335 }
2336
2337
2338 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
2339                                               struct wpa_driver_capa *capa,
2340                                               char *buf, size_t buflen)
2341 {
2342         int ret, first = 1;
2343         char *pos, *end;
2344         size_t len;
2345
2346         pos = buf;
2347         end = pos + buflen;
2348
2349         if (res < 0) {
2350                 if (strict)
2351                         return 0;
2352                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
2353                 if (len >= buflen)
2354                         return -1;
2355                 return len;
2356         }
2357
2358         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
2359                 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
2360                 if (ret < 0 || ret >= end - pos)
2361                         return pos - buf;
2362                 pos += ret;
2363                 first = 0;
2364         }
2365
2366         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
2367                 ret = os_snprintf(pos, end - pos, "%sSHARED",
2368                                   first ? "" : " ");
2369                 if (ret < 0 || ret >= end - pos)
2370                         return pos - buf;
2371                 pos += ret;
2372                 first = 0;
2373         }
2374
2375         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
2376                 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
2377                 if (ret < 0 || ret >= end - pos)
2378                         return pos - buf;
2379                 pos += ret;
2380                 first = 0;
2381         }
2382
2383         return pos - buf;
2384 }
2385
2386
2387 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
2388                                               char *buf, size_t buflen)
2389 {
2390         struct hostapd_channel_data *chnl;
2391         int ret, i, j;
2392         char *pos, *end, *hmode;
2393
2394         pos = buf;
2395         end = pos + buflen;
2396
2397         for (j = 0; j < wpa_s->hw.num_modes; j++) {
2398                 switch (wpa_s->hw.modes[j].mode) {
2399                 case HOSTAPD_MODE_IEEE80211B:
2400                         hmode = "B";
2401                         break;
2402                 case HOSTAPD_MODE_IEEE80211G:
2403                         hmode = "G";
2404                         break;
2405                 case HOSTAPD_MODE_IEEE80211A:
2406                         hmode = "A";
2407                         break;
2408                 default:
2409                         return pos - buf;
2410                 }
2411                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
2412                 if (ret < 0 || ret >= end - pos)
2413                         return pos - buf;
2414                 pos += ret;
2415                 chnl = wpa_s->hw.modes[j].channels;
2416                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
2417                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
2418                         if (ret < 0 || ret >= end - pos)
2419                                 return pos - buf;
2420                         pos += ret;
2421                 }
2422                 ret = os_snprintf(pos, end - pos, "\n");
2423                 if (ret < 0 || ret >= end - pos)
2424                         return pos - buf;
2425                 pos += ret;
2426         }
2427
2428         return pos - buf;
2429 }
2430
2431
2432 static int wpa_supplicant_ctrl_iface_get_capability(
2433         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
2434         size_t buflen)
2435 {
2436         struct wpa_driver_capa capa;
2437         int res;
2438         char *strict;
2439         char field[30];
2440         size_t len;
2441
2442         /* Determine whether or not strict checking was requested */
2443         len = os_strlcpy(field, _field, sizeof(field));
2444         if (len >= sizeof(field))
2445                 return -1;
2446         strict = os_strchr(field, ' ');
2447         if (strict != NULL) {
2448                 *strict++ = '\0';
2449                 if (os_strcmp(strict, "strict") != 0)
2450                         return -1;
2451         }
2452
2453         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
2454                 field, strict ? strict : "");
2455
2456         if (os_strcmp(field, "eap") == 0) {
2457                 return eap_get_names(buf, buflen);
2458         }
2459
2460         res = wpa_drv_get_capa(wpa_s, &capa);
2461
2462         if (os_strcmp(field, "pairwise") == 0)
2463                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
2464                                                           buf, buflen);
2465
2466         if (os_strcmp(field, "group") == 0)
2467                 return ctrl_iface_get_capability_group(res, strict, &capa,
2468                                                        buf, buflen);
2469
2470         if (os_strcmp(field, "key_mgmt") == 0)
2471                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
2472                                                           buf, buflen);
2473
2474         if (os_strcmp(field, "proto") == 0)
2475                 return ctrl_iface_get_capability_proto(res, strict, &capa,
2476                                                        buf, buflen);
2477
2478         if (os_strcmp(field, "auth_alg") == 0)
2479                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
2480                                                           buf, buflen);
2481
2482         if (os_strcmp(field, "channels") == 0)
2483                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
2484
2485         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
2486                    field);
2487
2488         return -1;
2489 }
2490
2491
2492 #ifdef CONFIG_INTERWORKING
2493 static char * anqp_add_hex(char *pos, char *end, const char *title,
2494                            struct wpabuf *data)
2495 {
2496         char *start = pos;
2497         size_t i;
2498         int ret;
2499         const u8 *d;
2500
2501         if (data == NULL)
2502                 return start;
2503
2504         ret = os_snprintf(pos, end - pos, "%s=", title);
2505         if (ret < 0 || ret >= end - pos)
2506                 return start;
2507         pos += ret;
2508
2509         d = wpabuf_head_u8(data);
2510         for (i = 0; i < wpabuf_len(data); i++) {
2511                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
2512                 if (ret < 0 || ret >= end - pos)
2513                         return start;
2514                 pos += ret;
2515         }
2516
2517         ret = os_snprintf(pos, end - pos, "\n");
2518         if (ret < 0 || ret >= end - pos)
2519                 return start;
2520         pos += ret;
2521
2522         return pos;
2523 }
2524 #endif /* CONFIG_INTERWORKING */
2525
2526
2527 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
2528                           unsigned long mask, char *buf, size_t buflen)
2529 {
2530         size_t i;
2531         int ret;
2532         char *pos, *end;
2533         const u8 *ie, *ie2;
2534
2535         pos = buf;
2536         end = buf + buflen;
2537
2538         if (mask & WPA_BSS_MASK_ID) {
2539                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
2540                 if (ret < 0 || ret >= end - pos)
2541                         return 0;
2542                 pos += ret;
2543         }
2544
2545         if (mask & WPA_BSS_MASK_BSSID) {
2546                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2547                                   MAC2STR(bss->bssid));
2548                 if (ret < 0 || ret >= end - pos)
2549                         return 0;
2550                 pos += ret;
2551         }
2552
2553         if (mask & WPA_BSS_MASK_FREQ) {
2554                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
2555                 if (ret < 0 || ret >= end - pos)
2556                         return 0;
2557                 pos += ret;
2558         }
2559
2560         if (mask & WPA_BSS_MASK_BEACON_INT) {
2561                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
2562                                   bss->beacon_int);
2563                 if (ret < 0 || ret >= end - pos)
2564                         return 0;
2565                 pos += ret;
2566         }
2567
2568         if (mask & WPA_BSS_MASK_CAPABILITIES) {
2569                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
2570                                   bss->caps);
2571                 if (ret < 0 || ret >= end - pos)
2572                         return 0;
2573                 pos += ret;
2574         }
2575
2576         if (mask & WPA_BSS_MASK_QUAL) {
2577                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
2578                 if (ret < 0 || ret >= end - pos)
2579                         return 0;
2580                 pos += ret;
2581         }
2582
2583         if (mask & WPA_BSS_MASK_NOISE) {
2584                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
2585                 if (ret < 0 || ret >= end - pos)
2586                         return 0;
2587                 pos += ret;
2588         }
2589
2590         if (mask & WPA_BSS_MASK_LEVEL) {
2591                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
2592                 if (ret < 0 || ret >= end - pos)
2593                         return 0;
2594                 pos += ret;
2595         }
2596
2597         if (mask & WPA_BSS_MASK_TSF) {
2598                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
2599                                   (unsigned long long) bss->tsf);
2600                 if (ret < 0 || ret >= end - pos)
2601                         return 0;
2602                 pos += ret;
2603         }
2604
2605         if (mask & WPA_BSS_MASK_AGE) {
2606                 struct os_time now;
2607
2608                 os_get_time(&now);
2609                 ret = os_snprintf(pos, end - pos, "age=%d\n",
2610                                   (int) (now.sec - bss->last_update.sec));
2611                 if (ret < 0 || ret >= end - pos)
2612                         return 0;
2613                 pos += ret;
2614         }
2615
2616         if (mask & WPA_BSS_MASK_IE) {
2617                 ret = os_snprintf(pos, end - pos, "ie=");
2618                 if (ret < 0 || ret >= end - pos)
2619                         return 0;
2620                 pos += ret;
2621
2622                 ie = (const u8 *) (bss + 1);
2623                 for (i = 0; i < bss->ie_len; i++) {
2624                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
2625                         if (ret < 0 || ret >= end - pos)
2626                                 return 0;
2627                         pos += ret;
2628                 }
2629
2630                 ret = os_snprintf(pos, end - pos, "\n");
2631                 if (ret < 0 || ret >= end - pos)
2632                         return 0;
2633                 pos += ret;
2634         }
2635
2636         if (mask & WPA_BSS_MASK_FLAGS) {
2637                 ret = os_snprintf(pos, end - pos, "flags=");
2638                 if (ret < 0 || ret >= end - pos)
2639                         return 0;
2640                 pos += ret;
2641
2642                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2643                 if (ie)
2644                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
2645                                                     2 + ie[1]);
2646                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2647                 if (ie2)
2648                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
2649                                                     2 + ie2[1]);
2650                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2651                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2652                         ret = os_snprintf(pos, end - pos, "[WEP]");
2653                         if (ret < 0 || ret >= end - pos)
2654                                 return 0;
2655                         pos += ret;
2656                 }
2657                 if (bss->caps & IEEE80211_CAP_IBSS) {
2658                         ret = os_snprintf(pos, end - pos, "[IBSS]");
2659                         if (ret < 0 || ret >= end - pos)
2660                                 return 0;
2661                         pos += ret;
2662                 }
2663                 if (bss->caps & IEEE80211_CAP_ESS) {
2664                         ret = os_snprintf(pos, end - pos, "[ESS]");
2665                         if (ret < 0 || ret >= end - pos)
2666                                 return 0;
2667                         pos += ret;
2668                 }
2669                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
2670                         ret = os_snprintf(pos, end - pos, "[P2P]");
2671                         if (ret < 0 || ret >= end - pos)
2672                                 return 0;
2673                         pos += ret;
2674                 }
2675 #ifdef CONFIG_HS20
2676                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
2677                         ret = os_snprintf(pos, end - pos, "[HS20]");
2678                         if (ret < 0 || ret >= end - pos)
2679                                 return -1;
2680                         pos += ret;
2681                 }
2682 #endif /* CONFIG_HS20 */
2683
2684                 ret = os_snprintf(pos, end - pos, "\n");
2685                 if (ret < 0 || ret >= end - pos)
2686                         return 0;
2687                 pos += ret;
2688         }
2689
2690         if (mask & WPA_BSS_MASK_SSID) {
2691                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
2692                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
2693                 if (ret < 0 || ret >= end - pos)
2694                         return 0;
2695                 pos += ret;
2696         }
2697
2698 #ifdef CONFIG_WPS
2699         if (mask & WPA_BSS_MASK_WPS_SCAN) {
2700                 ie = (const u8 *) (bss + 1);
2701                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
2702                 if (ret < 0 || ret >= end - pos)
2703                         return 0;
2704                 pos += ret;
2705         }
2706 #endif /* CONFIG_WPS */
2707
2708 #ifdef CONFIG_P2P
2709         if (mask & WPA_BSS_MASK_P2P_SCAN) {
2710                 ie = (const u8 *) (bss + 1);
2711                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
2712                 if (ret < 0 || ret >= end - pos)
2713                         return 0;
2714                 pos += ret;
2715         }
2716 #endif /* CONFIG_P2P */
2717
2718 #ifdef CONFIG_INTERWORKING
2719         if (mask & WPA_BSS_MASK_INTERNETW) {
2720                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
2721                                    bss->anqp_venue_name);
2722                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
2723                                    bss->anqp_network_auth_type);
2724                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
2725                                    bss->anqp_roaming_consortium);
2726                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
2727                                    bss->anqp_ip_addr_type_availability);
2728                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
2729                                    bss->anqp_nai_realm);
2730                 pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp);
2731                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
2732                                    bss->anqp_domain_name);
2733 #ifdef CONFIG_HS20
2734                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
2735                                    bss->hs20_operator_friendly_name);
2736                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
2737                                    bss->hs20_wan_metrics);
2738                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
2739                                    bss->hs20_connection_capability);
2740 #endif /* CONFIG_HS20 */
2741         }
2742 #endif /* CONFIG_INTERWORKING */
2743
2744         return pos - buf;
2745 }
2746
2747
2748 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
2749                                          const char *cmd, char *buf,
2750                                          size_t buflen)
2751 {
2752         u8 bssid[ETH_ALEN];
2753         size_t i;
2754         struct wpa_bss *bss;
2755         struct wpa_bss *bsslast = NULL;
2756         struct dl_list *next;
2757         int ret = 0;
2758         int len;
2759         char *ctmp;
2760         unsigned long mask = WPA_BSS_MASK_ALL;
2761
2762         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
2763                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
2764                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
2765                                             list_id);
2766                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
2767                                                list_id);
2768                 } else { /* N1-N2 */
2769                         unsigned int id1, id2;
2770
2771                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
2772                                 wpa_printf(MSG_INFO, "Wrong BSS range "
2773                                            "format");
2774                                 return 0;
2775                         }
2776
2777                         id1 = atoi(cmd + 6);
2778                         bss = wpa_bss_get_id(wpa_s, id1);
2779                         id2 = atoi(ctmp + 1);
2780                         if (id2 == 0)
2781                                 bsslast = dl_list_last(&wpa_s->bss_id,
2782                                                        struct wpa_bss,
2783                                                        list_id);
2784                         else {
2785                                 bsslast = wpa_bss_get_id(wpa_s, id2);
2786                                 if (bsslast == NULL && bss && id2 > id1) {
2787                                         struct wpa_bss *tmp = bss;
2788                                         for (;;) {
2789                                                 next = tmp->list_id.next;
2790                                                 if (next == &wpa_s->bss_id)
2791                                                         break;
2792                                                 tmp = dl_list_entry(
2793                                                         next, struct wpa_bss,
2794                                                         list_id);
2795                                                 if (tmp->id > id2)
2796                                                         break;
2797                                                 bsslast = tmp;
2798                                         }
2799                                 }
2800                         }
2801                 }
2802         } else if (os_strcmp(cmd, "FIRST") == 0)
2803                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
2804         else if (os_strncmp(cmd, "ID-", 3) == 0) {
2805                 i = atoi(cmd + 3);
2806                 bss = wpa_bss_get_id(wpa_s, i);
2807         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2808                 i = atoi(cmd + 5);
2809                 bss = wpa_bss_get_id(wpa_s, i);
2810                 if (bss) {
2811                         next = bss->list_id.next;
2812                         if (next == &wpa_s->bss_id)
2813                                 bss = NULL;
2814                         else
2815                                 bss = dl_list_entry(next, struct wpa_bss,
2816                                                     list_id);
2817                 }
2818 #ifdef CONFIG_P2P
2819         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
2820                 if (hwaddr_aton(cmd + 13, bssid) == 0)
2821                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
2822                 else
2823                         bss = NULL;
2824 #endif /* CONFIG_P2P */
2825         } else if (hwaddr_aton(cmd, bssid) == 0)
2826                 bss = wpa_bss_get_bssid(wpa_s, bssid);
2827         else {
2828                 struct wpa_bss *tmp;
2829                 i = atoi(cmd);
2830                 bss = NULL;
2831                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
2832                 {
2833                         if (i-- == 0) {
2834                                 bss = tmp;
2835                                 break;
2836                         }
2837                 }
2838         }
2839
2840         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
2841                 mask = strtoul(ctmp + 5, NULL, 0x10);
2842                 if (mask == 0)
2843                         mask = WPA_BSS_MASK_ALL;
2844         }
2845
2846         if (bss == NULL)
2847                 return 0;
2848
2849         if (bsslast == NULL)
2850                 bsslast = bss;
2851         do {
2852                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
2853                 ret += len;
2854                 buf += len;
2855                 buflen -= len;
2856                 if (bss == bsslast)
2857                         break;
2858                 next = bss->list_id.next;
2859                 if (next == &wpa_s->bss_id)
2860                         break;
2861                 bss = dl_list_entry(next, struct wpa_bss, list_id);
2862         } while (bss && len);
2863
2864         return ret;
2865 }
2866
2867
2868 static int wpa_supplicant_ctrl_iface_ap_scan(
2869         struct wpa_supplicant *wpa_s, char *cmd)
2870 {
2871         int ap_scan = atoi(cmd);
2872         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
2873 }
2874
2875
2876 static int wpa_supplicant_ctrl_iface_scan_interval(
2877         struct wpa_supplicant *wpa_s, char *cmd)
2878 {
2879         int scan_int = atoi(cmd);
2880         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
2881 }
2882
2883
2884 static int wpa_supplicant_ctrl_iface_bss_expire_age(
2885         struct wpa_supplicant *wpa_s, char *cmd)
2886 {
2887         int expire_age = atoi(cmd);
2888         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
2889 }
2890
2891
2892 static int wpa_supplicant_ctrl_iface_bss_expire_count(
2893         struct wpa_supplicant *wpa_s, char *cmd)
2894 {
2895         int expire_count = atoi(cmd);
2896         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
2897 }
2898
2899
2900 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
2901 {
2902         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
2903         /* MLME-DELETEKEYS.request */
2904         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
2905         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
2906         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
2907         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
2908 #ifdef CONFIG_IEEE80211W
2909         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
2910         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
2911 #endif /* CONFIG_IEEE80211W */
2912
2913         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
2914                         0);
2915         /* MLME-SETPROTECTION.request(None) */
2916         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
2917                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
2918                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2919         wpa_sm_drop_sa(wpa_s->wpa);
2920 }
2921
2922
2923 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
2924                                           char *addr)
2925 {
2926 #ifdef CONFIG_NO_SCAN_PROCESSING
2927         return -1;
2928 #else /* CONFIG_NO_SCAN_PROCESSING */
2929         u8 bssid[ETH_ALEN];
2930         struct wpa_bss *bss;
2931         struct wpa_ssid *ssid = wpa_s->current_ssid;
2932
2933         if (hwaddr_aton(addr, bssid)) {
2934                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
2935                            "address '%s'", addr);
2936                 return -1;
2937         }
2938
2939         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
2940
2941         bss = wpa_bss_get_bssid(wpa_s, bssid);
2942         if (!bss) {
2943                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
2944                            "from BSS table");
2945                 return -1;
2946         }
2947
2948         /*
2949          * TODO: Find best network configuration block from configuration to
2950          * allow roaming to other networks
2951          */
2952
2953         if (!ssid) {
2954                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
2955                            "configuration known for the target AP");
2956                 return -1;
2957         }
2958
2959         wpa_s->reassociate = 1;
2960         wpa_supplicant_connect(wpa_s, bss, ssid);
2961
2962         return 0;
2963 #endif /* CONFIG_NO_SCAN_PROCESSING */
2964 }
2965
2966
2967 #ifdef CONFIG_P2P
2968 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
2969 {
2970         unsigned int timeout = atoi(cmd);
2971         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
2972         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
2973         char *pos;
2974
2975         if (os_strstr(cmd, "type=social"))
2976                 type = P2P_FIND_ONLY_SOCIAL;
2977         else if (os_strstr(cmd, "type=progressive"))
2978                 type = P2P_FIND_PROGRESSIVE;
2979
2980         pos = os_strstr(cmd, "dev_id=");
2981         if (pos) {
2982                 pos += 7;
2983                 if (hwaddr_aton(pos, dev_id))
2984                         return -1;
2985                 _dev_id = dev_id;
2986         }
2987
2988         return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id);
2989 }
2990
2991
2992 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
2993                             char *buf, size_t buflen)
2994 {
2995         u8 addr[ETH_ALEN];
2996         char *pos, *pos2;
2997         char *pin = NULL;
2998         enum p2p_wps_method wps_method;
2999         int new_pin;
3000         int ret;
3001         int persistent_group, persistent_id = -1;
3002         int join;
3003         int auth;
3004         int automatic;
3005         int go_intent = -1;
3006         int freq = 0;
3007         int pd;
3008
3009         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
3010          * [persistent|persistent=<network id>]
3011          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] */
3012
3013         if (hwaddr_aton(cmd, addr))
3014                 return -1;
3015
3016         pos = cmd + 17;
3017         if (*pos != ' ')
3018                 return -1;
3019         pos++;
3020
3021         persistent_group = os_strstr(pos, " persistent") != NULL;
3022         pos2 = os_strstr(pos, " persistent=");
3023         if (pos2) {
3024                 struct wpa_ssid *ssid;
3025                 persistent_id = atoi(pos2 + 12);
3026                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3027                 if (ssid == NULL || ssid->disabled != 2 ||
3028                     ssid->mode != WPAS_MODE_P2P_GO) {
3029                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3030                                    "SSID id=%d for persistent P2P group (GO)",
3031                                    persistent_id);
3032                         return -1;
3033                 }
3034         }
3035         join = os_strstr(pos, " join") != NULL;
3036         auth = os_strstr(pos, " auth") != NULL;
3037         automatic = os_strstr(pos, " auto") != NULL;
3038         pd = os_strstr(pos, " provdisc") != NULL;
3039
3040         pos2 = os_strstr(pos, " go_intent=");
3041         if (pos2) {
3042                 pos2 += 11;
3043                 go_intent = atoi(pos2);
3044                 if (go_intent < 0 || go_intent > 15)
3045                         return -1;
3046         }
3047
3048         pos2 = os_strstr(pos, " freq=");
3049         if (pos2) {
3050                 pos2 += 6;
3051                 freq = atoi(pos2);
3052                 if (freq <= 0)
3053                         return -1;
3054         }
3055
3056         if (os_strncmp(pos, "pin", 3) == 0) {
3057                 /* Request random PIN (to be displayed) and enable the PIN */
3058                 wps_method = WPS_PIN_DISPLAY;
3059         } else if (os_strncmp(pos, "pbc", 3) == 0) {
3060                 wps_method = WPS_PBC;
3061         } else {
3062                 pin = pos;
3063                 pos = os_strchr(pin, ' ');
3064                 wps_method = WPS_PIN_KEYPAD;
3065                 if (pos) {
3066                         *pos++ = '\0';
3067                         if (os_strncmp(pos, "display", 7) == 0)
3068                                 wps_method = WPS_PIN_DISPLAY;
3069                 }
3070                 if (!wps_pin_str_valid(pin)) {
3071                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
3072                         return 17;
3073                 }
3074         }
3075
3076         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
3077                                    persistent_group, automatic, join,
3078                                    auth, go_intent, freq, persistent_id, pd);
3079         if (new_pin == -2) {
3080                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
3081                 return 25;
3082         }
3083         if (new_pin == -3) {
3084                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
3085                 return 25;
3086         }
3087         if (new_pin < 0)
3088                 return -1;
3089         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
3090                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
3091                 if (ret < 0 || (size_t) ret >= buflen)
3092                         return -1;
3093                 return ret;
3094         }
3095
3096         os_memcpy(buf, "OK\n", 3);
3097         return 3;
3098 }
3099
3100
3101 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
3102 {
3103         unsigned int timeout = atoi(cmd);
3104         return wpas_p2p_listen(wpa_s, timeout);
3105 }
3106
3107
3108 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
3109 {
3110         u8 addr[ETH_ALEN];
3111         char *pos;
3112         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
3113
3114         /* <addr> <config method> [join|auto] */
3115
3116         if (hwaddr_aton(cmd, addr))
3117                 return -1;
3118
3119         pos = cmd + 17;
3120         if (*pos != ' ')
3121                 return -1;
3122         pos++;
3123
3124         if (os_strstr(pos, " join") != NULL)
3125                 use = WPAS_P2P_PD_FOR_JOIN;
3126         else if (os_strstr(pos, " auto") != NULL)
3127                 use = WPAS_P2P_PD_AUTO;
3128
3129         return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
3130 }
3131
3132
3133 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
3134                               size_t buflen)
3135 {
3136         struct wpa_ssid *ssid = wpa_s->current_ssid;
3137
3138         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
3139             ssid->passphrase == NULL)
3140                 return -1;
3141
3142         os_strlcpy(buf, ssid->passphrase, buflen);
3143         return os_strlen(buf);
3144 }
3145
3146
3147 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
3148                                   char *buf, size_t buflen)
3149 {
3150         u64 ref;
3151         int res;
3152         u8 dst_buf[ETH_ALEN], *dst;
3153         struct wpabuf *tlvs;
3154         char *pos;
3155         size_t len;
3156
3157         if (hwaddr_aton(cmd, dst_buf))
3158                 return -1;
3159         dst = dst_buf;
3160         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
3161             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
3162                 dst = NULL;
3163         pos = cmd + 17;
3164         if (*pos != ' ')
3165                 return -1;
3166         pos++;
3167
3168         if (os_strncmp(pos, "upnp ", 5) == 0) {
3169                 u8 version;
3170                 pos += 5;
3171                 if (hexstr2bin(pos, &version, 1) < 0)
3172                         return -1;
3173                 pos += 2;
3174                 if (*pos != ' ')
3175                         return -1;
3176                 pos++;
3177                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
3178         } else {
3179                 len = os_strlen(pos);
3180                 if (len & 1)
3181                         return -1;
3182                 len /= 2;
3183                 tlvs = wpabuf_alloc(len);
3184                 if (tlvs == NULL)
3185                         return -1;
3186                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
3187                         wpabuf_free(tlvs);
3188                         return -1;
3189                 }
3190
3191                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
3192                 wpabuf_free(tlvs);
3193         }
3194         if (ref == 0)
3195                 return -1;
3196         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
3197         if (res < 0 || (unsigned) res >= buflen)
3198                 return -1;
3199         return res;
3200 }
3201
3202
3203 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
3204                                          char *cmd)
3205 {
3206         long long unsigned val;
3207         u64 req;
3208         if (sscanf(cmd, "%llx", &val) != 1)
3209                 return -1;
3210         req = val;
3211         return wpas_p2p_sd_cancel_request(wpa_s, req);
3212 }
3213
3214
3215 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
3216 {
3217         int freq;
3218         u8 dst[ETH_ALEN];
3219         u8 dialog_token;
3220         struct wpabuf *resp_tlvs;
3221         char *pos, *pos2;
3222         size_t len;
3223
3224         pos = os_strchr(cmd, ' ');
3225         if (pos == NULL)
3226                 return -1;
3227         *pos++ = '\0';
3228         freq = atoi(cmd);
3229         if (freq == 0)
3230                 return -1;
3231
3232         if (hwaddr_aton(pos, dst))
3233                 return -1;
3234         pos += 17;
3235         if (*pos != ' ')
3236                 return -1;
3237         pos++;
3238
3239         pos2 = os_strchr(pos, ' ');
3240         if (pos2 == NULL)
3241                 return -1;
3242         *pos2++ = '\0';
3243         dialog_token = atoi(pos);
3244
3245         len = os_strlen(pos2);
3246         if (len & 1)
3247                 return -1;
3248         len /= 2;
3249         resp_tlvs = wpabuf_alloc(len);
3250         if (resp_tlvs == NULL)
3251                 return -1;
3252         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
3253                 wpabuf_free(resp_tlvs);
3254                 return -1;
3255         }
3256
3257         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
3258         wpabuf_free(resp_tlvs);
3259         return 0;
3260 }
3261
3262
3263 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
3264                                        char *cmd)
3265 {
3266         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
3267                 return -1;
3268         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
3269         return 0;
3270 }
3271
3272
3273 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
3274                                         char *cmd)
3275 {
3276         char *pos;
3277         size_t len;
3278         struct wpabuf *query, *resp;
3279
3280         pos = os_strchr(cmd, ' ');
3281         if (pos == NULL)
3282                 return -1;
3283         *pos++ = '\0';
3284
3285         len = os_strlen(cmd);
3286         if (len & 1)
3287                 return -1;
3288         len /= 2;
3289         query = wpabuf_alloc(len);
3290         if (query == NULL)
3291                 return -1;
3292         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3293                 wpabuf_free(query);
3294                 return -1;
3295         }
3296
3297         len = os_strlen(pos);
3298         if (len & 1) {
3299                 wpabuf_free(query);
3300                 return -1;
3301         }
3302         len /= 2;
3303         resp = wpabuf_alloc(len);
3304         if (resp == NULL) {
3305                 wpabuf_free(query);
3306                 return -1;
3307         }
3308         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
3309                 wpabuf_free(query);
3310                 wpabuf_free(resp);
3311                 return -1;
3312         }
3313
3314         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
3315                 wpabuf_free(query);
3316                 wpabuf_free(resp);
3317                 return -1;
3318         }
3319         return 0;
3320 }
3321
3322
3323 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
3324 {
3325         char *pos;
3326         u8 version;
3327
3328         pos = os_strchr(cmd, ' ');
3329         if (pos == NULL)
3330                 return -1;
3331         *pos++ = '\0';
3332
3333         if (hexstr2bin(cmd, &version, 1) < 0)
3334                 return -1;
3335
3336         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
3337 }
3338
3339
3340 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
3341 {
3342         char *pos;
3343
3344         pos = os_strchr(cmd, ' ');
3345         if (pos == NULL)
3346                 return -1;
3347         *pos++ = '\0';
3348
3349         if (os_strcmp(cmd, "bonjour") == 0)
3350                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
3351         if (os_strcmp(cmd, "upnp") == 0)
3352                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
3353         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
3354         return -1;
3355 }
3356
3357
3358 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
3359                                         char *cmd)
3360 {
3361         size_t len;
3362         struct wpabuf *query;
3363         int ret;
3364
3365         len = os_strlen(cmd);
3366         if (len & 1)
3367                 return -1;
3368         len /= 2;
3369         query = wpabuf_alloc(len);
3370         if (query == NULL)
3371                 return -1;
3372         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3373                 wpabuf_free(query);
3374                 return -1;
3375         }
3376
3377         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
3378         wpabuf_free(query);
3379         return ret;
3380 }
3381
3382
3383 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
3384 {
3385         char *pos;
3386         u8 version;
3387
3388         pos = os_strchr(cmd, ' ');
3389         if (pos == NULL)
3390                 return -1;
3391         *pos++ = '\0';
3392
3393         if (hexstr2bin(cmd, &version, 1) < 0)
3394                 return -1;
3395
3396         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
3397 }
3398
3399
3400 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
3401 {
3402         char *pos;
3403
3404         pos = os_strchr(cmd, ' ');
3405         if (pos == NULL)
3406                 return -1;
3407         *pos++ = '\0';
3408
3409         if (os_strcmp(cmd, "bonjour") == 0)
3410                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
3411         if (os_strcmp(cmd, "upnp") == 0)
3412                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
3413         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
3414         return -1;
3415 }
3416
3417
3418 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
3419 {
3420         u8 addr[ETH_ALEN];
3421
3422         /* <addr> */
3423
3424         if (hwaddr_aton(cmd, addr))
3425                 return -1;
3426
3427         return wpas_p2p_reject(wpa_s, addr);
3428 }
3429
3430
3431 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
3432 {
3433         char *pos;
3434         int id;
3435         struct wpa_ssid *ssid;
3436         u8 peer[ETH_ALEN];
3437
3438         id = atoi(cmd);
3439         pos = os_strstr(cmd, " peer=");
3440         if (pos) {
3441                 pos += 6;
3442                 if (hwaddr_aton(pos, peer))
3443                         return -1;
3444         }
3445         ssid = wpa_config_get_network(wpa_s->conf, id);
3446         if (ssid == NULL || ssid->disabled != 2) {
3447                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
3448                            "for persistent P2P group",
3449                            id);
3450                 return -1;
3451         }
3452
3453         return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
3454 }
3455
3456
3457 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
3458 {
3459         char *pos;
3460         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
3461
3462         pos = os_strstr(cmd, " peer=");
3463         if (!pos)
3464                 return -1;
3465
3466         *pos = '\0';
3467         pos += 6;
3468         if (hwaddr_aton(pos, peer)) {
3469                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
3470                 return -1;
3471         }
3472
3473         pos = os_strstr(pos, " go_dev_addr=");
3474         if (pos) {
3475                 pos += 13;
3476                 if (hwaddr_aton(pos, go_dev_addr)) {
3477                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
3478                                    pos);
3479                         return -1;
3480                 }
3481                 go_dev = go_dev_addr;
3482         }
3483
3484         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
3485 }
3486
3487
3488 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
3489 {
3490         if (os_strncmp(cmd, "persistent=", 11) == 0)
3491                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
3492         if (os_strncmp(cmd, "group=", 6) == 0)
3493                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
3494
3495         return -1;
3496 }
3497
3498
3499 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
3500                                          char *cmd, int freq)
3501 {
3502         int id;
3503         struct wpa_ssid *ssid;
3504
3505         id = atoi(cmd);
3506         ssid = wpa_config_get_network(wpa_s->conf, id);
3507         if (ssid == NULL || ssid->disabled != 2) {
3508                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
3509                            "for persistent P2P group",
3510                            id);
3511                 return -1;
3512         }
3513
3514         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
3515 }
3516
3517
3518 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
3519 {
3520         int freq = 0;
3521         char *pos;
3522
3523         pos = os_strstr(cmd, "freq=");
3524         if (pos)
3525                 freq = atoi(pos + 5);
3526
3527         if (os_strncmp(cmd, "persistent=", 11) == 0)
3528                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
3529         if (os_strcmp(cmd, "persistent") == 0 ||
3530             os_strncmp(cmd, "persistent ", 11) == 0)
3531                 return wpas_p2p_group_add(wpa_s, 1, freq);
3532         if (os_strncmp(cmd, "freq=", 5) == 0)
3533                 return wpas_p2p_group_add(wpa_s, 0, freq);
3534
3535         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
3536                    cmd);
3537         return -1;
3538 }
3539
3540
3541 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
3542                          char *buf, size_t buflen)
3543 {
3544         u8 addr[ETH_ALEN], *addr_ptr;
3545         int next, res;
3546         const struct p2p_peer_info *info;
3547         char *pos, *end;
3548         char devtype[WPS_DEV_TYPE_BUFSIZE];
3549         struct wpa_ssid *ssid;
3550
3551         if (!wpa_s->global->p2p)
3552                 return -1;
3553
3554         if (os_strcmp(cmd, "FIRST") == 0) {
3555                 addr_ptr = NULL;
3556                 next = 0;
3557         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3558                 if (hwaddr_aton(cmd + 5, addr) < 0)
3559                         return -1;
3560                 addr_ptr = addr;
3561                 next = 1;
3562         } else {
3563                 if (hwaddr_aton(cmd, addr) < 0)
3564                         return -1;
3565                 addr_ptr = addr;
3566                 next = 0;
3567         }
3568
3569         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
3570         if (info == NULL)
3571                 return -1;
3572
3573         pos = buf;
3574         end = buf + buflen;
3575
3576         res = os_snprintf(pos, end - pos, MACSTR "\n"
3577                           "pri_dev_type=%s\n"
3578                           "device_name=%s\n"
3579                           "manufacturer=%s\n"
3580                           "model_name=%s\n"
3581                           "model_number=%s\n"
3582                           "serial_number=%s\n"
3583                           "config_methods=0x%x\n"
3584                           "dev_capab=0x%x\n"
3585                           "group_capab=0x%x\n"
3586                           "level=%d\n",
3587                           MAC2STR(info->p2p_device_addr),
3588                           wps_dev_type_bin2str(info->pri_dev_type,
3589                                                devtype, sizeof(devtype)),
3590                           info->device_name,
3591                           info->manufacturer,
3592                           info->model_name,
3593                           info->model_number,
3594                           info->serial_number,
3595                           info->config_methods,
3596                           info->dev_capab,
3597                           info->group_capab,
3598                           info->level);
3599         if (res < 0 || res >= end - pos)
3600                 return pos - buf;
3601         pos += res;
3602
3603         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
3604         if (ssid) {
3605                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
3606                 if (res < 0 || res >= end - pos)
3607                         return pos - buf;
3608                 pos += res;
3609         }
3610
3611         res = p2p_get_peer_info_txt(info, pos, end - pos);
3612         if (res < 0)
3613                 return pos - buf;
3614         pos += res;
3615
3616         return pos - buf;
3617 }
3618
3619
3620 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
3621                                   const char *param)
3622 {
3623         struct wpa_freq_range *freq = NULL, *n;
3624         unsigned int count = 0, i;
3625         const char *pos, *pos2, *pos3;
3626
3627         if (wpa_s->global->p2p == NULL)
3628                 return -1;
3629
3630         /*
3631          * param includes comma separated frequency range.
3632          * For example: 2412-2432,2462,5000-6000
3633          */
3634         pos = param;
3635         while (pos && pos[0]) {
3636                 n = os_realloc(freq,
3637                                (count + 1) * sizeof(struct wpa_freq_range));
3638                 if (n == NULL) {
3639                         os_free(freq);
3640                         return -1;
3641                 }
3642                 freq = n;
3643                 freq[count].min = atoi(pos);
3644                 pos2 = os_strchr(pos, '-');
3645                 pos3 = os_strchr(pos, ',');
3646                 if (pos2 && (!pos3 || pos2 < pos3)) {
3647                         pos2++;
3648                         freq[count].max = atoi(pos2);
3649                 } else
3650                         freq[count].max = freq[count].min;
3651                 pos = pos3;
3652                 if (pos)
3653                         pos++;
3654                 count++;
3655         }
3656
3657         for (i = 0; i < count; i++) {
3658                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
3659                            freq[i].min, freq[i].max);
3660         }
3661
3662         os_free(wpa_s->global->p2p_disallow_freq);
3663         wpa_s->global->p2p_disallow_freq = freq;
3664         wpa_s->global->num_p2p_disallow_freq = count;
3665         wpas_p2p_update_channel_list(wpa_s);
3666         return 0;
3667 }
3668
3669
3670 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
3671 {
3672         char *param;
3673
3674         if (wpa_s->global->p2p == NULL)
3675                 return -1;
3676
3677         param = os_strchr(cmd, ' ');
3678         if (param == NULL)
3679                 return -1;
3680         *param++ = '\0';
3681
3682         if (os_strcmp(cmd, "discoverability") == 0) {
3683                 p2p_set_client_discoverability(wpa_s->global->p2p,
3684                                                atoi(param));
3685                 return 0;
3686         }
3687
3688         if (os_strcmp(cmd, "managed") == 0) {
3689                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
3690                 return 0;
3691         }
3692
3693         if (os_strcmp(cmd, "listen_channel") == 0) {
3694                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
3695                                               atoi(param));
3696         }
3697
3698         if (os_strcmp(cmd, "ssid_postfix") == 0) {
3699                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
3700                                             os_strlen(param));
3701         }
3702
3703         if (os_strcmp(cmd, "noa") == 0) {
3704                 char *pos;
3705                 int count, start, duration;
3706                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
3707                 count = atoi(param);
3708                 pos = os_strchr(param, ',');
3709                 if (pos == NULL)
3710                         return -1;
3711                 pos++;
3712                 start = atoi(pos);
3713                 pos = os_strchr(pos, ',');
3714                 if (pos == NULL)
3715                         return -1;
3716                 pos++;
3717                 duration = atoi(pos);
3718                 if (count < 0 || count > 255 || start < 0 || duration < 0)
3719                         return -1;
3720                 if (count == 0 && duration > 0)
3721                         return -1;
3722                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
3723                            "start=%d duration=%d", count, start, duration);
3724                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
3725         }
3726
3727         if (os_strcmp(cmd, "ps") == 0)
3728                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
3729
3730         if (os_strcmp(cmd, "oppps") == 0)
3731                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
3732
3733         if (os_strcmp(cmd, "ctwindow") == 0)
3734                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
3735
3736         if (os_strcmp(cmd, "disabled") == 0) {
3737                 wpa_s->global->p2p_disabled = atoi(param);
3738                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
3739                            wpa_s->global->p2p_disabled ?
3740                            "disabled" : "enabled");
3741                 if (wpa_s->global->p2p_disabled) {
3742                         wpas_p2p_stop_find(wpa_s);
3743                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
3744                         p2p_flush(wpa_s->global->p2p);
3745                 }
3746                 return 0;
3747         }
3748
3749         if (os_strcmp(cmd, "conc_pref") == 0) {
3750                 if (os_strcmp(param, "sta") == 0)
3751                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
3752                 else if (os_strcmp(param, "p2p") == 0)
3753                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
3754                 else {
3755                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
3756                         return -1;
3757                 }
3758                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
3759                            "%s", param);
3760                 return 0;
3761         }
3762
3763         if (os_strcmp(cmd, "force_long_sd") == 0) {
3764                 wpa_s->force_long_sd = atoi(param);
3765                 return 0;
3766         }
3767
3768         if (os_strcmp(cmd, "peer_filter") == 0) {
3769                 u8 addr[ETH_ALEN];
3770                 if (hwaddr_aton(param, addr))
3771                         return -1;
3772                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
3773                 return 0;
3774         }
3775
3776         if (os_strcmp(cmd, "cross_connect") == 0)
3777                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
3778
3779         if (os_strcmp(cmd, "go_apsd") == 0) {
3780                 if (os_strcmp(param, "disable") == 0)
3781                         wpa_s->set_ap_uapsd = 0;
3782                 else {
3783                         wpa_s->set_ap_uapsd = 1;
3784                         wpa_s->ap_uapsd = atoi(param);
3785                 }
3786                 return 0;
3787         }
3788
3789         if (os_strcmp(cmd, "client_apsd") == 0) {
3790                 if (os_strcmp(param, "disable") == 0)
3791                         wpa_s->set_sta_uapsd = 0;
3792                 else {
3793                         int be, bk, vi, vo;
3794                         char *pos;
3795                         /* format: BE,BK,VI,VO;max SP Length */
3796                         be = atoi(param);
3797                         pos = os_strchr(param, ',');
3798                         if (pos == NULL)
3799                                 return -1;
3800                         pos++;
3801                         bk = atoi(pos);
3802                         pos = os_strchr(pos, ',');
3803                         if (pos == NULL)
3804                                 return -1;
3805                         pos++;
3806                         vi = atoi(pos);
3807                         pos = os_strchr(pos, ',');
3808                         if (pos == NULL)
3809                                 return -1;
3810                         pos++;
3811                         vo = atoi(pos);
3812                         /* ignore max SP Length for now */
3813
3814                         wpa_s->set_sta_uapsd = 1;
3815                         wpa_s->sta_uapsd = 0;
3816                         if (be)
3817                                 wpa_s->sta_uapsd |= BIT(0);
3818                         if (bk)
3819                                 wpa_s->sta_uapsd |= BIT(1);
3820                         if (vi)
3821                                 wpa_s->sta_uapsd |= BIT(2);
3822                         if (vo)
3823                                 wpa_s->sta_uapsd |= BIT(3);
3824                 }
3825                 return 0;
3826         }
3827
3828         if (os_strcmp(cmd, "disallow_freq") == 0)
3829                 return p2p_ctrl_disallow_freq(wpa_s, param);
3830
3831         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
3832                    cmd);
3833
3834         return -1;
3835 }
3836
3837
3838 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
3839 {
3840         char *pos, *pos2;
3841         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
3842
3843         if (cmd[0]) {
3844                 pos = os_strchr(cmd, ' ');
3845                 if (pos == NULL)
3846                         return -1;
3847                 *pos++ = '\0';
3848                 dur1 = atoi(cmd);
3849
3850                 pos2 = os_strchr(pos, ' ');
3851                 if (pos2)
3852                         *pos2++ = '\0';
3853                 int1 = atoi(pos);
3854         } else
3855                 pos2 = NULL;
3856
3857         if (pos2) {
3858                 pos = os_strchr(pos2, ' ');
3859                 if (pos == NULL)
3860                         return -1;
3861                 *pos++ = '\0';
3862                 dur2 = atoi(pos2);
3863                 int2 = atoi(pos);
3864         }
3865
3866         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
3867 }
3868
3869
3870 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
3871 {
3872         char *pos;
3873         unsigned int period = 0, interval = 0;
3874
3875         if (cmd[0]) {
3876                 pos = os_strchr(cmd, ' ');
3877                 if (pos == NULL)
3878                         return -1;
3879                 *pos++ = '\0';
3880                 period = atoi(cmd);
3881                 interval = atoi(pos);
3882         }
3883
3884         return wpas_p2p_ext_listen(wpa_s, period, interval);
3885 }
3886
3887 #endif /* CONFIG_P2P */
3888
3889
3890 #ifdef CONFIG_INTERWORKING
3891 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
3892 {
3893         u8 bssid[ETH_ALEN];
3894         struct wpa_bss *bss;
3895
3896         if (hwaddr_aton(dst, bssid)) {
3897                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
3898                 return -1;
3899         }
3900
3901         bss = wpa_bss_get_bssid(wpa_s, bssid);
3902         if (bss == NULL) {
3903                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
3904                            MAC2STR(bssid));
3905                 return -1;
3906         }
3907
3908         return interworking_connect(wpa_s, bss);
3909 }
3910
3911
3912 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
3913 {
3914         u8 dst_addr[ETH_ALEN];
3915         int used;
3916         char *pos;
3917 #define MAX_ANQP_INFO_ID 100
3918         u16 id[MAX_ANQP_INFO_ID];
3919         size_t num_id = 0;
3920
3921         used = hwaddr_aton2(dst, dst_addr);
3922         if (used < 0)
3923                 return -1;
3924         pos = dst + used;
3925         while (num_id < MAX_ANQP_INFO_ID) {
3926                 id[num_id] = atoi(pos);
3927                 if (id[num_id])
3928                         num_id++;
3929                 pos = os_strchr(pos + 1, ',');
3930                 if (pos == NULL)
3931                         break;
3932                 pos++;
3933         }
3934
3935         if (num_id == 0)
3936                 return -1;
3937
3938         return anqp_send_req(wpa_s, dst_addr, id, num_id);
3939 }
3940 #endif /* CONFIG_INTERWORKING */
3941
3942
3943 #ifdef CONFIG_HS20
3944
3945 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
3946 {
3947         u8 dst_addr[ETH_ALEN];
3948         int used;
3949         char *pos;
3950         u32 subtypes = 0;
3951
3952         used = hwaddr_aton2(dst, dst_addr);
3953         if (used < 0)
3954                 return -1;
3955         pos = dst + used;
3956         for (;;) {
3957                 int num = atoi(pos);
3958                 if (num <= 0 || num > 31)
3959                         return -1;
3960                 subtypes |= BIT(num);
3961                 pos = os_strchr(pos + 1, ',');
3962                 if (pos == NULL)
3963                         break;
3964                 pos++;
3965         }
3966
3967         if (subtypes == 0)
3968                 return -1;
3969
3970         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
3971 }
3972
3973
3974 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
3975                                     const u8 *addr, const char *realm)
3976 {
3977         u8 *buf;
3978         size_t rlen, len;
3979         int ret;
3980
3981         rlen = os_strlen(realm);
3982         len = 3 + rlen;
3983         buf = os_malloc(len);
3984         if (buf == NULL)
3985                 return -1;
3986         buf[0] = 1; /* NAI Home Realm Count */
3987         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
3988         buf[2] = rlen;
3989         os_memcpy(buf + 3, realm, rlen);
3990
3991         ret = hs20_anqp_send_req(wpa_s, addr,
3992                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
3993                                  buf, len);
3994
3995         os_free(buf);
3996
3997         return ret;
3998 }
3999
4000
4001 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
4002                                         char *dst)
4003 {
4004         struct wpa_cred *cred = wpa_s->conf->cred;
4005         u8 dst_addr[ETH_ALEN];
4006         int used;
4007         u8 *buf;
4008         size_t len;
4009         int ret;
4010
4011         used = hwaddr_aton2(dst, dst_addr);
4012         if (used < 0)
4013                 return -1;
4014
4015         while (dst[used] == ' ')
4016                 used++;
4017         if (os_strncmp(dst + used, "realm=", 6) == 0)
4018                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
4019                                                 dst + used + 6);
4020
4021         len = os_strlen(dst + used);
4022
4023         if (len == 0 && cred && cred->realm)
4024                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
4025
4026         if (len % 1)
4027                 return -1;
4028         len /= 2;
4029         buf = os_malloc(len);
4030         if (buf == NULL)
4031                 return -1;
4032         if (hexstr2bin(dst + used, buf, len) < 0) {
4033                 os_free(buf);
4034                 return -1;
4035         }
4036
4037         ret = hs20_anqp_send_req(wpa_s, dst_addr,
4038                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
4039                                  buf, len);
4040         os_free(buf);
4041
4042         return ret;
4043 }
4044
4045 #endif /* CONFIG_HS20 */
4046
4047
4048 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
4049         struct wpa_supplicant *wpa_s, char *cmd)
4050 {
4051         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
4052         return 0;
4053 }
4054
4055
4056 #ifdef CONFIG_AUTOSCAN
4057
4058 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
4059                                               char *cmd)
4060 {
4061         enum wpa_states state = wpa_s->wpa_state;
4062         char *new_params = NULL;
4063
4064         if (os_strlen(cmd) > 0) {
4065                 new_params = os_strdup(cmd);
4066                 if (new_params == NULL)
4067                         return -1;
4068         }
4069
4070         os_free(wpa_s->conf->autoscan);
4071         wpa_s->conf->autoscan = new_params;
4072
4073         if (wpa_s->conf->autoscan == NULL)
4074                 autoscan_deinit(wpa_s);
4075         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
4076                 autoscan_init(wpa_s, 1);
4077         else if (state == WPA_SCANNING)
4078                 wpa_supplicant_reinit_autoscan(wpa_s);
4079
4080         return 0;
4081 }
4082
4083 #endif /* CONFIG_AUTOSCAN */
4084
4085
4086 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
4087                                       size_t buflen)
4088 {
4089         struct wpa_signal_info si;
4090         int ret;
4091
4092         ret = wpa_drv_signal_poll(wpa_s, &si);
4093         if (ret)
4094                 return -1;
4095
4096         ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
4097                           "NOISE=%d\nFREQUENCY=%u\n",
4098                           si.current_signal, si.current_txrate / 1000,
4099                           si.current_noise, si.frequency);
4100         if (ret < 0 || (unsigned int) ret > buflen)
4101                 return -1;
4102         return ret;
4103 }
4104
4105 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
4106                                       size_t buflen)
4107 {
4108         struct hostap_sta_driver_data sta;
4109         int ret;
4110
4111         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
4112         if (ret)
4113                 return -1;
4114
4115         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
4116                     sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
4117         if (ret < 0 || (unsigned int) ret > buflen)
4118                 return -1;
4119         return ret;
4120 }
4121
4122
4123 #ifdef ANDROID
4124 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
4125                                      char *buf, size_t buflen)
4126 {
4127         int ret;
4128
4129         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
4130         if (ret == 0)
4131                 ret = sprintf(buf, "%s\n", "OK");
4132         return ret;
4133 }
4134 #endif
4135
4136 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
4137                                          char *buf, size_t *resp_len)
4138 {
4139         char *reply;
4140         const int reply_size = 4096;
4141         int ctrl_rsp = 0;
4142         int reply_len;
4143
4144         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
4145             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
4146                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
4147                                       (const u8 *) buf, os_strlen(buf));
4148         } else {
4149                 int level = MSG_DEBUG;
4150                 if (os_strcmp(buf, "PING") == 0)
4151                         level = MSG_EXCESSIVE;
4152                 wpa_hexdump_ascii(level, "RX ctrl_iface",
4153                                   (const u8 *) buf, os_strlen(buf));
4154         }
4155
4156         reply = os_malloc(reply_size);
4157         if (reply == NULL) {
4158                 *resp_len = 1;
4159                 return NULL;
4160         }
4161
4162         os_memcpy(reply, "OK\n", 3);
4163         reply_len = 3;
4164
4165         if (os_strcmp(buf, "PING") == 0) {
4166                 os_memcpy(reply, "PONG\n", 5);
4167                 reply_len = 5;
4168         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
4169                 if (wpa_debug_reopen_file() < 0)
4170                         reply_len = -1;
4171         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
4172                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
4173         } else if (os_strcmp(buf, "MIB") == 0) {
4174                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
4175                 if (reply_len >= 0) {
4176                         int res;
4177                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
4178                                                reply_size - reply_len);
4179                         if (res < 0)
4180                                 reply_len = -1;
4181                         else
4182                                 reply_len += res;
4183                 }
4184         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
4185                 reply_len = wpa_supplicant_ctrl_iface_status(
4186                         wpa_s, buf + 6, reply, reply_size);
4187         } else if (os_strcmp(buf, "PMKSA") == 0) {
4188                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
4189                                                     reply_size);
4190         } else if (os_strncmp(buf, "SET ", 4) == 0) {
4191                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
4192                         reply_len = -1;
4193         } else if (os_strncmp(buf, "GET ", 4) == 0) {
4194                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
4195                                                           reply, reply_size);
4196         } else if (os_strcmp(buf, "LOGON") == 0) {
4197                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
4198         } else if (os_strcmp(buf, "LOGOFF") == 0) {
4199                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
4200         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
4201                 wpa_s->normal_scans = 0;
4202                 wpa_supplicant_reinit_autoscan(wpa_s);
4203                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
4204                         reply_len = -1;
4205                 else {
4206                         wpa_s->disconnected = 0;
4207                         wpa_s->reassociate = 1;
4208                         wpa_supplicant_req_scan(wpa_s, 0, 0);
4209                 }
4210         } else if (os_strcmp(buf, "RECONNECT") == 0) {
4211                 wpa_s->normal_scans = 0;
4212                 wpa_supplicant_reinit_autoscan(wpa_s);
4213                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
4214                         reply_len = -1;
4215                 else if (wpa_s->disconnected) {
4216                         wpa_s->disconnected = 0;
4217                         wpa_s->reassociate = 1;
4218                         wpa_supplicant_req_scan(wpa_s, 0, 0);
4219                 }
4220 #ifdef IEEE8021X_EAPOL
4221         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
4222                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
4223                         reply_len = -1;
4224 #endif /* IEEE8021X_EAPOL */
4225 #ifdef CONFIG_PEERKEY
4226         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
4227                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
4228                         reply_len = -1;
4229 #endif /* CONFIG_PEERKEY */
4230 #ifdef CONFIG_IEEE80211R
4231         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
4232                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
4233                         reply_len = -1;
4234 #endif /* CONFIG_IEEE80211R */
4235 #ifdef CONFIG_WPS
4236         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
4237                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
4238                 if (res == -2) {
4239                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
4240                         reply_len = 17;
4241                 } else if (res)
4242                         reply_len = -1;
4243         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
4244                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
4245                 if (res == -2) {
4246                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
4247                         reply_len = 17;
4248                 } else if (res)
4249                         reply_len = -1;
4250         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
4251                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
4252                                                               reply,
4253                                                               reply_size);
4254         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
4255                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
4256                         wpa_s, buf + 14, reply, reply_size);
4257         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
4258                 if (wpas_wps_cancel(wpa_s))
4259                         reply_len = -1;
4260 #ifdef CONFIG_WPS_OOB
4261         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
4262                 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
4263                         reply_len = -1;
4264 #endif /* CONFIG_WPS_OOB */
4265 #ifdef CONFIG_WPS_NFC
4266         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
4267                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
4268                         reply_len = -1;
4269         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
4270                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
4271                         reply_len = -1;
4272         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
4273                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
4274                         wpa_s, buf + 14, reply, reply_size);
4275         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
4276                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
4277                                                                buf + 17))
4278                         reply_len = -1;
4279 #endif /* CONFIG_WPS_NFC */
4280         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
4281                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
4282                         reply_len = -1;
4283 #ifdef CONFIG_AP
4284         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
4285                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
4286                         wpa_s, buf + 11, reply, reply_size);
4287 #endif /* CONFIG_AP */
4288 #ifdef CONFIG_WPS_ER
4289         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
4290                 if (wpas_wps_er_start(wpa_s, NULL))
4291                         reply_len = -1;
4292         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
4293                 if (wpas_wps_er_start(wpa_s, buf + 13))
4294                         reply_len = -1;
4295         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
4296                 if (wpas_wps_er_stop(wpa_s))
4297                         reply_len = -1;
4298         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
4299                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
4300                         reply_len = -1;
4301         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
4302                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
4303                 if (ret == -2) {
4304                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
4305                         reply_len = 17;
4306                 } else if (ret == -3) {
4307                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
4308                         reply_len = 18;
4309                 } else if (ret == -4) {
4310                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
4311                         reply_len = 20;
4312                 } else if (ret)
4313                         reply_len = -1;
4314         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
4315                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
4316                         reply_len = -1;
4317         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
4318                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
4319                                                                 buf + 18))
4320                         reply_len = -1;
4321         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
4322                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
4323                         reply_len = -1;
4324 #ifdef CONFIG_WPS_NFC
4325         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
4326                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
4327                         wpa_s, buf + 24, reply, reply_size);
4328 #endif /* CONFIG_WPS_NFC */
4329 #endif /* CONFIG_WPS_ER */
4330 #endif /* CONFIG_WPS */
4331 #ifdef CONFIG_IBSS_RSN
4332         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
4333                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
4334                         reply_len = -1;
4335 #endif /* CONFIG_IBSS_RSN */
4336 #ifdef CONFIG_P2P
4337         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
4338                 if (p2p_ctrl_find(wpa_s, buf + 9))
4339                         reply_len = -1;
4340         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
4341                 if (p2p_ctrl_find(wpa_s, ""))
4342                         reply_len = -1;
4343         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
4344                 wpas_p2p_stop_find(wpa_s);
4345         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
4346                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
4347                                              reply_size);
4348         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
4349                 if (p2p_ctrl_listen(wpa_s, buf + 11))
4350                         reply_len = -1;
4351         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
4352                 if (p2p_ctrl_listen(wpa_s, ""))
4353                         reply_len = -1;
4354         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
4355                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
4356                         reply_len = -1;
4357         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
4358                 if (wpas_p2p_group_add(wpa_s, 0, 0))
4359                         reply_len = -1;
4360         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
4361                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
4362                         reply_len = -1;
4363         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
4364                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
4365                         reply_len = -1;
4366         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
4367                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
4368         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
4369                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
4370                                                    reply_size);
4371         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
4372                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
4373                         reply_len = -1;
4374         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
4375                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
4376                         reply_len = -1;
4377         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
4378 #ifdef ANDROID_P2P
4379                 wpas_p2p_sd_service_update(wpa_s, SRV_UPDATE);
4380 #else
4381                 wpas_p2p_sd_service_update(wpa_s);
4382 #endif
4383         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
4384                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
4385                         reply_len = -1;
4386         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
4387                 wpas_p2p_service_flush(wpa_s);
4388         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
4389                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
4390                         reply_len = -1;
4391         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
4392                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
4393                         reply_len = -1;
4394         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
4395                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
4396                         reply_len = -1;
4397         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
4398                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
4399                         reply_len = -1;
4400         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
4401                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
4402                                               reply_size);
4403         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
4404                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
4405                         reply_len = -1;
4406         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
4407                 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4408                 wpa_s->force_long_sd = 0;
4409                 if (wpa_s->global->p2p)
4410                         p2p_flush(wpa_s->global->p2p);
4411         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
4412                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
4413                         reply_len = -1;
4414         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
4415                 if (wpas_p2p_cancel(wpa_s))
4416                         reply_len = -1;
4417         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
4418                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
4419                         reply_len = -1;
4420         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
4421                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
4422                         reply_len = -1;
4423         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
4424                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
4425                         reply_len = -1;
4426         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
4427                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
4428                         reply_len = -1;
4429 #endif /* CONFIG_P2P */
4430 #ifdef CONFIG_INTERWORKING
4431         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
4432                 if (interworking_fetch_anqp(wpa_s) < 0)
4433                         reply_len = -1;
4434         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
4435                 interworking_stop_fetch_anqp(wpa_s);
4436         } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
4437                 if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
4438                                         NULL) < 0)
4439                         reply_len = -1;
4440         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
4441                 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
4442                         reply_len = -1;
4443         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
4444                 if (get_anqp(wpa_s, buf + 9) < 0)
4445                         reply_len = -1;
4446 #endif /* CONFIG_INTERWORKING */
4447 #ifdef CONFIG_HS20
4448         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
4449                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
4450                         reply_len = -1;
4451         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
4452                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
4453                         reply_len = -1;
4454 #endif /* CONFIG_HS20 */
4455         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
4456         {
4457                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
4458                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
4459                         reply_len = -1;
4460                 else
4461                         ctrl_rsp = 1;
4462         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
4463                 if (wpa_supplicant_reload_configuration(wpa_s))
4464                         reply_len = -1;
4465         } else if (os_strcmp(buf, "TERMINATE") == 0) {
4466                 wpa_supplicant_terminate_proc(wpa_s->global);
4467         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
4468                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
4469                         reply_len = -1;
4470         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
4471                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
4472                         wpa_s, buf + 9, reply, reply_size);
4473         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
4474                 reply_len = wpa_supplicant_ctrl_iface_log_level(
4475                         wpa_s, buf + 9, reply, reply_size);
4476         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
4477                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
4478                         wpa_s, reply, reply_size);
4479         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
4480 #ifdef CONFIG_SME
4481                 wpa_s->sme.prev_bssid_set = 0;
4482 #endif /* CONFIG_SME */
4483                 wpa_s->reassociate = 0;
4484                 wpa_s->disconnected = 1;
4485                 wpa_supplicant_cancel_sched_scan(wpa_s);
4486                 wpa_supplicant_cancel_scan(wpa_s);
4487                 wpa_supplicant_deauthenticate(wpa_s,
4488                                               WLAN_REASON_DEAUTH_LEAVING);
4489         } else if (os_strcmp(buf, "SCAN") == 0) {
4490                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
4491                         reply_len = -1;
4492                 else {
4493                         if (!wpa_s->scanning &&
4494                             ((wpa_s->wpa_state <= WPA_SCANNING) ||
4495                              (wpa_s->wpa_state == WPA_COMPLETED))) {
4496                                 wpa_s->normal_scans = 0;
4497                                 wpa_s->scan_req = 2;
4498                                 wpa_supplicant_req_scan(wpa_s, 0, 0);
4499                         } else if (wpa_s->sched_scanning) {
4500                                 wpa_printf(MSG_DEBUG, "Stop ongoing "
4501                                            "sched_scan to allow requested "
4502                                            "full scan to proceed");
4503                                 wpa_supplicant_cancel_sched_scan(wpa_s);
4504                                 wpa_s->scan_req = 2;
4505                                 wpa_supplicant_req_scan(wpa_s, 0, 0);
4506                         } else {
4507                                 wpa_printf(MSG_DEBUG, "Ongoing scan action - "
4508                                            "reject new request");
4509                                 reply_len = os_snprintf(reply, reply_size,
4510                                                         "FAIL-BUSY\n");
4511                         }
4512                 }
4513         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
4514                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
4515                         wpa_s, reply, reply_size);
4516         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
4517                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
4518                         reply_len = -1;
4519         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
4520                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
4521                         reply_len = -1;
4522         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
4523                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
4524                         reply_len = -1;
4525         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
4526                 reply_len = wpa_supplicant_ctrl_iface_add_network(
4527                         wpa_s, reply, reply_size);
4528         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
4529                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
4530                         reply_len = -1;
4531         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
4532                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
4533                         reply_len = -1;
4534         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
4535                 reply_len = wpa_supplicant_ctrl_iface_get_network(
4536                         wpa_s, buf + 12, reply, reply_size);
4537         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
4538                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
4539                         wpa_s, reply, reply_size);
4540         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
4541                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
4542                         wpa_s, reply, reply_size);
4543         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
4544                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
4545                         reply_len = -1;
4546         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
4547                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
4548                         reply_len = -1;
4549 #ifndef CONFIG_NO_CONFIG_WRITE
4550         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
4551                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
4552                         reply_len = -1;
4553 #endif /* CONFIG_NO_CONFIG_WRITE */
4554         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
4555                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
4556                         wpa_s, buf + 15, reply, reply_size);
4557         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
4558                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
4559                         reply_len = -1;
4560         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
4561                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
4562                         reply_len = -1;
4563         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
4564                 reply_len = wpa_supplicant_global_iface_list(
4565                         wpa_s->global, reply, reply_size);
4566         } else if (os_strcmp(buf, "INTERFACES") == 0) {
4567                 reply_len = wpa_supplicant_global_iface_interfaces(
4568                         wpa_s->global, reply, reply_size);
4569         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
4570                 reply_len = wpa_supplicant_ctrl_iface_bss(
4571                         wpa_s, buf + 4, reply, reply_size);
4572 #ifdef CONFIG_AP
4573         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
4574                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
4575         } else if (os_strncmp(buf, "STA ", 4) == 0) {
4576                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
4577                                               reply_size);
4578         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
4579                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
4580                                                    reply_size);
4581         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
4582                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
4583                         reply_len = -1;
4584         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
4585                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
4586                         reply_len = -1;
4587 #endif /* CONFIG_AP */
4588         } else if (os_strcmp(buf, "SUSPEND") == 0) {
4589                 wpas_notify_suspend(wpa_s->global);
4590         } else if (os_strcmp(buf, "RESUME") == 0) {
4591                 wpas_notify_resume(wpa_s->global);
4592         } else if (os_strcmp(buf, "DROP_SA") == 0) {
4593                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
4594         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
4595                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
4596                         reply_len = -1;
4597         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
4598                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
4599                         reply_len = -1;
4600         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
4601                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
4602                         reply_len = -1;
4603         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
4604                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
4605                                                                buf + 17))
4606                         reply_len = -1;
4607 #ifdef CONFIG_TDLS
4608         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
4609                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
4610                         reply_len = -1;
4611         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
4612                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
4613                         reply_len = -1;
4614         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
4615                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
4616                         reply_len = -1;
4617 #endif /* CONFIG_TDLS */
4618         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
4619                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
4620                                                        reply_size);
4621         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
4622                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
4623                                                        reply_size);
4624 #ifdef CONFIG_AUTOSCAN
4625         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
4626                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
4627                         reply_len = -1;
4628 #endif /* CONFIG_AUTOSCAN */
4629 #ifdef ANDROID
4630         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
4631                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
4632                                                       reply_size);
4633 #endif
4634         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
4635                 eapol_sm_request_reauth(wpa_s->eapol);
4636         } else {
4637                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
4638                 reply_len = 16;
4639         }
4640
4641         if (reply_len < 0) {
4642                 os_memcpy(reply, "FAIL\n", 5);
4643                 reply_len = 5;
4644         }
4645
4646         if (ctrl_rsp)
4647                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
4648
4649         *resp_len = reply_len;
4650         return reply;
4651 }
4652
4653
4654 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
4655                                            char *cmd)
4656 {
4657         struct wpa_interface iface;
4658         char *pos;
4659
4660         /*
4661          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
4662          * TAB<bridge_ifname>
4663          */
4664         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
4665
4666         os_memset(&iface, 0, sizeof(iface));
4667
4668         do {
4669                 iface.ifname = pos = cmd;
4670                 pos = os_strchr(pos, '\t');
4671                 if (pos)
4672                         *pos++ = '\0';
4673                 if (iface.ifname[0] == '\0')
4674                         return -1;
4675                 if (pos == NULL)
4676                         break;
4677
4678                 iface.confname = pos;
4679                 pos = os_strchr(pos, '\t');
4680                 if (pos)
4681                         *pos++ = '\0';
4682                 if (iface.confname[0] == '\0')
4683                         iface.confname = NULL;
4684                 if (pos == NULL)
4685                         break;
4686
4687                 iface.driver = pos;
4688                 pos = os_strchr(pos, '\t');
4689                 if (pos)
4690                         *pos++ = '\0';
4691                 if (iface.driver[0] == '\0')
4692                         iface.driver = NULL;
4693                 if (pos == NULL)
4694                         break;
4695
4696                 iface.ctrl_interface = pos;
4697                 pos = os_strchr(pos, '\t');
4698                 if (pos)
4699                         *pos++ = '\0';
4700                 if (iface.ctrl_interface[0] == '\0')
4701                         iface.ctrl_interface = NULL;
4702                 if (pos == NULL)
4703                         break;
4704
4705                 iface.driver_param = pos;
4706                 pos = os_strchr(pos, '\t');
4707                 if (pos)
4708                         *pos++ = '\0';
4709                 if (iface.driver_param[0] == '\0')
4710                         iface.driver_param = NULL;
4711                 if (pos == NULL)
4712                         break;
4713
4714                 iface.bridge_ifname = pos;
4715                 pos = os_strchr(pos, '\t');
4716                 if (pos)
4717                         *pos++ = '\0';
4718                 if (iface.bridge_ifname[0] == '\0')
4719                         iface.bridge_ifname = NULL;
4720                 if (pos == NULL)
4721                         break;
4722         } while (0);
4723
4724         if (wpa_supplicant_get_iface(global, iface.ifname))
4725                 return -1;
4726
4727         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
4728 }
4729
4730
4731 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
4732                                               char *cmd)
4733 {
4734         struct wpa_supplicant *wpa_s;
4735
4736         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
4737
4738         wpa_s = wpa_supplicant_get_iface(global, cmd);
4739         if (wpa_s == NULL)
4740                 return -1;
4741         return wpa_supplicant_remove_iface(global, wpa_s, 0);
4742 }
4743
4744
4745 static void wpa_free_iface_info(struct wpa_interface_info *iface)
4746 {
4747         struct wpa_interface_info *prev;
4748
4749         while (iface) {
4750                 prev = iface;
4751                 iface = iface->next;
4752
4753                 os_free(prev->ifname);
4754                 os_free(prev->desc);
4755                 os_free(prev);
4756         }
4757 }
4758
4759
4760 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
4761                                             char *buf, int len)
4762 {
4763         int i, res;
4764         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
4765         char *pos, *end;
4766
4767         for (i = 0; wpa_drivers[i]; i++) {
4768                 struct wpa_driver_ops *drv = wpa_drivers[i];
4769                 if (drv->get_interfaces == NULL)
4770                         continue;
4771                 tmp = drv->get_interfaces(global->drv_priv[i]);
4772                 if (tmp == NULL)
4773                         continue;
4774
4775                 if (last == NULL)
4776                         iface = last = tmp;
4777                 else
4778                         last->next = tmp;
4779                 while (last->next)
4780                         last = last->next;
4781         }
4782
4783         pos = buf;
4784         end = buf + len;
4785         for (tmp = iface; tmp; tmp = tmp->next) {
4786                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
4787                                   tmp->drv_name, tmp->ifname,
4788                                   tmp->desc ? tmp->desc : "");
4789                 if (res < 0 || res >= end - pos) {
4790                         *pos = '\0';
4791                         break;
4792                 }
4793                 pos += res;
4794         }
4795
4796         wpa_free_iface_info(iface);
4797
4798         return pos - buf;
4799 }
4800
4801
4802 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
4803                                                   char *buf, int len)
4804 {
4805         int res;
4806         char *pos, *end;
4807         struct wpa_supplicant *wpa_s;
4808
4809         wpa_s = global->ifaces;
4810         pos = buf;
4811         end = buf + len;
4812
4813         while (wpa_s) {
4814                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
4815                 if (res < 0 || res >= end - pos) {
4816                         *pos = '\0';
4817                         break;
4818                 }
4819                 pos += res;
4820                 wpa_s = wpa_s->next;
4821         }
4822         return pos - buf;
4823 }
4824
4825
4826 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
4827                                                 char *buf, size_t *resp_len)
4828 {
4829         char *reply;
4830         const int reply_size = 2048;
4831         int reply_len;
4832         int level = MSG_DEBUG;
4833
4834         if (os_strcmp(buf, "PING") == 0)
4835                 level = MSG_EXCESSIVE;
4836         wpa_hexdump_ascii(level, "RX global ctrl_iface",
4837                           (const u8 *) buf, os_strlen(buf));
4838
4839         reply = os_malloc(reply_size);
4840         if (reply == NULL) {
4841                 *resp_len = 1;
4842                 return NULL;
4843         }
4844
4845         os_memcpy(reply, "OK\n", 3);
4846         reply_len = 3;
4847
4848         if (os_strcmp(buf, "PING") == 0) {
4849                 os_memcpy(reply, "PONG\n", 5);
4850                 reply_len = 5;
4851         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
4852                 if (wpa_supplicant_global_iface_add(global, buf + 14))
4853                         reply_len = -1;
4854         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
4855                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
4856                         reply_len = -1;
4857         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
4858                 reply_len = wpa_supplicant_global_iface_list(
4859                         global, reply, reply_size);
4860         } else if (os_strcmp(buf, "INTERFACES") == 0) {
4861                 reply_len = wpa_supplicant_global_iface_interfaces(
4862                         global, reply, reply_size);
4863         } else if (os_strcmp(buf, "TERMINATE") == 0) {
4864                 wpa_supplicant_terminate_proc(global);
4865         } else if (os_strcmp(buf, "SUSPEND") == 0) {
4866                 wpas_notify_suspend(global);
4867         } else if (os_strcmp(buf, "RESUME") == 0) {
4868                 wpas_notify_resume(global);
4869         } else {
4870                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
4871                 reply_len = 16;
4872         }
4873
4874         if (reply_len < 0) {
4875                 os_memcpy(reply, "FAIL\n", 5);
4876                 reply_len = 5;
4877         }
4878
4879         *resp_len = reply_len;
4880         return reply;
4881 }