Add [ESS] flag for scan/BSS info from ctrl_iface
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2009, 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 "notify.h"
35 #include "bss.h"
36 #include "ctrl_iface.h"
37
38 extern struct wpa_driver_ops *wpa_drivers[];
39
40 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
41                                             char *buf, int len);
42 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
43                                                   char *buf, int len);
44
45
46 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
47                                          char *cmd)
48 {
49         char *value;
50         int ret = 0;
51
52         value = os_strchr(cmd, ' ');
53         if (value == NULL)
54                 return -1;
55         *value++ = '\0';
56
57         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
58         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
59                 eapol_sm_configure(wpa_s->eapol,
60                                    atoi(value), -1, -1, -1);
61         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
62                 eapol_sm_configure(wpa_s->eapol,
63                                    -1, atoi(value), -1, -1);
64         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
65                 eapol_sm_configure(wpa_s->eapol,
66                                    -1, -1, atoi(value), -1);
67         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
68                 eapol_sm_configure(wpa_s->eapol,
69                                    -1, -1, -1, atoi(value));
70         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
71                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
72                                      atoi(value)))
73                         ret = -1;
74         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
75                    0) {
76                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
77                                      atoi(value)))
78                         ret = -1;
79         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
80                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
81                         ret = -1;
82         } else
83                 ret = -1;
84
85         return ret;
86 }
87
88
89 #ifdef IEEE8021X_EAPOL
90 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
91                                              char *addr)
92 {
93         u8 bssid[ETH_ALEN];
94         struct wpa_ssid *ssid = wpa_s->current_ssid;
95
96         if (hwaddr_aton(addr, bssid)) {
97                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
98                            "'%s'", addr);
99                 return -1;
100         }
101
102         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
103         rsn_preauth_deinit(wpa_s->wpa);
104         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
105                 return -1;
106
107         return 0;
108 }
109 #endif /* IEEE8021X_EAPOL */
110
111
112 #ifdef CONFIG_PEERKEY
113 /* MLME-STKSTART.request(peer) */
114 static int wpa_supplicant_ctrl_iface_stkstart(
115         struct wpa_supplicant *wpa_s, char *addr)
116 {
117         u8 peer[ETH_ALEN];
118
119         if (hwaddr_aton(addr, peer)) {
120                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
121                            "address '%s'", peer);
122                 return -1;
123         }
124
125         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
126                    MAC2STR(peer));
127
128         return wpa_sm_stkstart(wpa_s->wpa, peer);
129 }
130 #endif /* CONFIG_PEERKEY */
131
132
133 #ifdef CONFIG_IEEE80211R
134 static int wpa_supplicant_ctrl_iface_ft_ds(
135         struct wpa_supplicant *wpa_s, char *addr)
136 {
137         u8 target_ap[ETH_ALEN];
138
139         if (hwaddr_aton(addr, target_ap)) {
140                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
141                            "address '%s'", target_ap);
142                 return -1;
143         }
144
145         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
146
147         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap);
148 }
149 #endif /* CONFIG_IEEE80211R */
150
151
152 #ifdef CONFIG_WPS
153 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
154                                              char *cmd)
155 {
156         u8 bssid[ETH_ALEN], *_bssid = bssid;
157
158         if (cmd == NULL || os_strcmp(cmd, "any") == 0)
159                 _bssid = NULL;
160         else if (hwaddr_aton(cmd, bssid)) {
161                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
162                            cmd);
163                 return -1;
164         }
165
166 #ifdef CONFIG_AP
167         if (wpa_s->ap_iface)
168                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
169 #endif /* CONFIG_AP */
170
171         return wpas_wps_start_pbc(wpa_s, _bssid);
172 }
173
174
175 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
176                                              char *cmd, char *buf,
177                                              size_t buflen)
178 {
179         u8 bssid[ETH_ALEN], *_bssid = bssid;
180         char *pin;
181         int ret;
182
183         pin = os_strchr(cmd, ' ');
184         if (pin)
185                 *pin++ = '\0';
186
187         if (os_strcmp(cmd, "any") == 0)
188                 _bssid = NULL;
189         else if (hwaddr_aton(cmd, bssid)) {
190                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
191                            cmd);
192                 return -1;
193         }
194
195 #ifdef CONFIG_AP
196         if (wpa_s->ap_iface)
197                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
198                                                  buf, buflen);
199 #endif /* CONFIG_AP */
200
201         if (pin) {
202                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
203                 if (ret < 0)
204                         return -1;
205                 ret = os_snprintf(buf, buflen, "%s", pin);
206                 if (ret < 0 || (size_t) ret >= buflen)
207                         return -1;
208                 return ret;
209         }
210
211         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL);
212         if (ret < 0)
213                 return -1;
214
215         /* Return the generated PIN */
216         ret = os_snprintf(buf, buflen, "%08d", ret);
217         if (ret < 0 || (size_t) ret >= buflen)
218                 return -1;
219         return ret;
220 }
221
222
223 #ifdef CONFIG_WPS_OOB
224 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
225                                              char *cmd)
226 {
227         char *path, *method, *name;
228
229         path = os_strchr(cmd, ' ');
230         if (path == NULL)
231                 return -1;
232         *path++ = '\0';
233
234         method = os_strchr(path, ' ');
235         if (method == NULL)
236                 return -1;
237         *method++ = '\0';
238
239         name = os_strchr(method, ' ');
240         if (name != NULL)
241                 *name++ = '\0';
242
243         return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
244 }
245 #endif /* CONFIG_WPS_OOB */
246
247
248 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
249                                              char *cmd)
250 {
251         u8 bssid[ETH_ALEN], *_bssid = bssid;
252         char *pin;
253         char *new_ssid;
254         char *new_auth;
255         char *new_encr;
256         char *new_key;
257         struct wps_new_ap_settings ap;
258
259         pin = os_strchr(cmd, ' ');
260         if (pin == NULL)
261                 return -1;
262         *pin++ = '\0';
263
264         if (os_strcmp(cmd, "any") == 0)
265                 _bssid = NULL;
266         else if (hwaddr_aton(cmd, bssid)) {
267                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
268                            cmd);
269                 return -1;
270         }
271
272         new_ssid = os_strchr(pin, ' ');
273         if (new_ssid == NULL)
274                 return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL);
275         *new_ssid++ = '\0';
276
277         new_auth = os_strchr(new_ssid, ' ');
278         if (new_auth == NULL)
279                 return -1;
280         *new_auth++ = '\0';
281
282         new_encr = os_strchr(new_auth, ' ');
283         if (new_encr == NULL)
284                 return -1;
285         *new_encr++ = '\0';
286
287         new_key = os_strchr(new_encr, ' ');
288         if (new_key == NULL)
289                 return -1;
290         *new_key++ = '\0';
291
292         os_memset(&ap, 0, sizeof(ap));
293         ap.ssid_hex = new_ssid;
294         ap.auth = new_auth;
295         ap.encr = new_encr;
296         ap.key_hex = new_key;
297         return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap);
298 }
299
300
301 #ifdef CONFIG_WPS_ER
302 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
303                                                 char *cmd)
304 {
305         char *uuid = cmd, *pin;
306         pin = os_strchr(uuid, ' ');
307         if (pin == NULL)
308                 return -1;
309         *pin++ = '\0';
310         return wpas_wps_er_add_pin(wpa_s, uuid, pin);
311 }
312
313
314 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
315                                                   char *cmd)
316 {
317         char *uuid = cmd, *pin;
318         pin = os_strchr(uuid, ' ');
319         if (pin == NULL)
320                 return -1;
321         *pin++ = '\0';
322         return wpas_wps_er_learn(wpa_s, uuid, pin);
323 }
324 #endif /* CONFIG_WPS_ER */
325
326 #endif /* CONFIG_WPS */
327
328
329 #ifdef CONFIG_IBSS_RSN
330 static int wpa_supplicant_ctrl_iface_ibss_rsn(
331         struct wpa_supplicant *wpa_s, char *addr)
332 {
333         u8 peer[ETH_ALEN];
334
335         if (hwaddr_aton(addr, peer)) {
336                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
337                            "address '%s'", peer);
338                 return -1;
339         }
340
341         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
342                    MAC2STR(peer));
343
344         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
345 }
346 #endif /* CONFIG_IBSS_RSN */
347
348
349 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
350                                               char *rsp)
351 {
352 #ifdef IEEE8021X_EAPOL
353         char *pos, *id_pos;
354         int id;
355         struct wpa_ssid *ssid;
356         struct eap_peer_config *eap;
357
358         pos = os_strchr(rsp, '-');
359         if (pos == NULL)
360                 return -1;
361         *pos++ = '\0';
362         id_pos = pos;
363         pos = os_strchr(pos, ':');
364         if (pos == NULL)
365                 return -1;
366         *pos++ = '\0';
367         id = atoi(id_pos);
368         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
369         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
370                               (u8 *) pos, os_strlen(pos));
371
372         ssid = wpa_config_get_network(wpa_s->conf, id);
373         if (ssid == NULL) {
374                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
375                            "to update", id);
376                 return -1;
377         }
378         eap = &ssid->eap;
379
380         if (os_strcmp(rsp, "IDENTITY") == 0) {
381                 os_free(eap->identity);
382                 eap->identity = (u8 *) os_strdup(pos);
383                 eap->identity_len = os_strlen(pos);
384                 eap->pending_req_identity = 0;
385                 if (ssid == wpa_s->current_ssid)
386                         wpa_s->reassociate = 1;
387         } else if (os_strcmp(rsp, "PASSWORD") == 0) {
388                 os_free(eap->password);
389                 eap->password = (u8 *) os_strdup(pos);
390                 eap->password_len = os_strlen(pos);
391                 eap->pending_req_password = 0;
392                 if (ssid == wpa_s->current_ssid)
393                         wpa_s->reassociate = 1;
394         } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
395                 os_free(eap->new_password);
396                 eap->new_password = (u8 *) os_strdup(pos);
397                 eap->new_password_len = os_strlen(pos);
398                 eap->pending_req_new_password = 0;
399                 if (ssid == wpa_s->current_ssid)
400                         wpa_s->reassociate = 1;
401         } else if (os_strcmp(rsp, "PIN") == 0) {
402                 os_free(eap->pin);
403                 eap->pin = os_strdup(pos);
404                 eap->pending_req_pin = 0;
405                 if (ssid == wpa_s->current_ssid)
406                         wpa_s->reassociate = 1;
407         } else if (os_strcmp(rsp, "OTP") == 0) {
408                 os_free(eap->otp);
409                 eap->otp = (u8 *) os_strdup(pos);
410                 eap->otp_len = os_strlen(pos);
411                 os_free(eap->pending_req_otp);
412                 eap->pending_req_otp = NULL;
413                 eap->pending_req_otp_len = 0;
414         } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
415                 os_free(eap->private_key_passwd);
416                 eap->private_key_passwd = (u8 *) os_strdup(pos);
417                 eap->pending_req_passphrase = 0;
418                 if (ssid == wpa_s->current_ssid)
419                         wpa_s->reassociate = 1;
420         } else {
421                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
422                 return -1;
423         }
424
425         return 0;
426 #else /* IEEE8021X_EAPOL */
427         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
428         return -1;
429 #endif /* IEEE8021X_EAPOL */
430 }
431
432
433 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
434                                             const char *params,
435                                             char *buf, size_t buflen)
436 {
437         char *pos, *end, tmp[30];
438         int res, verbose, ret;
439
440         verbose = os_strcmp(params, "-VERBOSE") == 0;
441         pos = buf;
442         end = buf + buflen;
443         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
444                 struct wpa_ssid *ssid = wpa_s->current_ssid;
445                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
446                                   MAC2STR(wpa_s->bssid));
447                 if (ret < 0 || ret >= end - pos)
448                         return pos - buf;
449                 pos += ret;
450                 if (ssid) {
451                         u8 *_ssid = ssid->ssid;
452                         size_t ssid_len = ssid->ssid_len;
453                         u8 ssid_buf[MAX_SSID_LEN];
454                         if (ssid_len == 0) {
455                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
456                                 if (_res < 0)
457                                         ssid_len = 0;
458                                 else
459                                         ssid_len = _res;
460                                 _ssid = ssid_buf;
461                         }
462                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
463                                           wpa_ssid_txt(_ssid, ssid_len),
464                                           ssid->id);
465                         if (ret < 0 || ret >= end - pos)
466                                 return pos - buf;
467                         pos += ret;
468
469                         if (ssid->id_str) {
470                                 ret = os_snprintf(pos, end - pos,
471                                                   "id_str=%s\n",
472                                                   ssid->id_str);
473                                 if (ret < 0 || ret >= end - pos)
474                                         return pos - buf;
475                                 pos += ret;
476                         }
477
478                         switch (ssid->mode) {
479                         case 0:
480                                 ret = os_snprintf(pos, end - pos,
481                                                   "mode=station\n");
482                                 break;
483                         case 1:
484                                 ret = os_snprintf(pos, end - pos,
485                                                   "mode=IBSS\n");
486                                 break;
487                         case 2:
488                                 ret = os_snprintf(pos, end - pos,
489                                                   "mode=AP\n");
490                                 break;
491                         default:
492                                 ret = 0;
493                                 break;
494                         }
495                         if (ret < 0 || ret >= end - pos)
496                                 return pos - buf;
497                         pos += ret;
498                 }
499
500 #ifdef CONFIG_AP
501                 if (wpa_s->ap_iface) {
502                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
503                                                             end - pos,
504                                                             verbose);
505                 } else
506 #endif /* CONFIG_AP */
507                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
508         }
509         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
510                           wpa_supplicant_state_txt(wpa_s->wpa_state));
511         if (ret < 0 || ret >= end - pos)
512                 return pos - buf;
513         pos += ret;
514
515         if (wpa_s->l2 &&
516             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
517                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
518                 if (ret < 0 || ret >= end - pos)
519                         return pos - buf;
520                 pos += ret;
521         }
522
523         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
524             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
525                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
526                                           verbose);
527                 if (res >= 0)
528                         pos += res;
529         }
530
531         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
532         if (res >= 0)
533                 pos += res;
534
535         return pos - buf;
536 }
537
538
539 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
540                                            char *cmd)
541 {
542         char *pos;
543         int id;
544         struct wpa_ssid *ssid;
545         u8 bssid[ETH_ALEN];
546
547         /* cmd: "<network id> <BSSID>" */
548         pos = os_strchr(cmd, ' ');
549         if (pos == NULL)
550                 return -1;
551         *pos++ = '\0';
552         id = atoi(cmd);
553         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
554         if (hwaddr_aton(pos, bssid)) {
555                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
556                 return -1;
557         }
558
559         ssid = wpa_config_get_network(wpa_s->conf, id);
560         if (ssid == NULL) {
561                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
562                            "to update", id);
563                 return -1;
564         }
565
566         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
567         ssid->bssid_set = !is_zero_ether_addr(bssid);
568
569         return 0;
570 }
571
572
573 static int wpa_supplicant_ctrl_iface_list_networks(
574         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
575 {
576         char *pos, *end;
577         struct wpa_ssid *ssid;
578         int ret;
579
580         pos = buf;
581         end = buf + buflen;
582         ret = os_snprintf(pos, end - pos,
583                           "network id / ssid / bssid / flags\n");
584         if (ret < 0 || ret >= end - pos)
585                 return pos - buf;
586         pos += ret;
587
588         ssid = wpa_s->conf->ssid;
589         while (ssid) {
590                 ret = os_snprintf(pos, end - pos, "%d\t%s",
591                                   ssid->id,
592                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
593                 if (ret < 0 || ret >= end - pos)
594                         return pos - buf;
595                 pos += ret;
596                 if (ssid->bssid_set) {
597                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
598                                           MAC2STR(ssid->bssid));
599                 } else {
600                         ret = os_snprintf(pos, end - pos, "\tany");
601                 }
602                 if (ret < 0 || ret >= end - pos)
603                         return pos - buf;
604                 pos += ret;
605                 ret = os_snprintf(pos, end - pos, "\t%s%s",
606                                   ssid == wpa_s->current_ssid ?
607                                   "[CURRENT]" : "",
608                                   ssid->disabled ? "[DISABLED]" : "");
609                 if (ret < 0 || ret >= end - pos)
610                         return pos - buf;
611                 pos += ret;
612                 ret = os_snprintf(pos, end - pos, "\n");
613                 if (ret < 0 || ret >= end - pos)
614                         return pos - buf;
615                 pos += ret;
616
617                 ssid = ssid->next;
618         }
619
620         return pos - buf;
621 }
622
623
624 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
625 {
626         int first = 1, ret;
627         ret = os_snprintf(pos, end - pos, "-");
628         if (ret < 0 || ret >= end - pos)
629                 return pos;
630         pos += ret;
631         if (cipher & WPA_CIPHER_NONE) {
632                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
633                 if (ret < 0 || ret >= end - pos)
634                         return pos;
635                 pos += ret;
636                 first = 0;
637         }
638         if (cipher & WPA_CIPHER_WEP40) {
639                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
640                 if (ret < 0 || ret >= end - pos)
641                         return pos;
642                 pos += ret;
643                 first = 0;
644         }
645         if (cipher & WPA_CIPHER_WEP104) {
646                 ret = os_snprintf(pos, end - pos, "%sWEP104",
647                                   first ? "" : "+");
648                 if (ret < 0 || ret >= end - pos)
649                         return pos;
650                 pos += ret;
651                 first = 0;
652         }
653         if (cipher & WPA_CIPHER_TKIP) {
654                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
655                 if (ret < 0 || ret >= end - pos)
656                         return pos;
657                 pos += ret;
658                 first = 0;
659         }
660         if (cipher & WPA_CIPHER_CCMP) {
661                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
662                 if (ret < 0 || ret >= end - pos)
663                         return pos;
664                 pos += ret;
665                 first = 0;
666         }
667         return pos;
668 }
669
670
671 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
672                                     const u8 *ie, size_t ie_len)
673 {
674         struct wpa_ie_data data;
675         int first, ret;
676
677         ret = os_snprintf(pos, end - pos, "[%s-", proto);
678         if (ret < 0 || ret >= end - pos)
679                 return pos;
680         pos += ret;
681
682         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
683                 ret = os_snprintf(pos, end - pos, "?]");
684                 if (ret < 0 || ret >= end - pos)
685                         return pos;
686                 pos += ret;
687                 return pos;
688         }
689
690         first = 1;
691         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
692                 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
693                 if (ret < 0 || ret >= end - pos)
694                         return pos;
695                 pos += ret;
696                 first = 0;
697         }
698         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
699                 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
700                 if (ret < 0 || ret >= end - pos)
701                         return pos;
702                 pos += ret;
703                 first = 0;
704         }
705         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
706                 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
707                 if (ret < 0 || ret >= end - pos)
708                         return pos;
709                 pos += ret;
710                 first = 0;
711         }
712 #ifdef CONFIG_IEEE80211R
713         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
714                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
715                                   first ? "" : "+");
716                 if (ret < 0 || ret >= end - pos)
717                         return pos;
718                 pos += ret;
719                 first = 0;
720         }
721         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
722                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
723                                   first ? "" : "+");
724                 if (ret < 0 || ret >= end - pos)
725                         return pos;
726                 pos += ret;
727                 first = 0;
728         }
729 #endif /* CONFIG_IEEE80211R */
730 #ifdef CONFIG_IEEE80211W
731         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
732                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
733                                   first ? "" : "+");
734                 if (ret < 0 || ret >= end - pos)
735                         return pos;
736                 pos += ret;
737                 first = 0;
738         }
739         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
740                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
741                                   first ? "" : "+");
742                 if (ret < 0 || ret >= end - pos)
743                         return pos;
744                 pos += ret;
745                 first = 0;
746         }
747 #endif /* CONFIG_IEEE80211W */
748
749         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
750
751         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
752                 ret = os_snprintf(pos, end - pos, "-preauth");
753                 if (ret < 0 || ret >= end - pos)
754                         return pos;
755                 pos += ret;
756         }
757
758         ret = os_snprintf(pos, end - pos, "]");
759         if (ret < 0 || ret >= end - pos)
760                 return pos;
761         pos += ret;
762
763         return pos;
764 }
765
766
767 #ifdef CONFIG_WPS
768 static char * wpa_supplicant_wps_ie_txt_buf(char *pos, char *end,
769                                             struct wpabuf *wps_ie)
770 {
771         int ret;
772         const char *txt;
773
774         if (wps_ie == NULL)
775                 return pos;
776         if (wps_is_selected_pbc_registrar(wps_ie))
777                 txt = "[WPS-PBC]";
778         else if (wps_is_selected_pin_registrar(wps_ie))
779                 txt = "[WPS-PIN]";
780         else
781                 txt = "[WPS]";
782
783         ret = os_snprintf(pos, end - pos, "%s", txt);
784         if (ret >= 0 && ret < end - pos)
785                 pos += ret;
786         wpabuf_free(wps_ie);
787         return pos;
788 }
789 #endif /* CONFIG_WPS */
790
791
792 static char * wpa_supplicant_wps_ie_txt(char *pos, char *end,
793                                         const struct wpa_scan_res *res)
794 {
795 #ifdef CONFIG_WPS
796         struct wpabuf *wps_ie;
797         wps_ie = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
798         return wpa_supplicant_wps_ie_txt_buf(pos, end, wps_ie);
799 #else /* CONFIG_WPS */
800         return pos;
801 #endif /* CONFIG_WPS */
802 }
803
804
805 static char * wpa_supplicant_wps_ie_txt_bss(char *pos, char *end,
806                                             const struct wpa_bss *bss)
807 {
808 #ifdef CONFIG_WPS
809         struct wpabuf *wps_ie;
810         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
811         return wpa_supplicant_wps_ie_txt_buf(pos, end, wps_ie);
812 #else /* CONFIG_WPS */
813         return pos;
814 #endif /* CONFIG_WPS */
815 }
816
817
818 /* Format one result on one text line into a buffer. */
819 static int wpa_supplicant_ctrl_iface_scan_result(
820         const struct wpa_scan_res *res, char *buf, size_t buflen)
821 {
822         char *pos, *end;
823         int ret;
824         const u8 *ie, *ie2;
825
826         pos = buf;
827         end = buf + buflen;
828
829         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
830                           MAC2STR(res->bssid), res->freq, res->level);
831         if (ret < 0 || ret >= end - pos)
832                 return pos - buf;
833         pos += ret;
834         ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
835         if (ie)
836                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
837         ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN);
838         if (ie2)
839                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
840         pos = wpa_supplicant_wps_ie_txt(pos, end, res);
841         if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) {
842                 ret = os_snprintf(pos, end - pos, "[WEP]");
843                 if (ret < 0 || ret >= end - pos)
844                         return pos - buf;
845                 pos += ret;
846         }
847         if (res->caps & IEEE80211_CAP_IBSS) {
848                 ret = os_snprintf(pos, end - pos, "[IBSS]");
849                 if (ret < 0 || ret >= end - pos)
850                         return pos - buf;
851                 pos += ret;
852         }
853         if (res->caps & IEEE80211_CAP_ESS) {
854                 ret = os_snprintf(pos, end - pos, "[ESS]");
855                 if (ret < 0 || ret >= end - pos)
856                         return pos - buf;
857                 pos += ret;
858         }
859
860         ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
861         ret = os_snprintf(pos, end - pos, "\t%s",
862                           ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
863         if (ret < 0 || ret >= end - pos)
864                 return pos - buf;
865         pos += ret;
866
867         ret = os_snprintf(pos, end - pos, "\n");
868         if (ret < 0 || ret >= end - pos)
869                 return pos - buf;
870         pos += ret;
871
872         return pos - buf;
873 }
874
875
876 static int wpa_supplicant_ctrl_iface_scan_results(
877         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
878 {
879         char *pos, *end;
880         struct wpa_scan_res *res;
881         int ret;
882         size_t i;
883
884         if (wpa_s->scan_res == NULL &&
885             wpa_supplicant_get_scan_results(wpa_s) < 0)
886                 return 0;
887
888         pos = buf;
889         end = buf + buflen;
890         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
891                           "flags / ssid\n");
892         if (ret < 0 || ret >= end - pos)
893                 return pos - buf;
894         pos += ret;
895
896         for (i = 0; i < wpa_s->scan_res->num; i++) {
897                 res = wpa_s->scan_res->res[i];
898                 ret = wpa_supplicant_ctrl_iface_scan_result(res, pos,
899                                                             end - pos);
900                 if (ret < 0 || ret >= end - pos)
901                         return pos - buf;
902                 pos += ret;
903         }
904
905         return pos - buf;
906 }
907
908
909 static int wpa_supplicant_ctrl_iface_select_network(
910         struct wpa_supplicant *wpa_s, char *cmd)
911 {
912         int id;
913         struct wpa_ssid *ssid;
914
915         /* cmd: "<network id>" or "any" */
916         if (os_strcmp(cmd, "any") == 0) {
917                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
918                 ssid = NULL;
919         } else {
920                 id = atoi(cmd);
921                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
922
923                 ssid = wpa_config_get_network(wpa_s->conf, id);
924                 if (ssid == NULL) {
925                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
926                                    "network id=%d", id);
927                         return -1;
928                 }
929         }
930
931         wpa_supplicant_select_network(wpa_s, ssid);
932
933         return 0;
934 }
935
936
937 static int wpa_supplicant_ctrl_iface_enable_network(
938         struct wpa_supplicant *wpa_s, char *cmd)
939 {
940         int id;
941         struct wpa_ssid *ssid;
942
943         /* cmd: "<network id>" or "all" */
944         if (os_strcmp(cmd, "all") == 0) {
945                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
946                 ssid = NULL;
947         } else {
948                 id = atoi(cmd);
949                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
950
951                 ssid = wpa_config_get_network(wpa_s->conf, id);
952                 if (ssid == NULL) {
953                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
954                                    "network id=%d", id);
955                         return -1;
956                 }
957         }
958         wpa_supplicant_enable_network(wpa_s, ssid);
959
960         return 0;
961 }
962
963
964 static int wpa_supplicant_ctrl_iface_disable_network(
965         struct wpa_supplicant *wpa_s, char *cmd)
966 {
967         int id;
968         struct wpa_ssid *ssid;
969
970         /* cmd: "<network id>" or "all" */
971         if (os_strcmp(cmd, "all") == 0) {
972                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
973                 ssid = NULL;
974         } else {
975                 id = atoi(cmd);
976                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
977
978                 ssid = wpa_config_get_network(wpa_s->conf, id);
979                 if (ssid == NULL) {
980                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
981                                    "network id=%d", id);
982                         return -1;
983                 }
984         }
985         wpa_supplicant_disable_network(wpa_s, ssid);
986
987         return 0;
988 }
989
990
991 static int wpa_supplicant_ctrl_iface_add_network(
992         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
993 {
994         struct wpa_ssid *ssid;
995         int ret;
996
997         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
998
999         ssid = wpa_config_add_network(wpa_s->conf);
1000         if (ssid == NULL)
1001                 return -1;
1002
1003         wpas_notify_network_added(wpa_s, ssid);
1004
1005         ssid->disabled = 1;
1006         wpa_config_set_network_defaults(ssid);
1007
1008         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1009         if (ret < 0 || (size_t) ret >= buflen)
1010                 return -1;
1011         return ret;
1012 }
1013
1014
1015 static int wpa_supplicant_ctrl_iface_remove_network(
1016         struct wpa_supplicant *wpa_s, char *cmd)
1017 {
1018         int id;
1019         struct wpa_ssid *ssid;
1020
1021         /* cmd: "<network id>" or "all" */
1022         if (os_strcmp(cmd, "all") == 0) {
1023                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1024                 ssid = wpa_s->conf->ssid;
1025                 while (ssid) {
1026                         struct wpa_ssid *remove_ssid = ssid;
1027                         id = ssid->id;
1028                         ssid = ssid->next;
1029                         wpas_notify_network_removed(wpa_s, remove_ssid);
1030                         wpa_config_remove_network(wpa_s->conf, id);
1031                 }
1032                 if (wpa_s->current_ssid) {
1033                         eapol_sm_invalidate_cached_session(wpa_s->eapol);
1034                         wpa_supplicant_disassociate(wpa_s,
1035                                                     WLAN_REASON_DEAUTH_LEAVING);
1036                 }
1037                 return 0;
1038         }
1039
1040         id = atoi(cmd);
1041         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1042
1043         ssid = wpa_config_get_network(wpa_s->conf, id);
1044         if (ssid == NULL ||
1045             wpa_config_remove_network(wpa_s->conf, id) < 0) {
1046                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1047                            "id=%d", id);
1048                 return -1;
1049         }
1050
1051         if (ssid == wpa_s->current_ssid) {
1052                 /*
1053                  * Invalidate the EAP session cache if the current network is
1054                  * removed.
1055                  */
1056                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1057
1058                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1059         }
1060
1061         return 0;
1062 }
1063
1064
1065 static int wpa_supplicant_ctrl_iface_set_network(
1066         struct wpa_supplicant *wpa_s, char *cmd)
1067 {
1068         int id;
1069         struct wpa_ssid *ssid;
1070         char *name, *value;
1071
1072         /* cmd: "<network id> <variable name> <value>" */
1073         name = os_strchr(cmd, ' ');
1074         if (name == NULL)
1075                 return -1;
1076         *name++ = '\0';
1077
1078         value = os_strchr(name, ' ');
1079         if (value == NULL)
1080                 return -1;
1081         *value++ = '\0';
1082
1083         id = atoi(cmd);
1084         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1085                    id, name);
1086         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1087                               (u8 *) value, os_strlen(value));
1088
1089         ssid = wpa_config_get_network(wpa_s->conf, id);
1090         if (ssid == NULL) {
1091                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1092                            "id=%d", id);
1093                 return -1;
1094         }
1095
1096         if (wpa_config_set(ssid, name, value, 0) < 0) {
1097                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1098                            "variable '%s'", name);
1099                 return -1;
1100         }
1101
1102         if (wpa_s->current_ssid == ssid) {
1103                 /*
1104                  * Invalidate the EAP session cache if anything in the current
1105                  * configuration changes.
1106                  */
1107                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1108         }
1109
1110         if ((os_strcmp(name, "psk") == 0 &&
1111              value[0] == '"' && ssid->ssid_len) ||
1112             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1113                 wpa_config_update_psk(ssid);
1114
1115         return 0;
1116 }
1117
1118
1119 static int wpa_supplicant_ctrl_iface_get_network(
1120         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1121 {
1122         int id;
1123         size_t res;
1124         struct wpa_ssid *ssid;
1125         char *name, *value;
1126
1127         /* cmd: "<network id> <variable name>" */
1128         name = os_strchr(cmd, ' ');
1129         if (name == NULL || buflen == 0)
1130                 return -1;
1131         *name++ = '\0';
1132
1133         id = atoi(cmd);
1134         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1135                    id, name);
1136
1137         ssid = wpa_config_get_network(wpa_s->conf, id);
1138         if (ssid == NULL) {
1139                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1140                            "id=%d", id);
1141                 return -1;
1142         }
1143
1144         value = wpa_config_get_no_key(ssid, name);
1145         if (value == NULL) {
1146                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1147                            "variable '%s'", name);
1148                 return -1;
1149         }
1150
1151         res = os_strlcpy(buf, value, buflen);
1152         if (res >= buflen) {
1153                 os_free(value);
1154                 return -1;
1155         }
1156
1157         os_free(value);
1158
1159         return res;
1160 }
1161
1162
1163 #ifndef CONFIG_NO_CONFIG_WRITE
1164 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1165 {
1166         int ret;
1167
1168         if (!wpa_s->conf->update_config) {
1169                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1170                            "to update configuration (update_config=0)");
1171                 return -1;
1172         }
1173
1174         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1175         if (ret) {
1176                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1177                            "update configuration");
1178         } else {
1179                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1180                            " updated");
1181         }
1182
1183         return ret;
1184 }
1185 #endif /* CONFIG_NO_CONFIG_WRITE */
1186
1187
1188 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1189                                               struct wpa_driver_capa *capa,
1190                                               char *buf, size_t buflen)
1191 {
1192         int ret, first = 1;
1193         char *pos, *end;
1194         size_t len;
1195
1196         pos = buf;
1197         end = pos + buflen;
1198
1199         if (res < 0) {
1200                 if (strict)
1201                         return 0;
1202                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1203                 if (len >= buflen)
1204                         return -1;
1205                 return len;
1206         }
1207
1208         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1209                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1210                 if (ret < 0 || ret >= end - pos)
1211                         return pos - buf;
1212                 pos += ret;
1213                 first = 0;
1214         }
1215
1216         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1217                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1218                 if (ret < 0 || ret >= end - pos)
1219                         return pos - buf;
1220                 pos += ret;
1221                 first = 0;
1222         }
1223
1224         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1225                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1226                 if (ret < 0 || ret >= end - pos)
1227                         return pos - buf;
1228                 pos += ret;
1229                 first = 0;
1230         }
1231
1232         return pos - buf;
1233 }
1234
1235
1236 static int ctrl_iface_get_capability_group(int res, char *strict,
1237                                            struct wpa_driver_capa *capa,
1238                                            char *buf, size_t buflen)
1239 {
1240         int ret, first = 1;
1241         char *pos, *end;
1242         size_t len;
1243
1244         pos = buf;
1245         end = pos + buflen;
1246
1247         if (res < 0) {
1248                 if (strict)
1249                         return 0;
1250                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1251                 if (len >= buflen)
1252                         return -1;
1253                 return len;
1254         }
1255
1256         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1257                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1258                 if (ret < 0 || ret >= end - pos)
1259                         return pos - buf;
1260                 pos += ret;
1261                 first = 0;
1262         }
1263
1264         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1265                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1266                 if (ret < 0 || ret >= end - pos)
1267                         return pos - buf;
1268                 pos += ret;
1269                 first = 0;
1270         }
1271
1272         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1273                 ret = os_snprintf(pos, end - pos, "%sWEP104",
1274                                   first ? "" : " ");
1275                 if (ret < 0 || ret >= end - pos)
1276                         return pos - buf;
1277                 pos += ret;
1278                 first = 0;
1279         }
1280
1281         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1282                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1283                 if (ret < 0 || ret >= end - pos)
1284                         return pos - buf;
1285                 pos += ret;
1286                 first = 0;
1287         }
1288
1289         return pos - buf;
1290 }
1291
1292
1293 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1294                                               struct wpa_driver_capa *capa,
1295                                               char *buf, size_t buflen)
1296 {
1297         int ret;
1298         char *pos, *end;
1299         size_t len;
1300
1301         pos = buf;
1302         end = pos + buflen;
1303
1304         if (res < 0) {
1305                 if (strict)
1306                         return 0;
1307                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1308                                  "NONE", buflen);
1309                 if (len >= buflen)
1310                         return -1;
1311                 return len;
1312         }
1313
1314         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1315         if (ret < 0 || ret >= end - pos)
1316                 return pos - buf;
1317         pos += ret;
1318
1319         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1320                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1321                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
1322                 if (ret < 0 || ret >= end - pos)
1323                         return pos - buf;
1324                 pos += ret;
1325         }
1326
1327         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1328                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1329                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
1330                 if (ret < 0 || ret >= end - pos)
1331                         return pos - buf;
1332                 pos += ret;
1333         }
1334
1335         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1336                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
1337                 if (ret < 0 || ret >= end - pos)
1338                         return pos - buf;
1339                 pos += ret;
1340         }
1341
1342         return pos - buf;
1343 }
1344
1345
1346 static int ctrl_iface_get_capability_proto(int res, char *strict,
1347                                            struct wpa_driver_capa *capa,
1348                                            char *buf, size_t buflen)
1349 {
1350         int ret, first = 1;
1351         char *pos, *end;
1352         size_t len;
1353
1354         pos = buf;
1355         end = pos + buflen;
1356
1357         if (res < 0) {
1358                 if (strict)
1359                         return 0;
1360                 len = os_strlcpy(buf, "RSN WPA", buflen);
1361                 if (len >= buflen)
1362                         return -1;
1363                 return len;
1364         }
1365
1366         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1367                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1368                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1369                 if (ret < 0 || ret >= end - pos)
1370                         return pos - buf;
1371                 pos += ret;
1372                 first = 0;
1373         }
1374
1375         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1376                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1377                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1378                 if (ret < 0 || ret >= end - pos)
1379                         return pos - buf;
1380                 pos += ret;
1381                 first = 0;
1382         }
1383
1384         return pos - buf;
1385 }
1386
1387
1388 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1389                                               struct wpa_driver_capa *capa,
1390                                               char *buf, size_t buflen)
1391 {
1392         int ret, first = 1;
1393         char *pos, *end;
1394         size_t len;
1395
1396         pos = buf;
1397         end = pos + buflen;
1398
1399         if (res < 0) {
1400                 if (strict)
1401                         return 0;
1402                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1403                 if (len >= buflen)
1404                         return -1;
1405                 return len;
1406         }
1407
1408         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1409                 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1410                 if (ret < 0 || ret >= end - pos)
1411                         return pos - buf;
1412                 pos += ret;
1413                 first = 0;
1414         }
1415
1416         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1417                 ret = os_snprintf(pos, end - pos, "%sSHARED",
1418                                   first ? "" : " ");
1419                 if (ret < 0 || ret >= end - pos)
1420                         return pos - buf;
1421                 pos += ret;
1422                 first = 0;
1423         }
1424
1425         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1426                 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1427                 if (ret < 0 || ret >= end - pos)
1428                         return pos - buf;
1429                 pos += ret;
1430                 first = 0;
1431         }
1432
1433         return pos - buf;
1434 }
1435
1436
1437 static int wpa_supplicant_ctrl_iface_get_capability(
1438         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1439         size_t buflen)
1440 {
1441         struct wpa_driver_capa capa;
1442         int res;
1443         char *strict;
1444         char field[30];
1445         size_t len;
1446
1447         /* Determine whether or not strict checking was requested */
1448         len = os_strlcpy(field, _field, sizeof(field));
1449         if (len >= sizeof(field))
1450                 return -1;
1451         strict = os_strchr(field, ' ');
1452         if (strict != NULL) {
1453                 *strict++ = '\0';
1454                 if (os_strcmp(strict, "strict") != 0)
1455                         return -1;
1456         }
1457
1458         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1459                 field, strict ? strict : "");
1460
1461         if (os_strcmp(field, "eap") == 0) {
1462                 return eap_get_names(buf, buflen);
1463         }
1464
1465         res = wpa_drv_get_capa(wpa_s, &capa);
1466
1467         if (os_strcmp(field, "pairwise") == 0)
1468                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1469                                                           buf, buflen);
1470
1471         if (os_strcmp(field, "group") == 0)
1472                 return ctrl_iface_get_capability_group(res, strict, &capa,
1473                                                        buf, buflen);
1474
1475         if (os_strcmp(field, "key_mgmt") == 0)
1476                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1477                                                           buf, buflen);
1478
1479         if (os_strcmp(field, "proto") == 0)
1480                 return ctrl_iface_get_capability_proto(res, strict, &capa,
1481                                                        buf, buflen);
1482
1483         if (os_strcmp(field, "auth_alg") == 0)
1484                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1485                                                           buf, buflen);
1486
1487         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1488                    field);
1489
1490         return -1;
1491 }
1492
1493
1494 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
1495                                          const char *cmd, char *buf,
1496                                          size_t buflen)
1497 {
1498         u8 bssid[ETH_ALEN];
1499         size_t i;
1500         struct wpa_bss *bss;
1501         int ret;
1502         char *pos, *end;
1503         const u8 *ie, *ie2;
1504
1505         if (os_strcmp(cmd, "FIRST") == 0)
1506                 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
1507         else if (os_strncmp(cmd, "ID-", 3) == 0) {
1508                 i = atoi(cmd + 3);
1509                 bss = wpa_bss_get_id(wpa_s, i);
1510         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
1511                 i = atoi(cmd + 5);
1512                 bss = wpa_bss_get_id(wpa_s, i);
1513                 if (bss) {
1514                         struct dl_list *next = bss->list_id.next;
1515                         if (next == &wpa_s->bss_id)
1516                                 bss = NULL;
1517                         else
1518                                 bss = dl_list_entry(next, struct wpa_bss,
1519                                                     list_id);
1520                 }
1521         } else if (hwaddr_aton(cmd, bssid) == 0)
1522                 bss = wpa_bss_get_bssid(wpa_s, bssid);
1523         else {
1524                 struct wpa_bss *tmp;
1525                 i = atoi(cmd);
1526                 bss = NULL;
1527                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
1528                 {
1529                         if (i-- == 0) {
1530                                 bss = tmp;
1531                                 break;
1532                         }
1533                 }
1534         }
1535
1536         if (bss == NULL)
1537                 return 0;
1538
1539         pos = buf;
1540         end = buf + buflen;
1541         ret = os_snprintf(pos, end - pos,
1542                           "id=%u\n"
1543                           "bssid=" MACSTR "\n"
1544                           "freq=%d\n"
1545                           "beacon_int=%d\n"
1546                           "capabilities=0x%04x\n"
1547                           "qual=%d\n"
1548                           "noise=%d\n"
1549                           "level=%d\n"
1550                           "tsf=%016llu\n"
1551                           "ie=",
1552                           bss->id,
1553                           MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
1554                           bss->caps, bss->qual, bss->noise, bss->level,
1555                           (unsigned long long) bss->tsf);
1556         if (ret < 0 || ret >= end - pos)
1557                 return pos - buf;
1558         pos += ret;
1559
1560         ie = (const u8 *) (bss + 1);
1561         for (i = 0; i < bss->ie_len; i++) {
1562                 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
1563                 if (ret < 0 || ret >= end - pos)
1564                         return pos - buf;
1565                 pos += ret;
1566         }
1567
1568         ret = os_snprintf(pos, end - pos, "\n");
1569         if (ret < 0 || ret >= end - pos)
1570                 return pos - buf;
1571         pos += ret;
1572
1573         ret = os_snprintf(pos, end - pos, "flags=");
1574         if (ret < 0 || ret >= end - pos)
1575                 return pos - buf;
1576         pos += ret;
1577
1578         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1579         if (ie)
1580                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1581         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1582         if (ie2)
1583                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1584         pos = wpa_supplicant_wps_ie_txt_bss(pos, end, bss);
1585         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1586                 ret = os_snprintf(pos, end - pos, "[WEP]");
1587                 if (ret < 0 || ret >= end - pos)
1588                         return pos - buf;
1589                 pos += ret;
1590         }
1591         if (bss->caps & IEEE80211_CAP_IBSS) {
1592                 ret = os_snprintf(pos, end - pos, "[IBSS]");
1593                 if (ret < 0 || ret >= end - pos)
1594                         return pos - buf;
1595                 pos += ret;
1596         }
1597         if (bss->caps & IEEE80211_CAP_ESS) {
1598                 ret = os_snprintf(pos, end - pos, "[ESS]");
1599                 if (ret < 0 || ret >= end - pos)
1600                         return pos - buf;
1601                 pos += ret;
1602         }
1603
1604         ret = os_snprintf(pos, end - pos, "\n");
1605         if (ret < 0 || ret >= end - pos)
1606                 return pos - buf;
1607         pos += ret;
1608
1609         ret = os_snprintf(pos, end - pos, "ssid=%s\n",
1610                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
1611         if (ret < 0 || ret >= end - pos)
1612                 return pos - buf;
1613         pos += ret;
1614
1615 #ifdef CONFIG_WPS
1616         ie = (const u8 *) (bss + 1);
1617         ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
1618         if (ret < 0 || ret >= end - pos)
1619                 return pos - buf;
1620         pos += ret;
1621 #endif /* CONFIG_WPS */
1622
1623         return pos - buf;
1624 }
1625
1626
1627 static int wpa_supplicant_ctrl_iface_ap_scan(
1628         struct wpa_supplicant *wpa_s, char *cmd)
1629 {
1630         int ap_scan = atoi(cmd);
1631         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
1632 }
1633
1634
1635 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
1636                                          char *buf, size_t *resp_len)
1637 {
1638         char *reply;
1639         const int reply_size = 2048;
1640         int ctrl_rsp = 0;
1641         int reply_len;
1642
1643         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
1644             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1645                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
1646                                       (const u8 *) buf, os_strlen(buf));
1647         } else {
1648                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
1649                                   (const u8 *) buf, os_strlen(buf));
1650         }
1651
1652         reply = os_malloc(reply_size);
1653         if (reply == NULL) {
1654                 *resp_len = 1;
1655                 return NULL;
1656         }
1657
1658         os_memcpy(reply, "OK\n", 3);
1659         reply_len = 3;
1660
1661         if (os_strcmp(buf, "PING") == 0) {
1662                 os_memcpy(reply, "PONG\n", 5);
1663                 reply_len = 5;
1664         } else if (os_strcmp(buf, "MIB") == 0) {
1665                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
1666                 if (reply_len >= 0) {
1667                         int res;
1668                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
1669                                                reply_size - reply_len);
1670                         if (res < 0)
1671                                 reply_len = -1;
1672                         else
1673                                 reply_len += res;
1674                 }
1675         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
1676                 reply_len = wpa_supplicant_ctrl_iface_status(
1677                         wpa_s, buf + 6, reply, reply_size);
1678         } else if (os_strcmp(buf, "PMKSA") == 0) {
1679                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
1680                                                     reply_size);
1681         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1682                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
1683                         reply_len = -1;
1684         } else if (os_strcmp(buf, "LOGON") == 0) {
1685                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
1686         } else if (os_strcmp(buf, "LOGOFF") == 0) {
1687                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
1688         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
1689                 wpa_s->disconnected = 0;
1690                 wpa_s->reassociate = 1;
1691                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1692         } else if (os_strcmp(buf, "RECONNECT") == 0) {
1693                 if (wpa_s->disconnected) {
1694                         wpa_s->disconnected = 0;
1695                         wpa_s->reassociate = 1;
1696                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1697                 }
1698 #ifdef IEEE8021X_EAPOL
1699         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
1700                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
1701                         reply_len = -1;
1702 #endif /* IEEE8021X_EAPOL */
1703 #ifdef CONFIG_PEERKEY
1704         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
1705                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
1706                         reply_len = -1;
1707 #endif /* CONFIG_PEERKEY */
1708 #ifdef CONFIG_IEEE80211R
1709         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
1710                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
1711                         reply_len = -1;
1712 #endif /* CONFIG_IEEE80211R */
1713 #ifdef CONFIG_WPS
1714         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
1715                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
1716                         reply_len = -1;
1717         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
1718                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
1719                         reply_len = -1;
1720         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1721                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
1722                                                               reply,
1723                                                               reply_size);
1724 #ifdef CONFIG_WPS_OOB
1725         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
1726                 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
1727                         reply_len = -1;
1728 #endif /* CONFIG_WPS_OOB */
1729         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
1730                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
1731                         reply_len = -1;
1732 #ifdef CONFIG_WPS_ER
1733         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
1734                 if (wpas_wps_er_start(wpa_s))
1735                         reply_len = -1;
1736         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
1737                 if (wpas_wps_er_stop(wpa_s))
1738                         reply_len = -1;
1739         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
1740                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
1741                         reply_len = -1;
1742         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
1743                 if (wpas_wps_er_pbc(wpa_s, buf + 11))
1744                         reply_len = -1;
1745         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
1746                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
1747                         reply_len = -1;
1748 #endif /* CONFIG_WPS_ER */
1749 #endif /* CONFIG_WPS */
1750 #ifdef CONFIG_IBSS_RSN
1751         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
1752                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
1753                         reply_len = -1;
1754 #endif /* CONFIG_IBSS_RSN */
1755         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
1756         {
1757                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
1758                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
1759                         reply_len = -1;
1760                 else
1761                         ctrl_rsp = 1;
1762         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
1763                 if (wpa_supplicant_reload_configuration(wpa_s))
1764                         reply_len = -1;
1765         } else if (os_strcmp(buf, "TERMINATE") == 0) {
1766                 wpa_supplicant_terminate_proc(wpa_s->global);
1767         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
1768                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
1769                         reply_len = -1;
1770         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
1771                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
1772                         wpa_s, reply, reply_size);
1773         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
1774                 wpa_s->reassociate = 0;
1775                 wpa_s->disconnected = 1;
1776                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1777         } else if (os_strcmp(buf, "SCAN") == 0) {
1778                 wpa_s->scan_req = 2;
1779                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1780         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
1781                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
1782                         wpa_s, reply, reply_size);
1783         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
1784                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
1785                         reply_len = -1;
1786         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
1787                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
1788                         reply_len = -1;
1789         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
1790                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
1791                         reply_len = -1;
1792         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
1793                 reply_len = wpa_supplicant_ctrl_iface_add_network(
1794                         wpa_s, reply, reply_size);
1795         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
1796                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
1797                         reply_len = -1;
1798         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1799                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
1800                         reply_len = -1;
1801         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
1802                 reply_len = wpa_supplicant_ctrl_iface_get_network(
1803                         wpa_s, buf + 12, reply, reply_size);
1804 #ifndef CONFIG_NO_CONFIG_WRITE
1805         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
1806                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
1807                         reply_len = -1;
1808 #endif /* CONFIG_NO_CONFIG_WRITE */
1809         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
1810                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
1811                         wpa_s, buf + 15, reply, reply_size);
1812         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
1813                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
1814                         reply_len = -1;
1815         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
1816                 reply_len = wpa_supplicant_global_iface_list(
1817                         wpa_s->global, reply, reply_size);
1818         } else if (os_strcmp(buf, "INTERFACES") == 0) {
1819                 reply_len = wpa_supplicant_global_iface_interfaces(
1820                         wpa_s->global, reply, reply_size);
1821         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
1822                 reply_len = wpa_supplicant_ctrl_iface_bss(
1823                         wpa_s, buf + 4, reply, reply_size);
1824 #ifdef CONFIG_AP
1825         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
1826                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
1827         } else if (os_strncmp(buf, "STA ", 4) == 0) {
1828                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
1829                                               reply_size);
1830         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
1831                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
1832                                                    reply_size);
1833 #endif /* CONFIG_AP */
1834         } else {
1835                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1836                 reply_len = 16;
1837         }
1838
1839         if (reply_len < 0) {
1840                 os_memcpy(reply, "FAIL\n", 5);
1841                 reply_len = 5;
1842         }
1843
1844         if (ctrl_rsp)
1845                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1846
1847         *resp_len = reply_len;
1848         return reply;
1849 }
1850
1851
1852 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
1853                                            char *cmd)
1854 {
1855         struct wpa_interface iface;
1856         char *pos;
1857
1858         /*
1859          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
1860          * TAB<bridge_ifname>
1861          */
1862         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
1863
1864         os_memset(&iface, 0, sizeof(iface));
1865
1866         do {
1867                 iface.ifname = pos = cmd;
1868                 pos = os_strchr(pos, '\t');
1869                 if (pos)
1870                         *pos++ = '\0';
1871                 if (iface.ifname[0] == '\0')
1872                         return -1;
1873                 if (pos == NULL)
1874                         break;
1875
1876                 iface.confname = pos;
1877                 pos = os_strchr(pos, '\t');
1878                 if (pos)
1879                         *pos++ = '\0';
1880                 if (iface.confname[0] == '\0')
1881                         iface.confname = NULL;
1882                 if (pos == NULL)
1883                         break;
1884
1885                 iface.driver = pos;
1886                 pos = os_strchr(pos, '\t');
1887                 if (pos)
1888                         *pos++ = '\0';
1889                 if (iface.driver[0] == '\0')
1890                         iface.driver = NULL;
1891                 if (pos == NULL)
1892                         break;
1893
1894                 iface.ctrl_interface = pos;
1895                 pos = os_strchr(pos, '\t');
1896                 if (pos)
1897                         *pos++ = '\0';
1898                 if (iface.ctrl_interface[0] == '\0')
1899                         iface.ctrl_interface = NULL;
1900                 if (pos == NULL)
1901                         break;
1902
1903                 iface.driver_param = pos;
1904                 pos = os_strchr(pos, '\t');
1905                 if (pos)
1906                         *pos++ = '\0';
1907                 if (iface.driver_param[0] == '\0')
1908                         iface.driver_param = NULL;
1909                 if (pos == NULL)
1910                         break;
1911
1912                 iface.bridge_ifname = pos;
1913                 pos = os_strchr(pos, '\t');
1914                 if (pos)
1915                         *pos++ = '\0';
1916                 if (iface.bridge_ifname[0] == '\0')
1917                         iface.bridge_ifname = NULL;
1918                 if (pos == NULL)
1919                         break;
1920         } while (0);
1921
1922         if (wpa_supplicant_get_iface(global, iface.ifname))
1923                 return -1;
1924
1925         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
1926 }
1927
1928
1929 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
1930                                               char *cmd)
1931 {
1932         struct wpa_supplicant *wpa_s;
1933
1934         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
1935
1936         wpa_s = wpa_supplicant_get_iface(global, cmd);
1937         if (wpa_s == NULL)
1938                 return -1;
1939         return wpa_supplicant_remove_iface(global, wpa_s);
1940 }
1941
1942
1943 static void wpa_free_iface_info(struct wpa_interface_info *iface)
1944 {
1945         struct wpa_interface_info *prev;
1946
1947         while (iface) {
1948                 prev = iface;
1949                 iface = iface->next;
1950
1951                 os_free(prev->ifname);
1952                 os_free(prev->desc);
1953                 os_free(prev);
1954         }
1955 }
1956
1957
1958 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
1959                                             char *buf, int len)
1960 {
1961         int i, res;
1962         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
1963         char *pos, *end;
1964
1965         for (i = 0; wpa_drivers[i]; i++) {
1966                 struct wpa_driver_ops *drv = wpa_drivers[i];
1967                 if (drv->get_interfaces == NULL)
1968                         continue;
1969                 tmp = drv->get_interfaces(global->drv_priv);
1970                 if (tmp == NULL)
1971                         continue;
1972
1973                 if (last == NULL)
1974                         iface = last = tmp;
1975                 else
1976                         last->next = tmp;
1977                 while (last->next)
1978                         last = last->next;
1979         }
1980
1981         pos = buf;
1982         end = buf + len;
1983         for (tmp = iface; tmp; tmp = tmp->next) {
1984                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
1985                                   tmp->drv_name, tmp->ifname,
1986                                   tmp->desc ? tmp->desc : "");
1987                 if (res < 0 || res >= end - pos) {
1988                         *pos = '\0';
1989                         break;
1990                 }
1991                 pos += res;
1992         }
1993
1994         wpa_free_iface_info(iface);
1995
1996         return pos - buf;
1997 }
1998
1999
2000 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
2001                                                   char *buf, int len)
2002 {
2003         int res;
2004         char *pos, *end;
2005         struct wpa_supplicant *wpa_s;
2006
2007         wpa_s = global->ifaces;
2008         pos = buf;
2009         end = buf + len;
2010
2011         while (wpa_s) {
2012                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
2013                 if (res < 0 || res >= end - pos) {
2014                         *pos = '\0';
2015                         break;
2016                 }
2017                 pos += res;
2018                 wpa_s = wpa_s->next;
2019         }
2020         return pos - buf;
2021 }
2022
2023
2024 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
2025                                                 char *buf, size_t *resp_len)
2026 {
2027         char *reply;
2028         const int reply_size = 2048;
2029         int reply_len;
2030
2031         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
2032                           (const u8 *) buf, os_strlen(buf));
2033
2034         reply = os_malloc(reply_size);
2035         if (reply == NULL) {
2036                 *resp_len = 1;
2037                 return NULL;
2038         }
2039
2040         os_memcpy(reply, "OK\n", 3);
2041         reply_len = 3;
2042
2043         if (os_strcmp(buf, "PING") == 0) {
2044                 os_memcpy(reply, "PONG\n", 5);
2045                 reply_len = 5;
2046         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
2047                 if (wpa_supplicant_global_iface_add(global, buf + 14))
2048                         reply_len = -1;
2049         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
2050                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
2051                         reply_len = -1;
2052         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
2053                 reply_len = wpa_supplicant_global_iface_list(
2054                         global, reply, reply_size);
2055         } else if (os_strcmp(buf, "INTERFACES") == 0) {
2056                 reply_len = wpa_supplicant_global_iface_interfaces(
2057                         global, reply, reply_size);
2058         } else if (os_strcmp(buf, "TERMINATE") == 0) {
2059                 wpa_supplicant_terminate_proc(global);
2060         } else {
2061                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2062                 reply_len = 16;
2063         }
2064
2065         if (reply_len < 0) {
2066                 os_memcpy(reply, "FAIL\n", 5);
2067                 reply_len = 5;
2068         }
2069
2070         *resp_len = reply_len;
2071         return reply;
2072 }