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