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