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