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