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