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