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