Convert ctrl_iface scan_results cmd to use BSS table
[libeap.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 WPAS_MODE_INFRA:
480                                 ret = os_snprintf(pos, end - pos,
481                                                   "mode=station\n");
482                                 break;
483                         case WPAS_MODE_IBSS:
484                                 ret = os_snprintf(pos, end - pos,
485                                                   "mode=IBSS\n");
486                                 break;
487                         case WPAS_MODE_AP:
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_bss *bss)
794 {
795 #ifdef CONFIG_WPS
796         struct wpabuf *wps_ie;
797         wps_ie = wpa_bss_get_vendor_ie_multi(bss, 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 /* Format one result on one text line into a buffer. */
806 static int wpa_supplicant_ctrl_iface_scan_result(
807         const struct wpa_bss *bss, char *buf, size_t buflen)
808 {
809         char *pos, *end;
810         int ret;
811         const u8 *ie, *ie2;
812
813         pos = buf;
814         end = buf + buflen;
815
816         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
817                           MAC2STR(bss->bssid), bss->freq, bss->level);
818         if (ret < 0 || ret >= end - pos)
819                 return pos - buf;
820         pos += ret;
821         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
822         if (ie)
823                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
824         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
825         if (ie2)
826                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
827         pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
828         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
829                 ret = os_snprintf(pos, end - pos, "[WEP]");
830                 if (ret < 0 || ret >= end - pos)
831                         return pos - buf;
832                 pos += ret;
833         }
834         if (bss->caps & IEEE80211_CAP_IBSS) {
835                 ret = os_snprintf(pos, end - pos, "[IBSS]");
836                 if (ret < 0 || ret >= end - pos)
837                         return pos - buf;
838                 pos += ret;
839         }
840         if (bss->caps & IEEE80211_CAP_ESS) {
841                 ret = os_snprintf(pos, end - pos, "[ESS]");
842                 if (ret < 0 || ret >= end - pos)
843                         return pos - buf;
844                 pos += ret;
845         }
846
847         ret = os_snprintf(pos, end - pos, "\t%s",
848                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
849         if (ret < 0 || ret >= end - pos)
850                 return pos - buf;
851         pos += ret;
852
853         ret = os_snprintf(pos, end - pos, "\n");
854         if (ret < 0 || ret >= end - pos)
855                 return pos - buf;
856         pos += ret;
857
858         return pos - buf;
859 }
860
861
862 static int wpa_supplicant_ctrl_iface_scan_results(
863         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
864 {
865         char *pos, *end;
866         struct wpa_bss *bss;
867         int ret;
868
869         pos = buf;
870         end = buf + buflen;
871         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
872                           "flags / ssid\n");
873         if (ret < 0 || ret >= end - pos)
874                 return pos - buf;
875         pos += ret;
876
877         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
878                 ret = wpa_supplicant_ctrl_iface_scan_result(bss, pos,
879                                                             end - pos);
880                 if (ret < 0 || ret >= end - pos)
881                         return pos - buf;
882                 pos += ret;
883         }
884
885         return pos - buf;
886 }
887
888
889 static int wpa_supplicant_ctrl_iface_select_network(
890         struct wpa_supplicant *wpa_s, char *cmd)
891 {
892         int id;
893         struct wpa_ssid *ssid;
894
895         /* cmd: "<network id>" or "any" */
896         if (os_strcmp(cmd, "any") == 0) {
897                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
898                 ssid = NULL;
899         } else {
900                 id = atoi(cmd);
901                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
902
903                 ssid = wpa_config_get_network(wpa_s->conf, id);
904                 if (ssid == NULL) {
905                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
906                                    "network id=%d", id);
907                         return -1;
908                 }
909         }
910
911         wpa_supplicant_select_network(wpa_s, ssid);
912
913         return 0;
914 }
915
916
917 static int wpa_supplicant_ctrl_iface_enable_network(
918         struct wpa_supplicant *wpa_s, char *cmd)
919 {
920         int id;
921         struct wpa_ssid *ssid;
922
923         /* cmd: "<network id>" or "all" */
924         if (os_strcmp(cmd, "all") == 0) {
925                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
926                 ssid = NULL;
927         } else {
928                 id = atoi(cmd);
929                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
930
931                 ssid = wpa_config_get_network(wpa_s->conf, id);
932                 if (ssid == NULL) {
933                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
934                                    "network id=%d", id);
935                         return -1;
936                 }
937         }
938         wpa_supplicant_enable_network(wpa_s, ssid);
939
940         return 0;
941 }
942
943
944 static int wpa_supplicant_ctrl_iface_disable_network(
945         struct wpa_supplicant *wpa_s, char *cmd)
946 {
947         int id;
948         struct wpa_ssid *ssid;
949
950         /* cmd: "<network id>" or "all" */
951         if (os_strcmp(cmd, "all") == 0) {
952                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
953                 ssid = NULL;
954         } else {
955                 id = atoi(cmd);
956                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
957
958                 ssid = wpa_config_get_network(wpa_s->conf, id);
959                 if (ssid == NULL) {
960                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
961                                    "network id=%d", id);
962                         return -1;
963                 }
964         }
965         wpa_supplicant_disable_network(wpa_s, ssid);
966
967         return 0;
968 }
969
970
971 static int wpa_supplicant_ctrl_iface_add_network(
972         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
973 {
974         struct wpa_ssid *ssid;
975         int ret;
976
977         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
978
979         ssid = wpa_config_add_network(wpa_s->conf);
980         if (ssid == NULL)
981                 return -1;
982
983         wpas_notify_network_added(wpa_s, ssid);
984
985         ssid->disabled = 1;
986         wpa_config_set_network_defaults(ssid);
987
988         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
989         if (ret < 0 || (size_t) ret >= buflen)
990                 return -1;
991         return ret;
992 }
993
994
995 static int wpa_supplicant_ctrl_iface_remove_network(
996         struct wpa_supplicant *wpa_s, char *cmd)
997 {
998         int id;
999         struct wpa_ssid *ssid;
1000
1001         /* cmd: "<network id>" or "all" */
1002         if (os_strcmp(cmd, "all") == 0) {
1003                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1004                 ssid = wpa_s->conf->ssid;
1005                 while (ssid) {
1006                         struct wpa_ssid *remove_ssid = ssid;
1007                         id = ssid->id;
1008                         ssid = ssid->next;
1009                         wpas_notify_network_removed(wpa_s, remove_ssid);
1010                         wpa_config_remove_network(wpa_s->conf, id);
1011                 }
1012                 if (wpa_s->current_ssid) {
1013                         eapol_sm_invalidate_cached_session(wpa_s->eapol);
1014                         wpa_supplicant_disassociate(wpa_s,
1015                                                     WLAN_REASON_DEAUTH_LEAVING);
1016                 }
1017                 return 0;
1018         }
1019
1020         id = atoi(cmd);
1021         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1022
1023         ssid = wpa_config_get_network(wpa_s->conf, id);
1024         if (ssid == NULL ||
1025             wpa_config_remove_network(wpa_s->conf, id) < 0) {
1026                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1027                            "id=%d", id);
1028                 return -1;
1029         }
1030
1031         if (ssid == wpa_s->current_ssid) {
1032                 /*
1033                  * Invalidate the EAP session cache if the current network is
1034                  * removed.
1035                  */
1036                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1037
1038                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1039         }
1040
1041         return 0;
1042 }
1043
1044
1045 static int wpa_supplicant_ctrl_iface_set_network(
1046         struct wpa_supplicant *wpa_s, char *cmd)
1047 {
1048         int id;
1049         struct wpa_ssid *ssid;
1050         char *name, *value;
1051
1052         /* cmd: "<network id> <variable name> <value>" */
1053         name = os_strchr(cmd, ' ');
1054         if (name == NULL)
1055                 return -1;
1056         *name++ = '\0';
1057
1058         value = os_strchr(name, ' ');
1059         if (value == NULL)
1060                 return -1;
1061         *value++ = '\0';
1062
1063         id = atoi(cmd);
1064         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1065                    id, name);
1066         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1067                               (u8 *) value, os_strlen(value));
1068
1069         ssid = wpa_config_get_network(wpa_s->conf, id);
1070         if (ssid == NULL) {
1071                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1072                            "id=%d", id);
1073                 return -1;
1074         }
1075
1076         if (wpa_config_set(ssid, name, value, 0) < 0) {
1077                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1078                            "variable '%s'", name);
1079                 return -1;
1080         }
1081
1082         if (wpa_s->current_ssid == ssid) {
1083                 /*
1084                  * Invalidate the EAP session cache if anything in the current
1085                  * configuration changes.
1086                  */
1087                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1088         }
1089
1090         if ((os_strcmp(name, "psk") == 0 &&
1091              value[0] == '"' && ssid->ssid_len) ||
1092             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1093                 wpa_config_update_psk(ssid);
1094
1095         return 0;
1096 }
1097
1098
1099 static int wpa_supplicant_ctrl_iface_get_network(
1100         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1101 {
1102         int id;
1103         size_t res;
1104         struct wpa_ssid *ssid;
1105         char *name, *value;
1106
1107         /* cmd: "<network id> <variable name>" */
1108         name = os_strchr(cmd, ' ');
1109         if (name == NULL || buflen == 0)
1110                 return -1;
1111         *name++ = '\0';
1112
1113         id = atoi(cmd);
1114         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1115                    id, name);
1116
1117         ssid = wpa_config_get_network(wpa_s->conf, id);
1118         if (ssid == NULL) {
1119                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1120                            "id=%d", id);
1121                 return -1;
1122         }
1123
1124         value = wpa_config_get_no_key(ssid, name);
1125         if (value == NULL) {
1126                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1127                            "variable '%s'", name);
1128                 return -1;
1129         }
1130
1131         res = os_strlcpy(buf, value, buflen);
1132         if (res >= buflen) {
1133                 os_free(value);
1134                 return -1;
1135         }
1136
1137         os_free(value);
1138
1139         return res;
1140 }
1141
1142
1143 #ifndef CONFIG_NO_CONFIG_WRITE
1144 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1145 {
1146         int ret;
1147
1148         if (!wpa_s->conf->update_config) {
1149                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1150                            "to update configuration (update_config=0)");
1151                 return -1;
1152         }
1153
1154         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1155         if (ret) {
1156                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1157                            "update configuration");
1158         } else {
1159                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1160                            " updated");
1161         }
1162
1163         return ret;
1164 }
1165 #endif /* CONFIG_NO_CONFIG_WRITE */
1166
1167
1168 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1169                                               struct wpa_driver_capa *capa,
1170                                               char *buf, size_t buflen)
1171 {
1172         int ret, first = 1;
1173         char *pos, *end;
1174         size_t len;
1175
1176         pos = buf;
1177         end = pos + buflen;
1178
1179         if (res < 0) {
1180                 if (strict)
1181                         return 0;
1182                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1183                 if (len >= buflen)
1184                         return -1;
1185                 return len;
1186         }
1187
1188         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1189                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1190                 if (ret < 0 || ret >= end - pos)
1191                         return pos - buf;
1192                 pos += ret;
1193                 first = 0;
1194         }
1195
1196         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1197                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1198                 if (ret < 0 || ret >= end - pos)
1199                         return pos - buf;
1200                 pos += ret;
1201                 first = 0;
1202         }
1203
1204         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1205                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1206                 if (ret < 0 || ret >= end - pos)
1207                         return pos - buf;
1208                 pos += ret;
1209                 first = 0;
1210         }
1211
1212         return pos - buf;
1213 }
1214
1215
1216 static int ctrl_iface_get_capability_group(int res, char *strict,
1217                                            struct wpa_driver_capa *capa,
1218                                            char *buf, size_t buflen)
1219 {
1220         int ret, first = 1;
1221         char *pos, *end;
1222         size_t len;
1223
1224         pos = buf;
1225         end = pos + buflen;
1226
1227         if (res < 0) {
1228                 if (strict)
1229                         return 0;
1230                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1231                 if (len >= buflen)
1232                         return -1;
1233                 return len;
1234         }
1235
1236         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1237                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1238                 if (ret < 0 || ret >= end - pos)
1239                         return pos - buf;
1240                 pos += ret;
1241                 first = 0;
1242         }
1243
1244         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1245                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1246                 if (ret < 0 || ret >= end - pos)
1247                         return pos - buf;
1248                 pos += ret;
1249                 first = 0;
1250         }
1251
1252         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1253                 ret = os_snprintf(pos, end - pos, "%sWEP104",
1254                                   first ? "" : " ");
1255                 if (ret < 0 || ret >= end - pos)
1256                         return pos - buf;
1257                 pos += ret;
1258                 first = 0;
1259         }
1260
1261         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1262                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1263                 if (ret < 0 || ret >= end - pos)
1264                         return pos - buf;
1265                 pos += ret;
1266                 first = 0;
1267         }
1268
1269         return pos - buf;
1270 }
1271
1272
1273 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1274                                               struct wpa_driver_capa *capa,
1275                                               char *buf, size_t buflen)
1276 {
1277         int ret;
1278         char *pos, *end;
1279         size_t len;
1280
1281         pos = buf;
1282         end = pos + buflen;
1283
1284         if (res < 0) {
1285                 if (strict)
1286                         return 0;
1287                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1288                                  "NONE", buflen);
1289                 if (len >= buflen)
1290                         return -1;
1291                 return len;
1292         }
1293
1294         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1295         if (ret < 0 || ret >= end - pos)
1296                 return pos - buf;
1297         pos += ret;
1298
1299         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1300                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1301                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
1302                 if (ret < 0 || ret >= end - pos)
1303                         return pos - buf;
1304                 pos += ret;
1305         }
1306
1307         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1308                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1309                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
1310                 if (ret < 0 || ret >= end - pos)
1311                         return pos - buf;
1312                 pos += ret;
1313         }
1314
1315         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1316                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
1317                 if (ret < 0 || ret >= end - pos)
1318                         return pos - buf;
1319                 pos += ret;
1320         }
1321
1322         return pos - buf;
1323 }
1324
1325
1326 static int ctrl_iface_get_capability_proto(int res, char *strict,
1327                                            struct wpa_driver_capa *capa,
1328                                            char *buf, size_t buflen)
1329 {
1330         int ret, first = 1;
1331         char *pos, *end;
1332         size_t len;
1333
1334         pos = buf;
1335         end = pos + buflen;
1336
1337         if (res < 0) {
1338                 if (strict)
1339                         return 0;
1340                 len = os_strlcpy(buf, "RSN WPA", buflen);
1341                 if (len >= buflen)
1342                         return -1;
1343                 return len;
1344         }
1345
1346         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1347                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1348                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1349                 if (ret < 0 || ret >= end - pos)
1350                         return pos - buf;
1351                 pos += ret;
1352                 first = 0;
1353         }
1354
1355         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1356                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1357                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1358                 if (ret < 0 || ret >= end - pos)
1359                         return pos - buf;
1360                 pos += ret;
1361                 first = 0;
1362         }
1363
1364         return pos - buf;
1365 }
1366
1367
1368 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1369                                               struct wpa_driver_capa *capa,
1370                                               char *buf, size_t buflen)
1371 {
1372         int ret, first = 1;
1373         char *pos, *end;
1374         size_t len;
1375
1376         pos = buf;
1377         end = pos + buflen;
1378
1379         if (res < 0) {
1380                 if (strict)
1381                         return 0;
1382                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1383                 if (len >= buflen)
1384                         return -1;
1385                 return len;
1386         }
1387
1388         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1389                 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1390                 if (ret < 0 || ret >= end - pos)
1391                         return pos - buf;
1392                 pos += ret;
1393                 first = 0;
1394         }
1395
1396         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1397                 ret = os_snprintf(pos, end - pos, "%sSHARED",
1398                                   first ? "" : " ");
1399                 if (ret < 0 || ret >= end - pos)
1400                         return pos - buf;
1401                 pos += ret;
1402                 first = 0;
1403         }
1404
1405         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1406                 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1407                 if (ret < 0 || ret >= end - pos)
1408                         return pos - buf;
1409                 pos += ret;
1410                 first = 0;
1411         }
1412
1413         return pos - buf;
1414 }
1415
1416
1417 static int wpa_supplicant_ctrl_iface_get_capability(
1418         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1419         size_t buflen)
1420 {
1421         struct wpa_driver_capa capa;
1422         int res;
1423         char *strict;
1424         char field[30];
1425         size_t len;
1426
1427         /* Determine whether or not strict checking was requested */
1428         len = os_strlcpy(field, _field, sizeof(field));
1429         if (len >= sizeof(field))
1430                 return -1;
1431         strict = os_strchr(field, ' ');
1432         if (strict != NULL) {
1433                 *strict++ = '\0';
1434                 if (os_strcmp(strict, "strict") != 0)
1435                         return -1;
1436         }
1437
1438         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1439                 field, strict ? strict : "");
1440
1441         if (os_strcmp(field, "eap") == 0) {
1442                 return eap_get_names(buf, buflen);
1443         }
1444
1445         res = wpa_drv_get_capa(wpa_s, &capa);
1446
1447         if (os_strcmp(field, "pairwise") == 0)
1448                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1449                                                           buf, buflen);
1450
1451         if (os_strcmp(field, "group") == 0)
1452                 return ctrl_iface_get_capability_group(res, strict, &capa,
1453                                                        buf, buflen);
1454
1455         if (os_strcmp(field, "key_mgmt") == 0)
1456                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1457                                                           buf, buflen);
1458
1459         if (os_strcmp(field, "proto") == 0)
1460                 return ctrl_iface_get_capability_proto(res, strict, &capa,
1461                                                        buf, buflen);
1462
1463         if (os_strcmp(field, "auth_alg") == 0)
1464                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1465                                                           buf, buflen);
1466
1467         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1468                    field);
1469
1470         return -1;
1471 }
1472
1473
1474 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
1475                                          const char *cmd, char *buf,
1476                                          size_t buflen)
1477 {
1478         u8 bssid[ETH_ALEN];
1479         size_t i;
1480         struct wpa_bss *bss;
1481         int ret;
1482         char *pos, *end;
1483         const u8 *ie, *ie2;
1484
1485         if (os_strcmp(cmd, "FIRST") == 0)
1486                 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
1487         else if (os_strncmp(cmd, "ID-", 3) == 0) {
1488                 i = atoi(cmd + 3);
1489                 bss = wpa_bss_get_id(wpa_s, i);
1490         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
1491                 i = atoi(cmd + 5);
1492                 bss = wpa_bss_get_id(wpa_s, i);
1493                 if (bss) {
1494                         struct dl_list *next = bss->list_id.next;
1495                         if (next == &wpa_s->bss_id)
1496                                 bss = NULL;
1497                         else
1498                                 bss = dl_list_entry(next, struct wpa_bss,
1499                                                     list_id);
1500                 }
1501         } else if (hwaddr_aton(cmd, bssid) == 0)
1502                 bss = wpa_bss_get_bssid(wpa_s, bssid);
1503         else {
1504                 struct wpa_bss *tmp;
1505                 i = atoi(cmd);
1506                 bss = NULL;
1507                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
1508                 {
1509                         if (i-- == 0) {
1510                                 bss = tmp;
1511                                 break;
1512                         }
1513                 }
1514         }
1515
1516         if (bss == NULL)
1517                 return 0;
1518
1519         pos = buf;
1520         end = buf + buflen;
1521         ret = os_snprintf(pos, end - pos,
1522                           "id=%u\n"
1523                           "bssid=" MACSTR "\n"
1524                           "freq=%d\n"
1525                           "beacon_int=%d\n"
1526                           "capabilities=0x%04x\n"
1527                           "qual=%d\n"
1528                           "noise=%d\n"
1529                           "level=%d\n"
1530                           "tsf=%016llu\n"
1531                           "ie=",
1532                           bss->id,
1533                           MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
1534                           bss->caps, bss->qual, bss->noise, bss->level,
1535                           (unsigned long long) bss->tsf);
1536         if (ret < 0 || ret >= end - pos)
1537                 return pos - buf;
1538         pos += ret;
1539
1540         ie = (const u8 *) (bss + 1);
1541         for (i = 0; i < bss->ie_len; i++) {
1542                 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
1543                 if (ret < 0 || ret >= end - pos)
1544                         return pos - buf;
1545                 pos += ret;
1546         }
1547
1548         ret = os_snprintf(pos, end - pos, "\n");
1549         if (ret < 0 || ret >= end - pos)
1550                 return pos - buf;
1551         pos += ret;
1552
1553         ret = os_snprintf(pos, end - pos, "flags=");
1554         if (ret < 0 || ret >= end - pos)
1555                 return pos - buf;
1556         pos += ret;
1557
1558         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1559         if (ie)
1560                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1561         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1562         if (ie2)
1563                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1564         pos = wpa_supplicant_wps_ie_txt(pos, end, bss);
1565         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1566                 ret = os_snprintf(pos, end - pos, "[WEP]");
1567                 if (ret < 0 || ret >= end - pos)
1568                         return pos - buf;
1569                 pos += ret;
1570         }
1571         if (bss->caps & IEEE80211_CAP_IBSS) {
1572                 ret = os_snprintf(pos, end - pos, "[IBSS]");
1573                 if (ret < 0 || ret >= end - pos)
1574                         return pos - buf;
1575                 pos += ret;
1576         }
1577         if (bss->caps & IEEE80211_CAP_ESS) {
1578                 ret = os_snprintf(pos, end - pos, "[ESS]");
1579                 if (ret < 0 || ret >= end - pos)
1580                         return pos - buf;
1581                 pos += ret;
1582         }
1583
1584         ret = os_snprintf(pos, end - pos, "\n");
1585         if (ret < 0 || ret >= end - pos)
1586                 return pos - buf;
1587         pos += ret;
1588
1589         ret = os_snprintf(pos, end - pos, "ssid=%s\n",
1590                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
1591         if (ret < 0 || ret >= end - pos)
1592                 return pos - buf;
1593         pos += ret;
1594
1595 #ifdef CONFIG_WPS
1596         ie = (const u8 *) (bss + 1);
1597         ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
1598         if (ret < 0 || ret >= end - pos)
1599                 return pos - buf;
1600         pos += ret;
1601 #endif /* CONFIG_WPS */
1602
1603         return pos - buf;
1604 }
1605
1606
1607 static int wpa_supplicant_ctrl_iface_ap_scan(
1608         struct wpa_supplicant *wpa_s, char *cmd)
1609 {
1610         int ap_scan = atoi(cmd);
1611         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
1612 }
1613
1614
1615 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
1616                                          char *buf, size_t *resp_len)
1617 {
1618         char *reply;
1619         const int reply_size = 2048;
1620         int ctrl_rsp = 0;
1621         int reply_len;
1622
1623         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
1624             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1625                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
1626                                       (const u8 *) buf, os_strlen(buf));
1627         } else {
1628                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
1629                                   (const u8 *) buf, os_strlen(buf));
1630         }
1631
1632         reply = os_malloc(reply_size);
1633         if (reply == NULL) {
1634                 *resp_len = 1;
1635                 return NULL;
1636         }
1637
1638         os_memcpy(reply, "OK\n", 3);
1639         reply_len = 3;
1640
1641         if (os_strcmp(buf, "PING") == 0) {
1642                 os_memcpy(reply, "PONG\n", 5);
1643                 reply_len = 5;
1644         } else if (os_strcmp(buf, "MIB") == 0) {
1645                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
1646                 if (reply_len >= 0) {
1647                         int res;
1648                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
1649                                                reply_size - reply_len);
1650                         if (res < 0)
1651                                 reply_len = -1;
1652                         else
1653                                 reply_len += res;
1654                 }
1655         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
1656                 reply_len = wpa_supplicant_ctrl_iface_status(
1657                         wpa_s, buf + 6, reply, reply_size);
1658         } else if (os_strcmp(buf, "PMKSA") == 0) {
1659                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
1660                                                     reply_size);
1661         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1662                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
1663                         reply_len = -1;
1664         } else if (os_strcmp(buf, "LOGON") == 0) {
1665                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
1666         } else if (os_strcmp(buf, "LOGOFF") == 0) {
1667                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
1668         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
1669                 wpa_s->disconnected = 0;
1670                 wpa_s->reassociate = 1;
1671                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1672         } else if (os_strcmp(buf, "RECONNECT") == 0) {
1673                 if (wpa_s->disconnected) {
1674                         wpa_s->disconnected = 0;
1675                         wpa_s->reassociate = 1;
1676                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1677                 }
1678 #ifdef IEEE8021X_EAPOL
1679         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
1680                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
1681                         reply_len = -1;
1682 #endif /* IEEE8021X_EAPOL */
1683 #ifdef CONFIG_PEERKEY
1684         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
1685                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
1686                         reply_len = -1;
1687 #endif /* CONFIG_PEERKEY */
1688 #ifdef CONFIG_IEEE80211R
1689         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
1690                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
1691                         reply_len = -1;
1692 #endif /* CONFIG_IEEE80211R */
1693 #ifdef CONFIG_WPS
1694         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
1695                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
1696                         reply_len = -1;
1697         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
1698                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
1699                         reply_len = -1;
1700         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
1701                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
1702                                                               reply,
1703                                                               reply_size);
1704 #ifdef CONFIG_WPS_OOB
1705         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
1706                 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
1707                         reply_len = -1;
1708 #endif /* CONFIG_WPS_OOB */
1709         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
1710                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
1711                         reply_len = -1;
1712 #ifdef CONFIG_WPS_ER
1713         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
1714                 if (wpas_wps_er_start(wpa_s))
1715                         reply_len = -1;
1716         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
1717                 if (wpas_wps_er_stop(wpa_s))
1718                         reply_len = -1;
1719         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
1720                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
1721                         reply_len = -1;
1722         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
1723                 if (wpas_wps_er_pbc(wpa_s, buf + 11))
1724                         reply_len = -1;
1725         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
1726                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
1727                         reply_len = -1;
1728 #endif /* CONFIG_WPS_ER */
1729 #endif /* CONFIG_WPS */
1730 #ifdef CONFIG_IBSS_RSN
1731         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
1732                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
1733                         reply_len = -1;
1734 #endif /* CONFIG_IBSS_RSN */
1735         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
1736         {
1737                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
1738                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
1739                         reply_len = -1;
1740                 else
1741                         ctrl_rsp = 1;
1742         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
1743                 if (wpa_supplicant_reload_configuration(wpa_s))
1744                         reply_len = -1;
1745         } else if (os_strcmp(buf, "TERMINATE") == 0) {
1746                 wpa_supplicant_terminate_proc(wpa_s->global);
1747         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
1748                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
1749                         reply_len = -1;
1750         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
1751                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
1752                         wpa_s, reply, reply_size);
1753         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
1754                 wpa_s->reassociate = 0;
1755                 wpa_s->disconnected = 1;
1756                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1757         } else if (os_strcmp(buf, "SCAN") == 0) {
1758                 wpa_s->scan_req = 2;
1759                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1760         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
1761                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
1762                         wpa_s, reply, reply_size);
1763         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
1764                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
1765                         reply_len = -1;
1766         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
1767                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
1768                         reply_len = -1;
1769         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
1770                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
1771                         reply_len = -1;
1772         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
1773                 reply_len = wpa_supplicant_ctrl_iface_add_network(
1774                         wpa_s, reply, reply_size);
1775         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
1776                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
1777                         reply_len = -1;
1778         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1779                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
1780                         reply_len = -1;
1781         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
1782                 reply_len = wpa_supplicant_ctrl_iface_get_network(
1783                         wpa_s, buf + 12, reply, reply_size);
1784 #ifndef CONFIG_NO_CONFIG_WRITE
1785         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
1786                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
1787                         reply_len = -1;
1788 #endif /* CONFIG_NO_CONFIG_WRITE */
1789         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
1790                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
1791                         wpa_s, buf + 15, reply, reply_size);
1792         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
1793                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
1794                         reply_len = -1;
1795         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
1796                 reply_len = wpa_supplicant_global_iface_list(
1797                         wpa_s->global, reply, reply_size);
1798         } else if (os_strcmp(buf, "INTERFACES") == 0) {
1799                 reply_len = wpa_supplicant_global_iface_interfaces(
1800                         wpa_s->global, reply, reply_size);
1801         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
1802                 reply_len = wpa_supplicant_ctrl_iface_bss(
1803                         wpa_s, buf + 4, reply, reply_size);
1804 #ifdef CONFIG_AP
1805         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
1806                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
1807         } else if (os_strncmp(buf, "STA ", 4) == 0) {
1808                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
1809                                               reply_size);
1810         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
1811                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
1812                                                    reply_size);
1813 #endif /* CONFIG_AP */
1814         } else {
1815                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1816                 reply_len = 16;
1817         }
1818
1819         if (reply_len < 0) {
1820                 os_memcpy(reply, "FAIL\n", 5);
1821                 reply_len = 5;
1822         }
1823
1824         if (ctrl_rsp)
1825                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1826
1827         *resp_len = reply_len;
1828         return reply;
1829 }
1830
1831
1832 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
1833                                            char *cmd)
1834 {
1835         struct wpa_interface iface;
1836         char *pos;
1837
1838         /*
1839          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
1840          * TAB<bridge_ifname>
1841          */
1842         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
1843
1844         os_memset(&iface, 0, sizeof(iface));
1845
1846         do {
1847                 iface.ifname = pos = cmd;
1848                 pos = os_strchr(pos, '\t');
1849                 if (pos)
1850                         *pos++ = '\0';
1851                 if (iface.ifname[0] == '\0')
1852                         return -1;
1853                 if (pos == NULL)
1854                         break;
1855
1856                 iface.confname = pos;
1857                 pos = os_strchr(pos, '\t');
1858                 if (pos)
1859                         *pos++ = '\0';
1860                 if (iface.confname[0] == '\0')
1861                         iface.confname = NULL;
1862                 if (pos == NULL)
1863                         break;
1864
1865                 iface.driver = pos;
1866                 pos = os_strchr(pos, '\t');
1867                 if (pos)
1868                         *pos++ = '\0';
1869                 if (iface.driver[0] == '\0')
1870                         iface.driver = NULL;
1871                 if (pos == NULL)
1872                         break;
1873
1874                 iface.ctrl_interface = pos;
1875                 pos = os_strchr(pos, '\t');
1876                 if (pos)
1877                         *pos++ = '\0';
1878                 if (iface.ctrl_interface[0] == '\0')
1879                         iface.ctrl_interface = NULL;
1880                 if (pos == NULL)
1881                         break;
1882
1883                 iface.driver_param = pos;
1884                 pos = os_strchr(pos, '\t');
1885                 if (pos)
1886                         *pos++ = '\0';
1887                 if (iface.driver_param[0] == '\0')
1888                         iface.driver_param = NULL;
1889                 if (pos == NULL)
1890                         break;
1891
1892                 iface.bridge_ifname = pos;
1893                 pos = os_strchr(pos, '\t');
1894                 if (pos)
1895                         *pos++ = '\0';
1896                 if (iface.bridge_ifname[0] == '\0')
1897                         iface.bridge_ifname = NULL;
1898                 if (pos == NULL)
1899                         break;
1900         } while (0);
1901
1902         if (wpa_supplicant_get_iface(global, iface.ifname))
1903                 return -1;
1904
1905         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
1906 }
1907
1908
1909 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
1910                                               char *cmd)
1911 {
1912         struct wpa_supplicant *wpa_s;
1913
1914         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
1915
1916         wpa_s = wpa_supplicant_get_iface(global, cmd);
1917         if (wpa_s == NULL)
1918                 return -1;
1919         return wpa_supplicant_remove_iface(global, wpa_s);
1920 }
1921
1922
1923 static void wpa_free_iface_info(struct wpa_interface_info *iface)
1924 {
1925         struct wpa_interface_info *prev;
1926
1927         while (iface) {
1928                 prev = iface;
1929                 iface = iface->next;
1930
1931                 os_free(prev->ifname);
1932                 os_free(prev->desc);
1933                 os_free(prev);
1934         }
1935 }
1936
1937
1938 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
1939                                             char *buf, int len)
1940 {
1941         int i, res;
1942         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
1943         char *pos, *end;
1944
1945         for (i = 0; wpa_drivers[i]; i++) {
1946                 struct wpa_driver_ops *drv = wpa_drivers[i];
1947                 if (drv->get_interfaces == NULL)
1948                         continue;
1949                 tmp = drv->get_interfaces(global->drv_priv);
1950                 if (tmp == NULL)
1951                         continue;
1952
1953                 if (last == NULL)
1954                         iface = last = tmp;
1955                 else
1956                         last->next = tmp;
1957                 while (last->next)
1958                         last = last->next;
1959         }
1960
1961         pos = buf;
1962         end = buf + len;
1963         for (tmp = iface; tmp; tmp = tmp->next) {
1964                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
1965                                   tmp->drv_name, tmp->ifname,
1966                                   tmp->desc ? tmp->desc : "");
1967                 if (res < 0 || res >= end - pos) {
1968                         *pos = '\0';
1969                         break;
1970                 }
1971                 pos += res;
1972         }
1973
1974         wpa_free_iface_info(iface);
1975
1976         return pos - buf;
1977 }
1978
1979
1980 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
1981                                                   char *buf, int len)
1982 {
1983         int res;
1984         char *pos, *end;
1985         struct wpa_supplicant *wpa_s;
1986
1987         wpa_s = global->ifaces;
1988         pos = buf;
1989         end = buf + len;
1990
1991         while (wpa_s) {
1992                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
1993                 if (res < 0 || res >= end - pos) {
1994                         *pos = '\0';
1995                         break;
1996                 }
1997                 pos += res;
1998                 wpa_s = wpa_s->next;
1999         }
2000         return pos - buf;
2001 }
2002
2003
2004 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
2005                                                 char *buf, size_t *resp_len)
2006 {
2007         char *reply;
2008         const int reply_size = 2048;
2009         int reply_len;
2010
2011         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
2012                           (const u8 *) buf, os_strlen(buf));
2013
2014         reply = os_malloc(reply_size);
2015         if (reply == NULL) {
2016                 *resp_len = 1;
2017                 return NULL;
2018         }
2019
2020         os_memcpy(reply, "OK\n", 3);
2021         reply_len = 3;
2022
2023         if (os_strcmp(buf, "PING") == 0) {
2024                 os_memcpy(reply, "PONG\n", 5);
2025                 reply_len = 5;
2026         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
2027                 if (wpa_supplicant_global_iface_add(global, buf + 14))
2028                         reply_len = -1;
2029         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
2030                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
2031                         reply_len = -1;
2032         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
2033                 reply_len = wpa_supplicant_global_iface_list(
2034                         global, reply, reply_size);
2035         } else if (os_strcmp(buf, "INTERFACES") == 0) {
2036                 reply_len = wpa_supplicant_global_iface_interfaces(
2037                         global, reply, reply_size);
2038         } else if (os_strcmp(buf, "TERMINATE") == 0) {
2039                 wpa_supplicant_terminate_proc(global);
2040         } else {
2041                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2042                 reply_len = 16;
2043         }
2044
2045         if (reply_len < 0) {
2046                 os_memcpy(reply, "FAIL\n", 5);
2047                 reply_len = 5;
2048         }
2049
2050         *resp_len = reply_len;
2051         return reply;
2052 }