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