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