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