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