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