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