Merge branch 'moonshot' of ssh://moonshot.suchdamage.org:822/srv/git/libeap into...
[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 == -2) {
1979                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
1980                 return 25;
1981         }
1982         if (new_pin == -3) {
1983                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
1984                 return 25;
1985         }
1986         if (new_pin < 0)
1987                 return -1;
1988         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
1989                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
1990                 if (ret < 0 || (size_t) ret >= buflen)
1991                         return -1;
1992                 return ret;
1993         }
1994
1995         os_memcpy(buf, "OK\n", 3);
1996         return 3;
1997 }
1998
1999
2000 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
2001 {
2002         unsigned int timeout = atoi(cmd);
2003         return wpas_p2p_listen(wpa_s, timeout);
2004 }
2005
2006
2007 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
2008 {
2009         u8 addr[ETH_ALEN];
2010         char *pos;
2011
2012         /* <addr> <config method> */
2013
2014         if (hwaddr_aton(cmd, addr))
2015                 return -1;
2016
2017         pos = cmd + 17;
2018         if (*pos != ' ')
2019                 return -1;
2020         pos++;
2021
2022         return wpas_p2p_prov_disc(wpa_s, addr, pos);
2023 }
2024
2025
2026 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
2027                               size_t buflen)
2028 {
2029         struct wpa_ssid *ssid = wpa_s->current_ssid;
2030
2031         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
2032             ssid->passphrase == NULL)
2033                 return -1;
2034
2035         os_strlcpy(buf, ssid->passphrase, buflen);
2036         return os_strlen(buf);
2037 }
2038
2039
2040 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
2041                                   char *buf, size_t buflen)
2042 {
2043         u64 ref;
2044         int res;
2045         u8 dst_buf[ETH_ALEN], *dst;
2046         struct wpabuf *tlvs;
2047         char *pos;
2048         size_t len;
2049
2050         if (hwaddr_aton(cmd, dst_buf))
2051                 return -1;
2052         dst = dst_buf;
2053         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2054             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2055                 dst = NULL;
2056         pos = cmd + 17;
2057         if (*pos != ' ')
2058                 return -1;
2059         pos++;
2060
2061         if (os_strncmp(pos, "upnp ", 5) == 0) {
2062                 u8 version;
2063                 pos += 5;
2064                 if (hexstr2bin(pos, &version, 1) < 0)
2065                         return -1;
2066                 pos += 2;
2067                 if (*pos != ' ')
2068                         return -1;
2069                 pos++;
2070                 ref = (u64) wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
2071         } else {
2072                 len = os_strlen(pos);
2073                 if (len & 1)
2074                         return -1;
2075                 len /= 2;
2076                 tlvs = wpabuf_alloc(len);
2077                 if (tlvs == NULL)
2078                         return -1;
2079                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
2080                         wpabuf_free(tlvs);
2081                         return -1;
2082                 }
2083
2084                 ref = (u64) wpas_p2p_sd_request(wpa_s, dst, tlvs);
2085                 wpabuf_free(tlvs);
2086         }
2087         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
2088         if (res < 0 || (unsigned) res >= buflen)
2089                 return -1;
2090         return res;
2091 }
2092
2093
2094 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
2095                                          char *cmd)
2096 {
2097         long long unsigned val;
2098         u64 req;
2099         if (sscanf(cmd, "%llx", &val) != 1)
2100                 return -1;
2101         req = val;
2102         return wpas_p2p_sd_cancel_request(wpa_s, (void *) req);
2103 }
2104
2105
2106 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
2107 {
2108         int freq;
2109         u8 dst_buf[ETH_ALEN], *dst;
2110         u8 dialog_token;
2111         struct wpabuf *resp_tlvs;
2112         char *pos, *pos2;
2113         size_t len;
2114
2115         pos = os_strchr(cmd, ' ');
2116         if (pos == NULL)
2117                 return -1;
2118         *pos++ = '\0';
2119         freq = atoi(cmd);
2120         if (freq == 0)
2121                 return -1;
2122
2123         if (hwaddr_aton(pos, dst_buf))
2124                 return -1;
2125         dst = dst_buf;
2126         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2127             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2128                 dst = NULL;
2129         pos += 17;
2130         if (*pos != ' ')
2131                 return -1;
2132         pos++;
2133
2134         pos2 = os_strchr(pos, ' ');
2135         if (pos2 == NULL)
2136                 return -1;
2137         *pos2++ = '\0';
2138         dialog_token = atoi(pos);
2139
2140         len = os_strlen(pos2);
2141         if (len & 1)
2142                 return -1;
2143         len /= 2;
2144         resp_tlvs = wpabuf_alloc(len);
2145         if (resp_tlvs == NULL)
2146                 return -1;
2147         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
2148                 wpabuf_free(resp_tlvs);
2149                 return -1;
2150         }
2151
2152         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
2153         wpabuf_free(resp_tlvs);
2154         return 0;
2155 }
2156
2157
2158 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
2159                                        char *cmd)
2160 {
2161         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
2162         return 0;
2163 }
2164
2165
2166 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
2167                                         char *cmd)
2168 {
2169         char *pos;
2170         size_t len;
2171         struct wpabuf *query, *resp;
2172
2173         pos = os_strchr(cmd, ' ');
2174         if (pos == NULL)
2175                 return -1;
2176         *pos++ = '\0';
2177
2178         len = os_strlen(cmd);
2179         if (len & 1)
2180                 return -1;
2181         len /= 2;
2182         query = wpabuf_alloc(len);
2183         if (query == NULL)
2184                 return -1;
2185         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2186                 wpabuf_free(query);
2187                 return -1;
2188         }
2189
2190         len = os_strlen(pos);
2191         if (len & 1) {
2192                 wpabuf_free(query);
2193                 return -1;
2194         }
2195         len /= 2;
2196         resp = wpabuf_alloc(len);
2197         if (resp == NULL) {
2198                 wpabuf_free(query);
2199                 return -1;
2200         }
2201         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
2202                 wpabuf_free(query);
2203                 wpabuf_free(resp);
2204                 return -1;
2205         }
2206
2207         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
2208                 wpabuf_free(query);
2209                 wpabuf_free(resp);
2210                 return -1;
2211         }
2212         return 0;
2213 }
2214
2215
2216 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2217 {
2218         char *pos;
2219         u8 version;
2220
2221         pos = os_strchr(cmd, ' ');
2222         if (pos == NULL)
2223                 return -1;
2224         *pos++ = '\0';
2225
2226         if (hexstr2bin(cmd, &version, 1) < 0)
2227                 return -1;
2228
2229         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
2230 }
2231
2232
2233 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
2234 {
2235         char *pos;
2236
2237         pos = os_strchr(cmd, ' ');
2238         if (pos == NULL)
2239                 return -1;
2240         *pos++ = '\0';
2241
2242         if (os_strcmp(cmd, "bonjour") == 0)
2243                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
2244         if (os_strcmp(cmd, "upnp") == 0)
2245                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
2246         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2247         return -1;
2248 }
2249
2250
2251 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
2252                                         char *cmd)
2253 {
2254         size_t len;
2255         struct wpabuf *query;
2256         int ret;
2257
2258         len = os_strlen(cmd);
2259         if (len & 1)
2260                 return -1;
2261         len /= 2;
2262         query = wpabuf_alloc(len);
2263         if (query == NULL)
2264                 return -1;
2265         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2266                 wpabuf_free(query);
2267                 return -1;
2268         }
2269
2270         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2271         wpabuf_free(query);
2272         return ret;
2273 }
2274
2275
2276 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2277 {
2278         char *pos;
2279         u8 version;
2280
2281         pos = os_strchr(cmd, ' ');
2282         if (pos == NULL)
2283                 return -1;
2284         *pos++ = '\0';
2285
2286         if (hexstr2bin(cmd, &version, 1) < 0)
2287                 return -1;
2288
2289         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
2290 }
2291
2292
2293 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
2294 {
2295         char *pos;
2296
2297         pos = os_strchr(cmd, ' ');
2298         if (pos == NULL)
2299                 return -1;
2300         *pos++ = '\0';
2301
2302         if (os_strcmp(cmd, "bonjour") == 0)
2303                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
2304         if (os_strcmp(cmd, "upnp") == 0)
2305                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
2306         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2307         return -1;
2308 }
2309
2310
2311 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
2312 {
2313         u8 addr[ETH_ALEN];
2314
2315         /* <addr> */
2316
2317         if (hwaddr_aton(cmd, addr))
2318                 return -1;
2319
2320         return wpas_p2p_reject(wpa_s, addr);
2321 }
2322
2323
2324 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
2325 {
2326         char *pos;
2327         int id;
2328         struct wpa_ssid *ssid;
2329         u8 peer[ETH_ALEN];
2330
2331         id = atoi(cmd);
2332         pos = os_strstr(cmd, " peer=");
2333         if (pos) {
2334                 pos += 6;
2335                 if (hwaddr_aton(pos, peer))
2336                         return -1;
2337         }
2338         ssid = wpa_config_get_network(wpa_s->conf, id);
2339         if (ssid == NULL || ssid->disabled != 2) {
2340                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2341                            "for persistent P2P group",
2342                            id);
2343                 return -1;
2344         }
2345
2346         return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
2347 }
2348
2349
2350 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
2351 {
2352         char *pos;
2353         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
2354
2355         pos = os_strstr(cmd, " peer=");
2356         if (!pos)
2357                 return -1;
2358
2359         *pos = '\0';
2360         pos += 6;
2361         if (hwaddr_aton(pos, peer)) {
2362                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
2363                 return -1;
2364         }
2365
2366         pos = os_strstr(pos, " go_dev_addr=");
2367         if (pos) {
2368                 pos += 13;
2369                 if (hwaddr_aton(pos, go_dev_addr)) {
2370                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
2371                                    pos);
2372                         return -1;
2373                 }
2374                 go_dev = go_dev_addr;
2375         }
2376
2377         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
2378 }
2379
2380
2381 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
2382 {
2383         if (os_strncmp(cmd, "persistent=", 11) == 0)
2384                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
2385         if (os_strncmp(cmd, "group=", 6) == 0)
2386                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
2387
2388         return -1;
2389 }
2390
2391
2392 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
2393                                          char *cmd, int freq)
2394 {
2395         int id;
2396         struct wpa_ssid *ssid;
2397
2398         id = atoi(cmd);
2399         ssid = wpa_config_get_network(wpa_s->conf, id);
2400         if (ssid == NULL || ssid->disabled != 2) {
2401                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2402                            "for persistent P2P group",
2403                            id);
2404                 return -1;
2405         }
2406
2407         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
2408 }
2409
2410
2411 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
2412 {
2413         int freq = 0;
2414         char *pos;
2415
2416         pos = os_strstr(cmd, "freq=");
2417         if (pos)
2418                 freq = atoi(pos + 5);
2419
2420         if (os_strncmp(cmd, "persistent=", 11) == 0)
2421                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
2422         if (os_strcmp(cmd, "persistent") == 0 ||
2423             os_strncmp(cmd, "persistent ", 11) == 0)
2424                 return wpas_p2p_group_add(wpa_s, 1, freq);
2425         if (os_strncmp(cmd, "freq=", 5) == 0)
2426                 return wpas_p2p_group_add(wpa_s, 0, freq);
2427
2428         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
2429                    cmd);
2430         return -1;
2431 }
2432
2433
2434 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
2435                          char *buf, size_t buflen)
2436 {
2437         u8 addr[ETH_ALEN], *addr_ptr;
2438         int next;
2439
2440         if (!wpa_s->global->p2p)
2441                 return -1;
2442
2443         if (os_strcmp(cmd, "FIRST") == 0) {
2444                 addr_ptr = NULL;
2445                 next = 0;
2446         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2447                 if (hwaddr_aton(cmd + 5, addr) < 0)
2448                         return -1;
2449                 addr_ptr = addr;
2450                 next = 1;
2451         } else {
2452                 if (hwaddr_aton(cmd, addr) < 0)
2453                         return -1;
2454                 addr_ptr = addr;
2455                 next = 0;
2456         }
2457
2458         return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next,
2459                                  buf, buflen);
2460 }
2461
2462
2463 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
2464 {
2465         char *param;
2466
2467         if (wpa_s->global->p2p == NULL)
2468                 return -1;
2469
2470         param = os_strchr(cmd, ' ');
2471         if (param == NULL)
2472                 return -1;
2473         *param++ = '\0';
2474
2475         if (os_strcmp(cmd, "discoverability") == 0) {
2476                 p2p_set_client_discoverability(wpa_s->global->p2p,
2477                                                atoi(param));
2478                 return 0;
2479         }
2480
2481         if (os_strcmp(cmd, "managed") == 0) {
2482                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
2483                 return 0;
2484         }
2485
2486         if (os_strcmp(cmd, "listen_channel") == 0) {
2487                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
2488                                               atoi(param));
2489         }
2490
2491         if (os_strcmp(cmd, "ssid_postfix") == 0) {
2492                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
2493                                             os_strlen(param));
2494         }
2495
2496         if (os_strcmp(cmd, "noa") == 0) {
2497                 char *pos;
2498                 int count, start, duration;
2499                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
2500                 count = atoi(param);
2501                 pos = os_strchr(param, ',');
2502                 if (pos == NULL)
2503                         return -1;
2504                 pos++;
2505                 start = atoi(pos);
2506                 pos = os_strchr(pos, ',');
2507                 if (pos == NULL)
2508                         return -1;
2509                 pos++;
2510                 duration = atoi(pos);
2511                 if (count < 0 || count > 255 || start < 0 || duration < 0)
2512                         return -1;
2513                 if (count == 0 && duration > 0)
2514                         return -1;
2515                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
2516                            "start=%d duration=%d", count, start, duration);
2517                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
2518         }
2519
2520         if (os_strcmp(cmd, "ps") == 0)
2521                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
2522
2523         if (os_strcmp(cmd, "oppps") == 0)
2524                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
2525
2526         if (os_strcmp(cmd, "ctwindow") == 0)
2527                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
2528
2529         if (os_strcmp(cmd, "disabled") == 0) {
2530                 wpa_s->global->p2p_disabled = atoi(param);
2531                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
2532                            wpa_s->global->p2p_disabled ?
2533                            "disabled" : "enabled");
2534                 if (wpa_s->global->p2p_disabled) {
2535                         wpas_p2p_stop_find(wpa_s);
2536                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2537                         p2p_flush(wpa_s->global->p2p);
2538                 }
2539                 return 0;
2540         }
2541
2542         if (os_strcmp(cmd, "force_long_sd") == 0) {
2543                 wpa_s->force_long_sd = atoi(param);
2544                 return 0;
2545         }
2546
2547         if (os_strcmp(cmd, "peer_filter") == 0) {
2548                 u8 addr[ETH_ALEN];
2549                 if (hwaddr_aton(param, addr))
2550                         return -1;
2551                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
2552                 return 0;
2553         }
2554
2555         if (os_strcmp(cmd, "cross_connect") == 0)
2556                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
2557
2558         if (os_strcmp(cmd, "go_apsd") == 0) {
2559                 if (os_strcmp(param, "disable") == 0)
2560                         wpa_s->set_ap_uapsd = 0;
2561                 else {
2562                         wpa_s->set_ap_uapsd = 1;
2563                         wpa_s->ap_uapsd = atoi(param);
2564                 }
2565                 return 0;
2566         }
2567
2568         if (os_strcmp(cmd, "client_apsd") == 0) {
2569                 if (os_strcmp(param, "disable") == 0)
2570                         wpa_s->set_sta_uapsd = 0;
2571                 else {
2572                         int be, bk, vi, vo;
2573                         char *pos;
2574                         /* format: BE,BK,VI,VO;max SP Length */
2575                         be = atoi(param);
2576                         pos = os_strchr(param, ',');
2577                         if (pos == NULL)
2578                                 return -1;
2579                         pos++;
2580                         bk = atoi(pos);
2581                         pos = os_strchr(pos, ',');
2582                         if (pos == NULL)
2583                                 return -1;
2584                         pos++;
2585                         vi = atoi(pos);
2586                         pos = os_strchr(pos, ',');
2587                         if (pos == NULL)
2588                                 return -1;
2589                         pos++;
2590                         vo = atoi(pos);
2591                         /* ignore max SP Length for now */
2592
2593                         wpa_s->set_sta_uapsd = 1;
2594                         wpa_s->sta_uapsd = 0;
2595                         if (be)
2596                                 wpa_s->sta_uapsd |= BIT(0);
2597                         if (bk)
2598                                 wpa_s->sta_uapsd |= BIT(1);
2599                         if (vi)
2600                                 wpa_s->sta_uapsd |= BIT(2);
2601                         if (vo)
2602                                 wpa_s->sta_uapsd |= BIT(3);
2603                 }
2604                 return 0;
2605         }
2606
2607         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
2608                    cmd);
2609
2610         return -1;
2611 }
2612
2613
2614 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
2615 {
2616         char *pos, *pos2;
2617         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
2618
2619         if (cmd[0]) {
2620                 pos = os_strchr(cmd, ' ');
2621                 if (pos == NULL)
2622                         return -1;
2623                 *pos++ = '\0';
2624                 dur1 = atoi(cmd);
2625
2626                 pos2 = os_strchr(pos, ' ');
2627                 if (pos2)
2628                         *pos2++ = '\0';
2629                 int1 = atoi(pos);
2630         } else
2631                 pos2 = NULL;
2632
2633         if (pos2) {
2634                 pos = os_strchr(pos2, ' ');
2635                 if (pos == NULL)
2636                         return -1;
2637                 *pos++ = '\0';
2638                 dur2 = atoi(pos2);
2639                 int2 = atoi(pos);
2640         }
2641
2642         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
2643 }
2644
2645
2646 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
2647 {
2648         char *pos;
2649         unsigned int period = 0, interval = 0;
2650
2651         if (cmd[0]) {
2652                 pos = os_strchr(cmd, ' ');
2653                 if (pos == NULL)
2654                         return -1;
2655                 *pos++ = '\0';
2656                 period = atoi(cmd);
2657                 interval = atoi(pos);
2658         }
2659
2660         return wpas_p2p_ext_listen(wpa_s, period, interval);
2661 }
2662
2663 #endif /* CONFIG_P2P */
2664
2665
2666 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
2667         struct wpa_supplicant *wpa_s, char *cmd)
2668 {
2669         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
2670         return 0;
2671 }
2672
2673
2674 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
2675                                          char *buf, size_t *resp_len)
2676 {
2677         char *reply;
2678         const int reply_size = 4096;
2679         int ctrl_rsp = 0;
2680         int reply_len;
2681
2682         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
2683             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
2684                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
2685                                       (const u8 *) buf, os_strlen(buf));
2686         } else {
2687                 int level = MSG_DEBUG;
2688                 if (os_strcmp(buf, "PING") == 0)
2689                         level = MSG_EXCESSIVE;
2690                 wpa_hexdump_ascii(level, "RX ctrl_iface",
2691                                   (const u8 *) buf, os_strlen(buf));
2692         }
2693
2694         reply = os_malloc(reply_size);
2695         if (reply == NULL) {
2696                 *resp_len = 1;
2697                 return NULL;
2698         }
2699
2700         os_memcpy(reply, "OK\n", 3);
2701         reply_len = 3;
2702
2703         if (os_strcmp(buf, "PING") == 0) {
2704                 os_memcpy(reply, "PONG\n", 5);
2705                 reply_len = 5;
2706         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
2707                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
2708         } else if (os_strcmp(buf, "MIB") == 0) {
2709                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
2710                 if (reply_len >= 0) {
2711                         int res;
2712                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
2713                                                reply_size - reply_len);
2714                         if (res < 0)
2715                                 reply_len = -1;
2716                         else
2717                                 reply_len += res;
2718                 }
2719         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
2720                 reply_len = wpa_supplicant_ctrl_iface_status(
2721                         wpa_s, buf + 6, reply, reply_size);
2722         } else if (os_strcmp(buf, "PMKSA") == 0) {
2723                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
2724                                                     reply_size);
2725         } else if (os_strncmp(buf, "SET ", 4) == 0) {
2726                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
2727                         reply_len = -1;
2728         } else if (os_strcmp(buf, "LOGON") == 0) {
2729                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2730         } else if (os_strcmp(buf, "LOGOFF") == 0) {
2731                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2732         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
2733                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
2734                         reply_len = -1;
2735                 else {
2736                         wpa_s->disconnected = 0;
2737                         wpa_s->reassociate = 1;
2738                         wpa_supplicant_req_scan(wpa_s, 0, 0);
2739                 }
2740         } else if (os_strcmp(buf, "RECONNECT") == 0) {
2741                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
2742                         reply_len = -1;
2743                 else if (wpa_s->disconnected) {
2744                         wpa_s->disconnected = 0;
2745                         wpa_s->reassociate = 1;
2746                         wpa_supplicant_req_scan(wpa_s, 0, 0);
2747                 }
2748 #ifdef IEEE8021X_EAPOL
2749         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
2750                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
2751                         reply_len = -1;
2752 #endif /* IEEE8021X_EAPOL */
2753 #ifdef CONFIG_PEERKEY
2754         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
2755                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
2756                         reply_len = -1;
2757 #endif /* CONFIG_PEERKEY */
2758 #ifdef CONFIG_IEEE80211R
2759         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
2760                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
2761                         reply_len = -1;
2762 #endif /* CONFIG_IEEE80211R */
2763 #ifdef CONFIG_WPS
2764         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2765                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
2766                         reply_len = -1;
2767         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
2768                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
2769                         reply_len = -1;
2770         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2771                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
2772                                                               reply,
2773                                                               reply_size);
2774         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
2775                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
2776                         wpa_s, buf + 14, reply, reply_size);
2777         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
2778                 if (wpas_wps_cancel(wpa_s))
2779                         reply_len = -1;
2780 #ifdef CONFIG_WPS_OOB
2781         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
2782                 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
2783                         reply_len = -1;
2784 #endif /* CONFIG_WPS_OOB */
2785         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
2786                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
2787                         reply_len = -1;
2788 #ifdef CONFIG_WPS_ER
2789         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
2790                 if (wpas_wps_er_start(wpa_s, NULL))
2791                         reply_len = -1;
2792         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
2793                 if (wpas_wps_er_start(wpa_s, buf + 13))
2794                         reply_len = -1;
2795         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
2796                 if (wpas_wps_er_stop(wpa_s))
2797                         reply_len = -1;
2798         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
2799                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
2800                         reply_len = -1;
2801         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
2802                 if (wpas_wps_er_pbc(wpa_s, buf + 11))
2803                         reply_len = -1;
2804         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
2805                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
2806                         reply_len = -1;
2807         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
2808                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
2809                         reply_len = -1;
2810 #endif /* CONFIG_WPS_ER */
2811 #endif /* CONFIG_WPS */
2812 #ifdef CONFIG_IBSS_RSN
2813         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
2814                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
2815                         reply_len = -1;
2816 #endif /* CONFIG_IBSS_RSN */
2817 #ifdef CONFIG_P2P
2818         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
2819                 if (p2p_ctrl_find(wpa_s, buf + 9))
2820                         reply_len = -1;
2821         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
2822                 if (p2p_ctrl_find(wpa_s, ""))
2823                         reply_len = -1;
2824         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
2825                 wpas_p2p_stop_find(wpa_s);
2826         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
2827                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
2828                                              reply_size);
2829         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
2830                 if (p2p_ctrl_listen(wpa_s, buf + 11))
2831                         reply_len = -1;
2832         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
2833                 if (p2p_ctrl_listen(wpa_s, ""))
2834                         reply_len = -1;
2835         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
2836                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
2837                         reply_len = -1;
2838         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
2839                 if (wpas_p2p_group_add(wpa_s, 0, 0))
2840                         reply_len = -1;
2841         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
2842                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
2843                         reply_len = -1;
2844         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
2845                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
2846                         reply_len = -1;
2847         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
2848                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
2849         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
2850                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
2851                                                    reply_size);
2852         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
2853                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
2854                         reply_len = -1;
2855         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
2856                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
2857                         reply_len = -1;
2858         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
2859                 wpas_p2p_sd_service_update(wpa_s);
2860         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
2861                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
2862                         reply_len = -1;
2863         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
2864                 wpas_p2p_service_flush(wpa_s);
2865         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
2866                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
2867                         reply_len = -1;
2868         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
2869                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
2870                         reply_len = -1;
2871         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
2872                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
2873                         reply_len = -1;
2874         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
2875                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
2876                         reply_len = -1;
2877         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
2878                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
2879                                               reply_size);
2880         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
2881                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
2882                         reply_len = -1;
2883         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
2884                 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
2885                 wpa_s->force_long_sd = 0;
2886                 p2p_flush(wpa_s->global->p2p);
2887         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
2888                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
2889                         reply_len = -1;
2890         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
2891                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
2892                         reply_len = -1;
2893         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
2894                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
2895                         reply_len = -1;
2896         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
2897                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
2898                         reply_len = -1;
2899 #endif /* CONFIG_P2P */
2900         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
2901         {
2902                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
2903                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
2904                         reply_len = -1;
2905                 else
2906                         ctrl_rsp = 1;
2907         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
2908                 if (wpa_supplicant_reload_configuration(wpa_s))
2909                         reply_len = -1;
2910         } else if (os_strcmp(buf, "TERMINATE") == 0) {
2911                 wpa_supplicant_terminate_proc(wpa_s->global);
2912         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
2913                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
2914                         reply_len = -1;
2915         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
2916                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
2917                         wpa_s, reply, reply_size);
2918         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
2919                 wpa_s->reassociate = 0;
2920                 wpa_s->disconnected = 1;
2921                 wpa_supplicant_deauthenticate(wpa_s,
2922                                               WLAN_REASON_DEAUTH_LEAVING);
2923         } else if (os_strcmp(buf, "SCAN") == 0) {
2924                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
2925                         reply_len = -1;
2926                 else {
2927                         wpa_s->scan_req = 2;
2928                         wpa_supplicant_req_scan(wpa_s, 0, 0);
2929                 }
2930         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
2931                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
2932                         wpa_s, reply, reply_size);
2933         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
2934                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
2935                         reply_len = -1;
2936         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
2937                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
2938                         reply_len = -1;
2939         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
2940                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
2941                         reply_len = -1;
2942         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
2943                 reply_len = wpa_supplicant_ctrl_iface_add_network(
2944                         wpa_s, reply, reply_size);
2945         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
2946                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
2947                         reply_len = -1;
2948         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
2949                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
2950                         reply_len = -1;
2951         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
2952                 reply_len = wpa_supplicant_ctrl_iface_get_network(
2953                         wpa_s, buf + 12, reply, reply_size);
2954 #ifndef CONFIG_NO_CONFIG_WRITE
2955         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
2956                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
2957                         reply_len = -1;
2958 #endif /* CONFIG_NO_CONFIG_WRITE */
2959         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
2960                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
2961                         wpa_s, buf + 15, reply, reply_size);
2962         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
2963                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
2964                         reply_len = -1;
2965         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
2966                 reply_len = wpa_supplicant_global_iface_list(
2967                         wpa_s->global, reply, reply_size);
2968         } else if (os_strcmp(buf, "INTERFACES") == 0) {
2969                 reply_len = wpa_supplicant_global_iface_interfaces(
2970                         wpa_s->global, reply, reply_size);
2971         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
2972                 reply_len = wpa_supplicant_ctrl_iface_bss(
2973                         wpa_s, buf + 4, reply, reply_size);
2974 #ifdef CONFIG_AP
2975         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
2976                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
2977         } else if (os_strncmp(buf, "STA ", 4) == 0) {
2978                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
2979                                               reply_size);
2980         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2981                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
2982                                                    reply_size);
2983 #endif /* CONFIG_AP */
2984         } else if (os_strcmp(buf, "SUSPEND") == 0) {
2985                 wpas_notify_suspend(wpa_s->global);
2986         } else if (os_strcmp(buf, "RESUME") == 0) {
2987                 wpas_notify_resume(wpa_s->global);
2988         } else if (os_strcmp(buf, "DROP_SA") == 0) {
2989                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
2990         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
2991                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
2992                         reply_len = -1;
2993         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
2994                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
2995                         reply_len = -1;
2996         } else {
2997                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2998                 reply_len = 16;
2999         }
3000
3001         if (reply_len < 0) {
3002                 os_memcpy(reply, "FAIL\n", 5);
3003                 reply_len = 5;
3004         }
3005
3006         if (ctrl_rsp)
3007                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
3008
3009         *resp_len = reply_len;
3010         return reply;
3011 }
3012
3013
3014 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
3015                                            char *cmd)
3016 {
3017         struct wpa_interface iface;
3018         char *pos;
3019
3020         /*
3021          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
3022          * TAB<bridge_ifname>
3023          */
3024         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
3025
3026         os_memset(&iface, 0, sizeof(iface));
3027
3028         do {
3029                 iface.ifname = pos = cmd;
3030                 pos = os_strchr(pos, '\t');
3031                 if (pos)
3032                         *pos++ = '\0';
3033                 if (iface.ifname[0] == '\0')
3034                         return -1;
3035                 if (pos == NULL)
3036                         break;
3037
3038                 iface.confname = pos;
3039                 pos = os_strchr(pos, '\t');
3040                 if (pos)
3041                         *pos++ = '\0';
3042                 if (iface.confname[0] == '\0')
3043                         iface.confname = NULL;
3044                 if (pos == NULL)
3045                         break;
3046
3047                 iface.driver = pos;
3048                 pos = os_strchr(pos, '\t');
3049                 if (pos)
3050                         *pos++ = '\0';
3051                 if (iface.driver[0] == '\0')
3052                         iface.driver = NULL;
3053                 if (pos == NULL)
3054                         break;
3055
3056                 iface.ctrl_interface = pos;
3057                 pos = os_strchr(pos, '\t');
3058                 if (pos)
3059                         *pos++ = '\0';
3060                 if (iface.ctrl_interface[0] == '\0')
3061                         iface.ctrl_interface = NULL;
3062                 if (pos == NULL)
3063                         break;
3064
3065                 iface.driver_param = pos;
3066                 pos = os_strchr(pos, '\t');
3067                 if (pos)
3068                         *pos++ = '\0';
3069                 if (iface.driver_param[0] == '\0')
3070                         iface.driver_param = NULL;
3071                 if (pos == NULL)
3072                         break;
3073
3074                 iface.bridge_ifname = pos;
3075                 pos = os_strchr(pos, '\t');
3076                 if (pos)
3077                         *pos++ = '\0';
3078                 if (iface.bridge_ifname[0] == '\0')
3079                         iface.bridge_ifname = NULL;
3080                 if (pos == NULL)
3081                         break;
3082         } while (0);
3083
3084         if (wpa_supplicant_get_iface(global, iface.ifname))
3085                 return -1;
3086
3087         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
3088 }
3089
3090
3091 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
3092                                               char *cmd)
3093 {
3094         struct wpa_supplicant *wpa_s;
3095
3096         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
3097
3098         wpa_s = wpa_supplicant_get_iface(global, cmd);
3099         if (wpa_s == NULL)
3100                 return -1;
3101         return wpa_supplicant_remove_iface(global, wpa_s);
3102 }
3103
3104
3105 static void wpa_free_iface_info(struct wpa_interface_info *iface)
3106 {
3107         struct wpa_interface_info *prev;
3108
3109         while (iface) {
3110                 prev = iface;
3111                 iface = iface->next;
3112
3113                 os_free(prev->ifname);
3114                 os_free(prev->desc);
3115                 os_free(prev);
3116         }
3117 }
3118
3119
3120 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
3121                                             char *buf, int len)
3122 {
3123         int i, res;
3124         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
3125         char *pos, *end;
3126
3127         for (i = 0; wpa_drivers[i]; i++) {
3128                 struct wpa_driver_ops *drv = wpa_drivers[i];
3129                 if (drv->get_interfaces == NULL)
3130                         continue;
3131                 tmp = drv->get_interfaces(global->drv_priv[i]);
3132                 if (tmp == NULL)
3133                         continue;
3134
3135                 if (last == NULL)
3136                         iface = last = tmp;
3137                 else
3138                         last->next = tmp;
3139                 while (last->next)
3140                         last = last->next;
3141         }
3142
3143         pos = buf;
3144         end = buf + len;
3145         for (tmp = iface; tmp; tmp = tmp->next) {
3146                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
3147                                   tmp->drv_name, tmp->ifname,
3148                                   tmp->desc ? tmp->desc : "");
3149                 if (res < 0 || res >= end - pos) {
3150                         *pos = '\0';
3151                         break;
3152                 }
3153                 pos += res;
3154         }
3155
3156         wpa_free_iface_info(iface);
3157
3158         return pos - buf;
3159 }
3160
3161
3162 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
3163                                                   char *buf, int len)
3164 {
3165         int res;
3166         char *pos, *end;
3167         struct wpa_supplicant *wpa_s;
3168
3169         wpa_s = global->ifaces;
3170         pos = buf;
3171         end = buf + len;
3172
3173         while (wpa_s) {
3174                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
3175                 if (res < 0 || res >= end - pos) {
3176                         *pos = '\0';
3177                         break;
3178                 }
3179                 pos += res;
3180                 wpa_s = wpa_s->next;
3181         }
3182         return pos - buf;
3183 }
3184
3185
3186 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
3187                                                 char *buf, size_t *resp_len)
3188 {
3189         char *reply;
3190         const int reply_size = 2048;
3191         int reply_len;
3192
3193         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
3194                           (const u8 *) buf, os_strlen(buf));
3195
3196         reply = os_malloc(reply_size);
3197         if (reply == NULL) {
3198                 *resp_len = 1;
3199                 return NULL;
3200         }
3201
3202         os_memcpy(reply, "OK\n", 3);
3203         reply_len = 3;
3204
3205         if (os_strcmp(buf, "PING") == 0) {
3206                 os_memcpy(reply, "PONG\n", 5);
3207                 reply_len = 5;
3208         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
3209                 if (wpa_supplicant_global_iface_add(global, buf + 14))
3210                         reply_len = -1;
3211         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
3212                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
3213                         reply_len = -1;
3214         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
3215                 reply_len = wpa_supplicant_global_iface_list(
3216                         global, reply, reply_size);
3217         } else if (os_strcmp(buf, "INTERFACES") == 0) {
3218                 reply_len = wpa_supplicant_global_iface_interfaces(
3219                         global, reply, reply_size);
3220         } else if (os_strcmp(buf, "TERMINATE") == 0) {
3221                 wpa_supplicant_terminate_proc(global);
3222         } else if (os_strcmp(buf, "SUSPEND") == 0) {
3223                 wpas_notify_suspend(global);
3224         } else if (os_strcmp(buf, "RESUME") == 0) {
3225                 wpas_notify_resume(global);
3226         } else {
3227                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3228                 reply_len = 16;
3229         }
3230
3231         if (reply_len < 0) {
3232                 os_memcpy(reply, "FAIL\n", 5);
3233                 reply_len = 5;
3234         }
3235
3236         *resp_len = reply_len;
3237         return reply;
3238 }