Fixed ctrl_iface BSS command to fetch scan results, if needed
[libeap.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eloop.h"
19 #include "wpa.h"
20 #include "config.h"
21 #include "eapol_supp/eapol_supp_sm.h"
22 #include "wpa_supplicant_i.h"
23 #include "ctrl_iface.h"
24 #include "l2_packet/l2_packet.h"
25 #include "preauth.h"
26 #include "pmksa_cache.h"
27 #include "wpa_ctrl.h"
28 #include "eap_peer/eap.h"
29 #include "ieee802_11_defs.h"
30
31
32 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
33                                                   char *buf, int len);
34
35
36 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
37                                          char *cmd)
38 {
39         char *value;
40         int ret = 0;
41
42         value = os_strchr(cmd, ' ');
43         if (value == NULL)
44                 return -1;
45         *value++ = '\0';
46
47         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
48         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
49                 eapol_sm_configure(wpa_s->eapol,
50                                    atoi(value), -1, -1, -1);
51         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
52                 eapol_sm_configure(wpa_s->eapol,
53                                    -1, atoi(value), -1, -1);
54         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
55                 eapol_sm_configure(wpa_s->eapol,
56                                    -1, -1, atoi(value), -1);
57         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
58                 eapol_sm_configure(wpa_s->eapol,
59                                    -1, -1, -1, atoi(value));
60         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
61                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
62                                      atoi(value)))
63                         ret = -1;
64         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
65                    0) {
66                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
67                                      atoi(value)))
68                         ret = -1;
69         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
70                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
71                         ret = -1;
72         } else
73                 ret = -1;
74
75         return ret;
76 }
77
78
79 #ifdef IEEE8021X_EAPOL
80 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
81                                              char *addr)
82 {
83         u8 bssid[ETH_ALEN];
84         struct wpa_ssid *ssid = wpa_s->current_ssid;
85
86         if (hwaddr_aton(addr, bssid)) {
87                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
88                            "'%s'", addr);
89                 return -1;
90         }
91
92         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
93         rsn_preauth_deinit(wpa_s->wpa);
94         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
95                 return -1;
96
97         return 0;
98 }
99 #endif /* IEEE8021X_EAPOL */
100
101
102 #ifdef CONFIG_PEERKEY
103 /* MLME-STKSTART.request(peer) */
104 static int wpa_supplicant_ctrl_iface_stkstart(
105         struct wpa_supplicant *wpa_s, char *addr)
106 {
107         u8 peer[ETH_ALEN];
108
109         if (hwaddr_aton(addr, peer)) {
110                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
111                            "address '%s'", peer);
112                 return -1;
113         }
114
115         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
116                    MAC2STR(peer));
117
118         return wpa_sm_stkstart(wpa_s->wpa, peer);
119 }
120 #endif /* CONFIG_PEERKEY */
121
122
123 #ifdef CONFIG_IEEE80211R
124 static int wpa_supplicant_ctrl_iface_ft_ds(
125         struct wpa_supplicant *wpa_s, char *addr)
126 {
127         u8 target_ap[ETH_ALEN];
128
129         if (hwaddr_aton(addr, target_ap)) {
130                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
131                            "address '%s'", target_ap);
132                 return -1;
133         }
134
135         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
136
137         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap);
138 }
139 #endif /* CONFIG_IEEE80211R */
140
141
142 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
143                                               char *rsp)
144 {
145 #ifdef IEEE8021X_EAPOL
146         char *pos, *id_pos;
147         int id;
148         struct wpa_ssid *ssid;
149         struct eap_peer_config *eap;
150
151         pos = os_strchr(rsp, '-');
152         if (pos == NULL)
153                 return -1;
154         *pos++ = '\0';
155         id_pos = pos;
156         pos = os_strchr(pos, ':');
157         if (pos == NULL)
158                 return -1;
159         *pos++ = '\0';
160         id = atoi(id_pos);
161         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
162         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
163                               (u8 *) pos, os_strlen(pos));
164
165         ssid = wpa_config_get_network(wpa_s->conf, id);
166         if (ssid == NULL) {
167                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
168                            "to update", id);
169                 return -1;
170         }
171         eap = &ssid->eap;
172
173         if (os_strcmp(rsp, "IDENTITY") == 0) {
174                 os_free(eap->identity);
175                 eap->identity = (u8 *) os_strdup(pos);
176                 eap->identity_len = os_strlen(pos);
177                 eap->pending_req_identity = 0;
178                 if (ssid == wpa_s->current_ssid)
179                         wpa_s->reassociate = 1;
180         } else if (os_strcmp(rsp, "PASSWORD") == 0) {
181                 os_free(eap->password);
182                 eap->password = (u8 *) os_strdup(pos);
183                 eap->password_len = os_strlen(pos);
184                 eap->pending_req_password = 0;
185                 if (ssid == wpa_s->current_ssid)
186                         wpa_s->reassociate = 1;
187         } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
188                 os_free(eap->new_password);
189                 eap->new_password = (u8 *) os_strdup(pos);
190                 eap->new_password_len = os_strlen(pos);
191                 eap->pending_req_new_password = 0;
192                 if (ssid == wpa_s->current_ssid)
193                         wpa_s->reassociate = 1;
194         } else if (os_strcmp(rsp, "PIN") == 0) {
195                 os_free(eap->pin);
196                 eap->pin = os_strdup(pos);
197                 eap->pending_req_pin = 0;
198                 if (ssid == wpa_s->current_ssid)
199                         wpa_s->reassociate = 1;
200         } else if (os_strcmp(rsp, "OTP") == 0) {
201                 os_free(eap->otp);
202                 eap->otp = (u8 *) os_strdup(pos);
203                 eap->otp_len = os_strlen(pos);
204                 os_free(eap->pending_req_otp);
205                 eap->pending_req_otp = NULL;
206                 eap->pending_req_otp_len = 0;
207         } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
208                 os_free(eap->private_key_passwd);
209                 eap->private_key_passwd = (u8 *) os_strdup(pos);
210                 eap->pending_req_passphrase = 0;
211                 if (ssid == wpa_s->current_ssid)
212                         wpa_s->reassociate = 1;
213         } else {
214                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
215                 return -1;
216         }
217
218         return 0;
219 #else /* IEEE8021X_EAPOL */
220         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
221         return -1;
222 #endif /* IEEE8021X_EAPOL */
223 }
224
225
226 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
227                                             const char *params,
228                                             char *buf, size_t buflen)
229 {
230         char *pos, *end, tmp[30];
231         int res, verbose, ret;
232
233         verbose = os_strcmp(params, "-VERBOSE") == 0;
234         pos = buf;
235         end = buf + buflen;
236         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
237                 struct wpa_ssid *ssid = wpa_s->current_ssid;
238                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
239                                   MAC2STR(wpa_s->bssid));
240                 if (ret < 0 || ret >= end - pos)
241                         return pos - buf;
242                 pos += ret;
243                 if (ssid) {
244                         u8 *_ssid = ssid->ssid;
245                         size_t ssid_len = ssid->ssid_len;
246                         u8 ssid_buf[MAX_SSID_LEN];
247                         if (ssid_len == 0) {
248                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
249                                 if (_res < 0)
250                                         ssid_len = 0;
251                                 else
252                                         ssid_len = _res;
253                                 _ssid = ssid_buf;
254                         }
255                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
256                                           wpa_ssid_txt(_ssid, ssid_len),
257                                           ssid->id);
258                         if (ret < 0 || ret >= end - pos)
259                                 return pos - buf;
260                         pos += ret;
261
262                         if (ssid->id_str) {
263                                 ret = os_snprintf(pos, end - pos,
264                                                   "id_str=%s\n",
265                                                   ssid->id_str);
266                                 if (ret < 0 || ret >= end - pos)
267                                         return pos - buf;
268                                 pos += ret;
269                         }
270                 }
271
272                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
273         }
274         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
275                           wpa_supplicant_state_txt(wpa_s->wpa_state));
276         if (ret < 0 || ret >= end - pos)
277                 return pos - buf;
278         pos += ret;
279
280         if (wpa_s->l2 &&
281             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
282                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
283                 if (ret < 0 || ret >= end - pos)
284                         return pos - buf;
285                 pos += ret;
286         }
287
288         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
289             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
290                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
291                                           verbose);
292                 if (res >= 0)
293                         pos += res;
294         }
295
296         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
297         if (res >= 0)
298                 pos += res;
299
300         return pos - buf;
301 }
302
303
304 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
305                                            char *cmd)
306 {
307         char *pos;
308         int id;
309         struct wpa_ssid *ssid;
310         u8 bssid[ETH_ALEN];
311
312         /* cmd: "<network id> <BSSID>" */
313         pos = os_strchr(cmd, ' ');
314         if (pos == NULL)
315                 return -1;
316         *pos++ = '\0';
317         id = atoi(cmd);
318         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
319         if (hwaddr_aton(pos, bssid)) {
320                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
321                 return -1;
322         }
323
324         ssid = wpa_config_get_network(wpa_s->conf, id);
325         if (ssid == NULL) {
326                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
327                            "to update", id);
328                 return -1;
329         }
330
331         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
332         ssid->bssid_set = !is_zero_ether_addr(bssid);
333
334         return 0;
335 }
336
337
338 static int wpa_supplicant_ctrl_iface_list_networks(
339         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
340 {
341         char *pos, *end;
342         struct wpa_ssid *ssid;
343         int ret;
344
345         pos = buf;
346         end = buf + buflen;
347         ret = os_snprintf(pos, end - pos,
348                           "network id / ssid / bssid / flags\n");
349         if (ret < 0 || ret >= end - pos)
350                 return pos - buf;
351         pos += ret;
352
353         ssid = wpa_s->conf->ssid;
354         while (ssid) {
355                 ret = os_snprintf(pos, end - pos, "%d\t%s",
356                                   ssid->id,
357                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
358                 if (ret < 0 || ret >= end - pos)
359                         return pos - buf;
360                 pos += ret;
361                 if (ssid->bssid_set) {
362                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
363                                           MAC2STR(ssid->bssid));
364                 } else {
365                         ret = os_snprintf(pos, end - pos, "\tany");
366                 }
367                 if (ret < 0 || ret >= end - pos)
368                         return pos - buf;
369                 pos += ret;
370                 ret = os_snprintf(pos, end - pos, "\t%s%s",
371                                   ssid == wpa_s->current_ssid ?
372                                   "[CURRENT]" : "",
373                                   ssid->disabled ? "[DISABLED]" : "");
374                 if (ret < 0 || ret >= end - pos)
375                         return pos - buf;
376                 pos += ret;
377                 ret = os_snprintf(pos, end - pos, "\n");
378                 if (ret < 0 || ret >= end - pos)
379                         return pos - buf;
380                 pos += ret;
381
382                 ssid = ssid->next;
383         }
384
385         return pos - buf;
386 }
387
388
389 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
390 {
391         int first = 1, ret;
392         ret = os_snprintf(pos, end - pos, "-");
393         if (ret < 0 || ret >= end - pos)
394                 return pos;
395         pos += ret;
396         if (cipher & WPA_CIPHER_NONE) {
397                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
398                 if (ret < 0 || ret >= end - pos)
399                         return pos;
400                 pos += ret;
401                 first = 0;
402         }
403         if (cipher & WPA_CIPHER_WEP40) {
404                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
405                 if (ret < 0 || ret >= end - pos)
406                         return pos;
407                 pos += ret;
408                 first = 0;
409         }
410         if (cipher & WPA_CIPHER_WEP104) {
411                 ret = os_snprintf(pos, end - pos, "%sWEP104",
412                                   first ? "" : "+");
413                 if (ret < 0 || ret >= end - pos)
414                         return pos;
415                 pos += ret;
416                 first = 0;
417         }
418         if (cipher & WPA_CIPHER_TKIP) {
419                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
420                 if (ret < 0 || ret >= end - pos)
421                         return pos;
422                 pos += ret;
423                 first = 0;
424         }
425         if (cipher & WPA_CIPHER_CCMP) {
426                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
427                 if (ret < 0 || ret >= end - pos)
428                         return pos;
429                 pos += ret;
430                 first = 0;
431         }
432         return pos;
433 }
434
435
436 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
437                                     const u8 *ie, size_t ie_len)
438 {
439         struct wpa_ie_data data;
440         int first, ret;
441
442         ret = os_snprintf(pos, end - pos, "[%s-", proto);
443         if (ret < 0 || ret >= end - pos)
444                 return pos;
445         pos += ret;
446
447         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
448                 ret = os_snprintf(pos, end - pos, "?]");
449                 if (ret < 0 || ret >= end - pos)
450                         return pos;
451                 pos += ret;
452                 return pos;
453         }
454
455         first = 1;
456         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
457                 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
458                 if (ret < 0 || ret >= end - pos)
459                         return pos;
460                 pos += ret;
461                 first = 0;
462         }
463         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
464                 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
465                 if (ret < 0 || ret >= end - pos)
466                         return pos;
467                 pos += ret;
468                 first = 0;
469         }
470         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
471                 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
472                 if (ret < 0 || ret >= end - pos)
473                         return pos;
474                 pos += ret;
475                 first = 0;
476         }
477 #ifdef CONFIG_IEEE80211R
478         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
479                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
480                                   first ? "" : "+");
481                 if (ret < 0 || ret >= end - pos)
482                         return pos;
483                 pos += ret;
484                 first = 0;
485         }
486         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
487                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
488                                   first ? "" : "+");
489                 if (ret < 0 || ret >= end - pos)
490                         return pos;
491                 pos += ret;
492                 first = 0;
493         }
494 #endif /* CONFIG_IEEE80211R */
495 #ifdef CONFIG_IEEE80211W
496         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
497                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
498                                   first ? "" : "+");
499                 if (ret < 0 || ret >= end - pos)
500                         return pos;
501                 pos += ret;
502                 first = 0;
503         }
504         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
505                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
506                                   first ? "" : "+");
507                 if (ret < 0 || ret >= end - pos)
508                         return pos;
509                 pos += ret;
510                 first = 0;
511         }
512 #endif /* CONFIG_IEEE80211W */
513
514         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
515
516         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
517                 ret = os_snprintf(pos, end - pos, "-preauth");
518                 if (ret < 0 || ret >= end - pos)
519                         return pos;
520                 pos += ret;
521         }
522
523         ret = os_snprintf(pos, end - pos, "]");
524         if (ret < 0 || ret >= end - pos)
525                 return pos;
526         pos += ret;
527
528         return pos;
529 }
530
531
532 /* Format one result on one text line into a buffer. */
533 static int wpa_supplicant_ctrl_iface_scan_result(
534         const struct wpa_scan_res *res, char *buf, size_t buflen)
535 {
536         char *pos, *end;
537         int ret;
538         const u8 *ie, *ie2;
539
540         pos = buf;
541         end = buf + buflen;
542
543         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
544                           MAC2STR(res->bssid), res->freq, res->level);
545         if (ret < 0 || ret >= end - pos)
546                 return pos - buf;
547         pos += ret;
548         ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
549         if (ie)
550                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
551         ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN);
552         if (ie2)
553                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
554         if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) {
555                 ret = os_snprintf(pos, end - pos, "[WEP]");
556                 if (ret < 0 || ret >= end - pos)
557                         return pos - buf;
558                 pos += ret;
559         }
560         if (res->caps & IEEE80211_CAP_IBSS) {
561                 ret = os_snprintf(pos, end - pos, "[IBSS]");
562                 if (ret < 0 || ret >= end - pos)
563                         return pos - buf;
564                 pos += ret;
565         }
566
567         ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
568         ret = os_snprintf(pos, end - pos, "\t%s",
569                           ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
570         if (ret < 0 || ret >= end - pos)
571                 return pos - buf;
572         pos += ret;
573
574         ret = os_snprintf(pos, end - pos, "\n");
575         if (ret < 0 || ret >= end - pos)
576                 return pos - buf;
577         pos += ret;
578
579         return pos - buf;
580 }
581
582
583 static int wpa_supplicant_ctrl_iface_scan_results(
584         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
585 {
586         char *pos, *end;
587         struct wpa_scan_res *res;
588         int ret;
589         size_t i;
590
591         if (wpa_s->scan_res == NULL &&
592             wpa_supplicant_get_scan_results(wpa_s) < 0)
593                 return 0;
594
595         pos = buf;
596         end = buf + buflen;
597         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
598                           "flags / ssid\n");
599         if (ret < 0 || ret >= end - pos)
600                 return pos - buf;
601         pos += ret;
602
603         for (i = 0; i < wpa_s->scan_res->num; i++) {
604                 res = wpa_s->scan_res->res[i];
605                 ret = wpa_supplicant_ctrl_iface_scan_result(res, pos,
606                                                             end - pos);
607                 if (ret < 0 || ret >= end - pos)
608                         return pos - buf;
609                 pos += ret;
610         }
611
612         return pos - buf;
613 }
614
615
616 static int wpa_supplicant_ctrl_iface_select_network(
617         struct wpa_supplicant *wpa_s, char *cmd)
618 {
619         int id;
620         struct wpa_ssid *ssid;
621
622         /* cmd: "<network id>" or "any" */
623         if (os_strcmp(cmd, "any") == 0) {
624                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
625                 ssid = wpa_s->conf->ssid;
626                 while (ssid) {
627                         ssid->disabled = 0;
628                         ssid = ssid->next;
629                 }
630                 wpa_s->reassociate = 1;
631                 wpa_supplicant_req_scan(wpa_s, 0, 0);
632                 return 0;
633         }
634
635         id = atoi(cmd);
636         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
637
638         ssid = wpa_config_get_network(wpa_s->conf, id);
639         if (ssid == NULL) {
640                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
641                            "id=%d", id);
642                 return -1;
643         }
644
645         if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
646                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
647
648         /* Mark all other networks disabled and trigger reassociation */
649         ssid = wpa_s->conf->ssid;
650         while (ssid) {
651                 ssid->disabled = id != ssid->id;
652                 ssid = ssid->next;
653         }
654         wpa_s->reassociate = 1;
655         wpa_supplicant_req_scan(wpa_s, 0, 0);
656
657         return 0;
658 }
659
660
661 static int wpa_supplicant_ctrl_iface_enable_network(
662         struct wpa_supplicant *wpa_s, char *cmd)
663 {
664         int id;
665         struct wpa_ssid *ssid;
666
667         /* cmd: "<network id>" or "all" */
668         if (os_strcmp(cmd, "all") == 0) {
669                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
670                 ssid = wpa_s->conf->ssid;
671                 while (ssid) {
672                         if (ssid == wpa_s->current_ssid && ssid->disabled)
673                                 wpa_s->reassociate = 1;
674                         ssid->disabled = 0;
675                         ssid = ssid->next;
676                 }
677                 if (wpa_s->reassociate)
678                         wpa_supplicant_req_scan(wpa_s, 0, 0);
679                 return 0;
680         }
681
682         id = atoi(cmd);
683         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
684
685         ssid = wpa_config_get_network(wpa_s->conf, id);
686         if (ssid == NULL) {
687                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
688                            "id=%d", id);
689                 return -1;
690         }
691
692         if (wpa_s->current_ssid == NULL && ssid->disabled) {
693                 /*
694                  * Try to reassociate since there is no current configuration
695                  * and a new network was made available. */
696                 wpa_s->reassociate = 1;
697                 wpa_supplicant_req_scan(wpa_s, 0, 0);
698         }
699         ssid->disabled = 0;
700
701         return 0;
702 }
703
704
705 static int wpa_supplicant_ctrl_iface_disable_network(
706         struct wpa_supplicant *wpa_s, char *cmd)
707 {
708         int id;
709         struct wpa_ssid *ssid;
710
711         /* cmd: "<network id>" or "all" */
712         if (os_strcmp(cmd, "all") == 0) {
713                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
714                 ssid = wpa_s->conf->ssid;
715                 while (ssid) {
716                         ssid->disabled = 1;
717                         ssid = ssid->next;
718                 }
719                 if (wpa_s->current_ssid)
720                         wpa_supplicant_disassociate(wpa_s,
721                                                     WLAN_REASON_DEAUTH_LEAVING);
722                 return 0;
723         }
724
725         id = atoi(cmd);
726         wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
727
728         ssid = wpa_config_get_network(wpa_s->conf, id);
729         if (ssid == NULL) {
730                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
731                            "id=%d", id);
732                 return -1;
733         }
734
735         if (ssid == wpa_s->current_ssid)
736                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
737         ssid->disabled = 1;
738
739         return 0;
740 }
741
742
743 static int wpa_supplicant_ctrl_iface_add_network(
744         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
745 {
746         struct wpa_ssid *ssid;
747         int ret;
748
749         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
750
751         ssid = wpa_config_add_network(wpa_s->conf);
752         if (ssid == NULL)
753                 return -1;
754         ssid->disabled = 1;
755         wpa_config_set_network_defaults(ssid);
756
757         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
758         if (ret < 0 || (size_t) ret >= buflen)
759                 return -1;
760         return ret;
761 }
762
763
764 static int wpa_supplicant_ctrl_iface_remove_network(
765         struct wpa_supplicant *wpa_s, char *cmd)
766 {
767         int id;
768         struct wpa_ssid *ssid;
769
770         /* cmd: "<network id>" or "all" */
771         if (os_strcmp(cmd, "all") == 0) {
772                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
773                 ssid = wpa_s->conf->ssid;
774                 while (ssid) {
775                         id = ssid->id;
776                         ssid = ssid->next;
777                         wpa_config_remove_network(wpa_s->conf, id);
778                 }
779                 if (wpa_s->current_ssid) {
780                         eapol_sm_invalidate_cached_session(wpa_s->eapol);
781                         wpa_supplicant_disassociate(wpa_s,
782                                                     WLAN_REASON_DEAUTH_LEAVING);
783                 }
784                 return 0;
785         }
786
787         id = atoi(cmd);
788         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
789
790         ssid = wpa_config_get_network(wpa_s->conf, id);
791         if (ssid == NULL ||
792             wpa_config_remove_network(wpa_s->conf, id) < 0) {
793                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
794                            "id=%d", id);
795                 return -1;
796         }
797
798         if (ssid == wpa_s->current_ssid) {
799                 /*
800                  * Invalidate the EAP session cache if the current network is
801                  * removed.
802                  */
803                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
804
805                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
806         }
807
808         return 0;
809 }
810
811
812 static int wpa_supplicant_ctrl_iface_set_network(
813         struct wpa_supplicant *wpa_s, char *cmd)
814 {
815         int id;
816         struct wpa_ssid *ssid;
817         char *name, *value;
818
819         /* cmd: "<network id> <variable name> <value>" */
820         name = os_strchr(cmd, ' ');
821         if (name == NULL)
822                 return -1;
823         *name++ = '\0';
824
825         value = os_strchr(name, ' ');
826         if (value == NULL)
827                 return -1;
828         *value++ = '\0';
829
830         id = atoi(cmd);
831         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
832                    id, name);
833         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
834                               (u8 *) value, os_strlen(value));
835
836         ssid = wpa_config_get_network(wpa_s->conf, id);
837         if (ssid == NULL) {
838                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
839                            "id=%d", id);
840                 return -1;
841         }
842
843         if (wpa_config_set(ssid, name, value, 0) < 0) {
844                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
845                            "variable '%s'", name);
846                 return -1;
847         }
848
849         if (wpa_s->current_ssid == ssid) {
850                 /*
851                  * Invalidate the EAP session cache if anything in the current
852                  * configuration changes.
853                  */
854                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
855         }
856
857         if ((os_strcmp(name, "psk") == 0 &&
858              value[0] == '"' && ssid->ssid_len) ||
859             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
860                 wpa_config_update_psk(ssid);
861
862         return 0;
863 }
864
865
866 static int wpa_supplicant_ctrl_iface_get_network(
867         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
868 {
869         int id;
870         size_t res;
871         struct wpa_ssid *ssid;
872         char *name, *value;
873
874         /* cmd: "<network id> <variable name>" */
875         name = os_strchr(cmd, ' ');
876         if (name == NULL || buflen == 0)
877                 return -1;
878         *name++ = '\0';
879
880         id = atoi(cmd);
881         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
882                    id, name);
883
884         ssid = wpa_config_get_network(wpa_s->conf, id);
885         if (ssid == NULL) {
886                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
887                            "id=%d", id);
888                 return -1;
889         }
890
891         value = wpa_config_get_no_key(ssid, name);
892         if (value == NULL) {
893                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
894                            "variable '%s'", name);
895                 return -1;
896         }
897
898         res = os_strlcpy(buf, value, buflen);
899         if (res >= buflen) {
900                 os_free(value);
901                 return -1;
902         }
903
904         os_free(value);
905
906         return res;
907 }
908
909
910 #ifndef CONFIG_NO_CONFIG_WRITE
911 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
912 {
913         int ret;
914
915         if (!wpa_s->conf->update_config) {
916                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
917                            "to update configuration (update_config=0)");
918                 return -1;
919         }
920
921         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
922         if (ret) {
923                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
924                            "update configuration");
925         } else {
926                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
927                            " updated");
928         }
929
930         return ret;
931 }
932 #endif /* CONFIG_NO_CONFIG_WRITE */
933
934
935 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
936                                               struct wpa_driver_capa *capa,
937                                               char *buf, size_t buflen)
938 {
939         int ret, first = 1;
940         char *pos, *end;
941         size_t len;
942
943         pos = buf;
944         end = pos + buflen;
945
946         if (res < 0) {
947                 if (strict)
948                         return 0;
949                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
950                 if (len >= buflen)
951                         return -1;
952                 return len;
953         }
954
955         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
956                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
957                 if (ret < 0 || ret >= end - pos)
958                         return pos - buf;
959                 pos += ret;
960                 first = 0;
961         }
962
963         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
964                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
965                 if (ret < 0 || ret >= end - pos)
966                         return pos - buf;
967                 pos += ret;
968                 first = 0;
969         }
970
971         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
972                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
973                 if (ret < 0 || ret >= end - pos)
974                         return pos - buf;
975                 pos += ret;
976                 first = 0;
977         }
978
979         return pos - buf;
980 }
981
982
983 static int ctrl_iface_get_capability_group(int res, char *strict,
984                                            struct wpa_driver_capa *capa,
985                                            char *buf, size_t buflen)
986 {
987         int ret, first = 1;
988         char *pos, *end;
989         size_t len;
990
991         pos = buf;
992         end = pos + buflen;
993
994         if (res < 0) {
995                 if (strict)
996                         return 0;
997                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
998                 if (len >= buflen)
999                         return -1;
1000                 return len;
1001         }
1002
1003         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1004                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1005                 if (ret < 0 || ret >= end - pos)
1006                         return pos - buf;
1007                 pos += ret;
1008                 first = 0;
1009         }
1010
1011         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1012                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1013                 if (ret < 0 || ret >= end - pos)
1014                         return pos - buf;
1015                 pos += ret;
1016                 first = 0;
1017         }
1018
1019         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1020                 ret = os_snprintf(pos, end - pos, "%sWEP104",
1021                                   first ? "" : " ");
1022                 if (ret < 0 || ret >= end - pos)
1023                         return pos - buf;
1024                 pos += ret;
1025                 first = 0;
1026         }
1027
1028         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1029                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1030                 if (ret < 0 || ret >= end - pos)
1031                         return pos - buf;
1032                 pos += ret;
1033                 first = 0;
1034         }
1035
1036         return pos - buf;
1037 }
1038
1039
1040 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1041                                               struct wpa_driver_capa *capa,
1042                                               char *buf, size_t buflen)
1043 {
1044         int ret;
1045         char *pos, *end;
1046         size_t len;
1047
1048         pos = buf;
1049         end = pos + buflen;
1050
1051         if (res < 0) {
1052                 if (strict)
1053                         return 0;
1054                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1055                                  "NONE", buflen);
1056                 if (len >= buflen)
1057                         return -1;
1058                 return len;
1059         }
1060
1061         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1062         if (ret < 0 || ret >= end - pos)
1063                 return pos - buf;
1064         pos += ret;
1065
1066         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1067                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1068                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
1069                 if (ret < 0 || ret >= end - pos)
1070                         return pos - buf;
1071                 pos += ret;
1072         }
1073
1074         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1075                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1076                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
1077                 if (ret < 0 || ret >= end - pos)
1078                         return pos - buf;
1079                 pos += ret;
1080         }
1081
1082         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1083                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
1084                 if (ret < 0 || ret >= end - pos)
1085                         return pos - buf;
1086                 pos += ret;
1087         }
1088
1089         return pos - buf;
1090 }
1091
1092
1093 static int ctrl_iface_get_capability_proto(int res, char *strict,
1094                                            struct wpa_driver_capa *capa,
1095                                            char *buf, size_t buflen)
1096 {
1097         int ret, first = 1;
1098         char *pos, *end;
1099         size_t len;
1100
1101         pos = buf;
1102         end = pos + buflen;
1103
1104         if (res < 0) {
1105                 if (strict)
1106                         return 0;
1107                 len = os_strlcpy(buf, "RSN WPA", buflen);
1108                 if (len >= buflen)
1109                         return -1;
1110                 return len;
1111         }
1112
1113         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1114                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1115                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1116                 if (ret < 0 || ret >= end - pos)
1117                         return pos - buf;
1118                 pos += ret;
1119                 first = 0;
1120         }
1121
1122         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1123                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1124                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1125                 if (ret < 0 || ret >= end - pos)
1126                         return pos - buf;
1127                 pos += ret;
1128                 first = 0;
1129         }
1130
1131         return pos - buf;
1132 }
1133
1134
1135 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1136                                               struct wpa_driver_capa *capa,
1137                                               char *buf, size_t buflen)
1138 {
1139         int ret, first = 1;
1140         char *pos, *end;
1141         size_t len;
1142
1143         pos = buf;
1144         end = pos + buflen;
1145
1146         if (res < 0) {
1147                 if (strict)
1148                         return 0;
1149                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1150                 if (len >= buflen)
1151                         return -1;
1152                 return len;
1153         }
1154
1155         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1156                 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1157                 if (ret < 0 || ret >= end - pos)
1158                         return pos - buf;
1159                 pos += ret;
1160                 first = 0;
1161         }
1162
1163         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1164                 ret = os_snprintf(pos, end - pos, "%sSHARED",
1165                                   first ? "" : " ");
1166                 if (ret < 0 || ret >= end - pos)
1167                         return pos - buf;
1168                 pos += ret;
1169                 first = 0;
1170         }
1171
1172         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1173                 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1174                 if (ret < 0 || ret >= end - pos)
1175                         return pos - buf;
1176                 pos += ret;
1177                 first = 0;
1178         }
1179
1180         return pos - buf;
1181 }
1182
1183
1184 static int wpa_supplicant_ctrl_iface_get_capability(
1185         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1186         size_t buflen)
1187 {
1188         struct wpa_driver_capa capa;
1189         int res;
1190         char *strict;
1191         char field[30];
1192         size_t len;
1193
1194         /* Determine whether or not strict checking was requested */
1195         len = os_strlcpy(field, _field, sizeof(field));
1196         if (len >= sizeof(field))
1197                 return -1;
1198         strict = os_strchr(field, ' ');
1199         if (strict != NULL) {
1200                 *strict++ = '\0';
1201                 if (os_strcmp(strict, "strict") != 0)
1202                         return -1;
1203         }
1204
1205         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1206                 field, strict ? strict : "");
1207
1208         if (os_strcmp(field, "eap") == 0) {
1209                 return eap_get_names(buf, buflen);
1210         }
1211
1212         res = wpa_drv_get_capa(wpa_s, &capa);
1213
1214         if (os_strcmp(field, "pairwise") == 0)
1215                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1216                                                           buf, buflen);
1217
1218         if (os_strcmp(field, "group") == 0)
1219                 return ctrl_iface_get_capability_group(res, strict, &capa,
1220                                                        buf, buflen);
1221
1222         if (os_strcmp(field, "key_mgmt") == 0)
1223                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1224                                                           buf, buflen);
1225
1226         if (os_strcmp(field, "proto") == 0)
1227                 return ctrl_iface_get_capability_proto(res, strict, &capa,
1228                                                        buf, buflen);
1229
1230         if (os_strcmp(field, "auth_alg") == 0)
1231                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1232                                                           buf, buflen);
1233
1234         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1235                    field);
1236
1237         return -1;
1238 }
1239
1240
1241 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
1242                                          const char *cmd, char *buf,
1243                                          size_t buflen)
1244 {
1245         u8 bssid[ETH_ALEN];
1246         size_t i;
1247         struct wpa_scan_results *results;
1248         struct wpa_scan_res *bss;
1249         int ret;
1250         char *pos, *end;
1251         const u8 *ie, *ie2;
1252
1253         if (wpa_s->scan_res == NULL &&
1254             wpa_supplicant_get_scan_results(wpa_s) < 0)
1255                 return 0;
1256
1257         results = wpa_s->scan_res;
1258         if (results == NULL)
1259                 return 0;
1260
1261         if (hwaddr_aton(cmd, bssid) == 0) {
1262                 for (i = 0; i < results->num; i++) {
1263                         if (os_memcmp(bssid, results->res[i]->bssid, ETH_ALEN)
1264                             == 0)
1265                                 break;
1266                 }
1267         } else
1268                 i = atoi(cmd);
1269
1270         if (i >= results->num || results->res[i] == NULL)
1271                 return 0; /* no match found */
1272
1273         bss = results->res[i];
1274         pos = buf;
1275         end = buf + buflen;
1276         ret = os_snprintf(pos, end - pos,
1277                           "bssid=" MACSTR "\n"
1278                           "freq=%d\n"
1279                           "beacon_int=%d\n"
1280                           "capabilities=0x%04x\n"
1281                           "qual=%d\n"
1282                           "noise=%d\n"
1283                           "level=%d\n"
1284                           "tsf=%016llu\n"
1285                           "ie=",
1286                           MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
1287                           bss->caps, bss->qual, bss->noise, bss->level,
1288                           (unsigned long long) bss->tsf);
1289         if (ret < 0 || ret >= end - pos)
1290                 return pos - buf;
1291         pos += ret;
1292
1293         ie = (const u8 *) (bss + 1);
1294         for (i = 0; i < bss->ie_len; i++) {
1295                 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
1296                 if (ret < 0 || ret >= end - pos)
1297                         return pos - buf;
1298                 pos += ret;
1299         }
1300
1301         ret = os_snprintf(pos, end - pos, "\n");
1302         if (ret < 0 || ret >= end - pos)
1303                 return pos - buf;
1304         pos += ret;
1305
1306         ret = os_snprintf(pos, end - pos, "flags=");
1307         if (ret < 0 || ret >= end - pos)
1308                 return pos - buf;
1309         pos += ret;
1310
1311         ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1312         if (ie)
1313                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1314         ie2 = wpa_scan_get_ie(bss, WLAN_EID_RSN);
1315         if (ie2)
1316                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1317         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1318                 ret = os_snprintf(pos, end - pos, "[WEP]");
1319                 if (ret < 0 || ret >= end - pos)
1320                         return pos - buf;
1321                 pos += ret;
1322         }
1323         if (bss->caps & IEEE80211_CAP_IBSS) {
1324                 ret = os_snprintf(pos, end - pos, "[IBSS]");
1325                 if (ret < 0 || ret >= end - pos)
1326                         return pos - buf;
1327                 pos += ret;
1328         }
1329
1330         ret = os_snprintf(pos, end - pos, "\n");
1331         if (ret < 0 || ret >= end - pos)
1332                 return pos - buf;
1333         pos += ret;
1334
1335         ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
1336         ret = os_snprintf(pos, end - pos, "ssid=%s\n",
1337                           ie ? wpa_ssid_txt(ie + 2, ie[1]) : "");
1338         if (ret < 0 || ret >= end - pos)
1339                 return pos - buf;
1340         pos += ret;
1341
1342         return pos - buf;
1343 }
1344
1345
1346 static int wpa_supplicant_ctrl_iface_ap_scan(
1347         struct wpa_supplicant *wpa_s, char *cmd)
1348 {
1349         int ap_scan = atoi(cmd);
1350
1351         if (ap_scan < 0 || ap_scan > 2)
1352                 return -1;
1353         wpa_s->conf->ap_scan = ap_scan;
1354         return 0;
1355 }
1356
1357
1358 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
1359                                          char *buf, size_t *resp_len)
1360 {
1361         char *reply;
1362         const int reply_size = 2048;
1363         int ctrl_rsp = 0;
1364         int reply_len;
1365
1366         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
1367             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1368                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
1369                                       (const u8 *) buf, os_strlen(buf));
1370         } else {
1371                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
1372                                   (const u8 *) buf, os_strlen(buf));
1373         }
1374
1375         reply = os_malloc(reply_size);
1376         if (reply == NULL) {
1377                 *resp_len = 1;
1378                 return NULL;
1379         }
1380
1381         os_memcpy(reply, "OK\n", 3);
1382         reply_len = 3;
1383
1384         if (os_strcmp(buf, "PING") == 0) {
1385                 os_memcpy(reply, "PONG\n", 5);
1386                 reply_len = 5;
1387         } else if (os_strcmp(buf, "MIB") == 0) {
1388                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
1389                 if (reply_len >= 0) {
1390                         int res;
1391                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
1392                                                reply_size - reply_len);
1393                         if (res < 0)
1394                                 reply_len = -1;
1395                         else
1396                                 reply_len += res;
1397                 }
1398         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
1399                 reply_len = wpa_supplicant_ctrl_iface_status(
1400                         wpa_s, buf + 6, reply, reply_size);
1401         } else if (os_strcmp(buf, "PMKSA") == 0) {
1402                 reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
1403         } else if (os_strncmp(buf, "SET ", 4) == 0) {
1404                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
1405                         reply_len = -1;
1406         } else if (os_strcmp(buf, "LOGON") == 0) {
1407                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
1408         } else if (os_strcmp(buf, "LOGOFF") == 0) {
1409                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
1410         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
1411                 wpa_s->disconnected = 0;
1412                 wpa_s->reassociate = 1;
1413                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1414         } else if (os_strcmp(buf, "RECONNECT") == 0) {
1415                 if (wpa_s->disconnected) {
1416                         wpa_s->disconnected = 0;
1417                         wpa_s->reassociate = 1;
1418                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1419                 }
1420 #ifdef IEEE8021X_EAPOL
1421         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
1422                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
1423                         reply_len = -1;
1424 #endif /* IEEE8021X_EAPOL */
1425 #ifdef CONFIG_PEERKEY
1426         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
1427                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
1428                         reply_len = -1;
1429 #endif /* CONFIG_PEERKEY */
1430 #ifdef CONFIG_IEEE80211R
1431         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
1432                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
1433                         reply_len = -1;
1434 #endif /* CONFIG_IEEE80211R */
1435         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
1436         {
1437                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
1438                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
1439                         reply_len = -1;
1440                 else
1441                         ctrl_rsp = 1;
1442         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
1443                 if (wpa_supplicant_reload_configuration(wpa_s))
1444                         reply_len = -1;
1445         } else if (os_strcmp(buf, "TERMINATE") == 0) {
1446                 eloop_terminate();
1447         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
1448                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
1449                         reply_len = -1;
1450         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
1451                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
1452                         wpa_s, reply, reply_size);
1453         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
1454                 wpa_s->reassociate = 0;
1455                 wpa_s->disconnected = 1;
1456                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1457         } else if (os_strcmp(buf, "SCAN") == 0) {
1458                 wpa_s->scan_req = 2;
1459                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1460         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
1461                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
1462                         wpa_s, reply, reply_size);
1463         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
1464                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
1465                         reply_len = -1;
1466         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
1467                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
1468                         reply_len = -1;
1469         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
1470                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
1471                         reply_len = -1;
1472         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
1473                 reply_len = wpa_supplicant_ctrl_iface_add_network(
1474                         wpa_s, reply, reply_size);
1475         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
1476                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
1477                         reply_len = -1;
1478         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
1479                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
1480                         reply_len = -1;
1481         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
1482                 reply_len = wpa_supplicant_ctrl_iface_get_network(
1483                         wpa_s, buf + 12, reply, reply_size);
1484 #ifndef CONFIG_NO_CONFIG_WRITE
1485         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
1486                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
1487                         reply_len = -1;
1488 #endif /* CONFIG_NO_CONFIG_WRITE */
1489         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
1490                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
1491                         wpa_s, buf + 15, reply, reply_size);
1492         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
1493                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
1494                         reply_len = -1;
1495         } else if (os_strcmp(buf, "INTERFACES") == 0) {
1496                 reply_len = wpa_supplicant_global_iface_interfaces(
1497                         wpa_s->global, reply, reply_size);
1498         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
1499                 reply_len = wpa_supplicant_ctrl_iface_bss(
1500                         wpa_s, buf + 4, reply, reply_size);
1501         } else {
1502                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1503                 reply_len = 16;
1504         }
1505
1506         if (reply_len < 0) {
1507                 os_memcpy(reply, "FAIL\n", 5);
1508                 reply_len = 5;
1509         }
1510
1511         if (ctrl_rsp)
1512                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1513
1514         *resp_len = reply_len;
1515         return reply;
1516 }
1517
1518
1519 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
1520                                            char *cmd)
1521 {
1522         struct wpa_interface iface;
1523         char *pos;
1524
1525         /*
1526          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
1527          * TAB<bridge_ifname>
1528          */
1529         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
1530
1531         os_memset(&iface, 0, sizeof(iface));
1532
1533         do {
1534                 iface.ifname = pos = cmd;
1535                 pos = os_strchr(pos, '\t');
1536                 if (pos)
1537                         *pos++ = '\0';
1538                 if (iface.ifname[0] == '\0')
1539                         return -1;
1540                 if (pos == NULL)
1541                         break;
1542
1543                 iface.confname = pos;
1544                 pos = os_strchr(pos, '\t');
1545                 if (pos)
1546                         *pos++ = '\0';
1547                 if (iface.confname[0] == '\0')
1548                         iface.confname = NULL;
1549                 if (pos == NULL)
1550                         break;
1551
1552                 iface.driver = pos;
1553                 pos = os_strchr(pos, '\t');
1554                 if (pos)
1555                         *pos++ = '\0';
1556                 if (iface.driver[0] == '\0')
1557                         iface.driver = NULL;
1558                 if (pos == NULL)
1559                         break;
1560
1561                 iface.ctrl_interface = pos;
1562                 pos = os_strchr(pos, '\t');
1563                 if (pos)
1564                         *pos++ = '\0';
1565                 if (iface.ctrl_interface[0] == '\0')
1566                         iface.ctrl_interface = NULL;
1567                 if (pos == NULL)
1568                         break;
1569
1570                 iface.driver_param = pos;
1571                 pos = os_strchr(pos, '\t');
1572                 if (pos)
1573                         *pos++ = '\0';
1574                 if (iface.driver_param[0] == '\0')
1575                         iface.driver_param = NULL;
1576                 if (pos == NULL)
1577                         break;
1578
1579                 iface.bridge_ifname = pos;
1580                 pos = os_strchr(pos, '\t');
1581                 if (pos)
1582                         *pos++ = '\0';
1583                 if (iface.bridge_ifname[0] == '\0')
1584                         iface.bridge_ifname = NULL;
1585                 if (pos == NULL)
1586                         break;
1587         } while (0);
1588
1589         if (wpa_supplicant_get_iface(global, iface.ifname))
1590                 return -1;
1591
1592         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
1593 }
1594
1595
1596 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
1597                                               char *cmd)
1598 {
1599         struct wpa_supplicant *wpa_s;
1600
1601         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
1602
1603         wpa_s = wpa_supplicant_get_iface(global, cmd);
1604         if (wpa_s == NULL)
1605                 return -1;
1606         return wpa_supplicant_remove_iface(global, wpa_s);
1607 }
1608
1609
1610 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
1611                                                   char *buf, int len)
1612 {
1613         int res;
1614         char *pos, *end;
1615         struct wpa_supplicant *wpa_s;
1616
1617         wpa_s = global->ifaces;
1618         pos = buf;
1619         end = buf + len;
1620
1621         while (wpa_s) {
1622                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
1623                 if (res < 0 || res >= end - pos) {
1624                         *pos = '\0';
1625                         break;
1626                 }
1627                 pos += res;
1628                 wpa_s = wpa_s->next;
1629         }
1630         return pos - buf;
1631 }
1632
1633
1634 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
1635                                                 char *buf, size_t *resp_len)
1636 {
1637         char *reply;
1638         const int reply_size = 2048;
1639         int reply_len;
1640
1641         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
1642                           (const u8 *) buf, os_strlen(buf));
1643
1644         reply = os_malloc(reply_size);
1645         if (reply == NULL) {
1646                 *resp_len = 1;
1647                 return NULL;
1648         }
1649
1650         os_memcpy(reply, "OK\n", 3);
1651         reply_len = 3;
1652
1653         if (os_strcmp(buf, "PING") == 0) {
1654                 os_memcpy(reply, "PONG\n", 5);
1655                 reply_len = 5;
1656         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
1657                 if (wpa_supplicant_global_iface_add(global, buf + 14))
1658                         reply_len = -1;
1659         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
1660                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
1661                         reply_len = -1;
1662         } else if (os_strcmp(buf, "INTERFACES") == 0) {
1663                 reply_len = wpa_supplicant_global_iface_interfaces(
1664                         global, reply, reply_size);
1665         } else if (os_strcmp(buf, "TERMINATE") == 0) {
1666                 eloop_terminate();
1667         } else {
1668                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
1669                 reply_len = 16;
1670         }
1671
1672         if (reply_len < 0) {
1673                 os_memcpy(reply, "FAIL\n", 5);
1674                 reply_len = 5;
1675         }
1676
1677         *resp_len = reply_len;
1678         return reply;
1679 }