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