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