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