OSDN Git Service

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