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