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