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