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