97f8e28a241aceee967a71f68c4bf8dac5793259
[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 "p2p_supplicant.h"
35 #include "p2p/p2p.h"
36 #include "notify.h"
37 #include "bss.h"
38 #include "scan.h"
39 #include "ctrl_iface.h"
40
41 extern struct wpa_driver_ops *wpa_drivers[];
42
43 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
44                                             char *buf, int len);
45 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
46                                                   char *buf, int len);
47
48
49 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
50                                          char *cmd)
51 {
52         char *value;
53         int ret = 0;
54
55         value = os_strchr(cmd, ' ');
56         if (value == NULL)
57                 return -1;
58         *value++ = '\0';
59
60         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
61         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
62                 eapol_sm_configure(wpa_s->eapol,
63                                    atoi(value), -1, -1, -1);
64         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
65                 eapol_sm_configure(wpa_s->eapol,
66                                    -1, atoi(value), -1, -1);
67         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
68                 eapol_sm_configure(wpa_s->eapol,
69                                    -1, -1, atoi(value), -1);
70         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
71                 eapol_sm_configure(wpa_s->eapol,
72                                    -1, -1, -1, atoi(value));
73         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
74                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
75                                      atoi(value)))
76                         ret = -1;
77         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
78                    0) {
79                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
80                                      atoi(value)))
81                         ret = -1;
82         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
83                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
84                         ret = -1;
85         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
86                 wpa_s->wps_fragment_size = atoi(value);
87         } else {
88                 value[-1] = '=';
89                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
90                 if (ret == 0)
91                         wpa_supplicant_update_config(wpa_s);
92         }
93
94         return ret;
95 }
96
97
98 #ifdef IEEE8021X_EAPOL
99 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
100                                              char *addr)
101 {
102         u8 bssid[ETH_ALEN];
103         struct wpa_ssid *ssid = wpa_s->current_ssid;
104
105         if (hwaddr_aton(addr, bssid)) {
106                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
107                            "'%s'", addr);
108                 return -1;
109         }
110
111         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
112         rsn_preauth_deinit(wpa_s->wpa);
113         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
114                 return -1;
115
116         return 0;
117 }
118 #endif /* IEEE8021X_EAPOL */
119
120
121 #ifdef CONFIG_PEERKEY
122 /* MLME-STKSTART.request(peer) */
123 static int wpa_supplicant_ctrl_iface_stkstart(
124         struct wpa_supplicant *wpa_s, char *addr)
125 {
126         u8 peer[ETH_ALEN];
127
128         if (hwaddr_aton(addr, peer)) {
129                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
130                            "address '%s'", addr);
131                 return -1;
132         }
133
134         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
135                    MAC2STR(peer));
136
137         return wpa_sm_stkstart(wpa_s->wpa, peer);
138 }
139 #endif /* CONFIG_PEERKEY */
140
141
142 #ifdef CONFIG_IEEE80211R
143 static int wpa_supplicant_ctrl_iface_ft_ds(
144         struct wpa_supplicant *wpa_s, char *addr)
145 {
146         u8 target_ap[ETH_ALEN];
147         struct wpa_bss *bss;
148         const u8 *mdie;
149
150         if (hwaddr_aton(addr, target_ap)) {
151                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
152                            "address '%s'", addr);
153                 return -1;
154         }
155
156         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
157
158         bss = wpa_bss_get_bssid(wpa_s, target_ap);
159         if (bss)
160                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
161         else
162                 mdie = NULL;
163
164         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
165 }
166 #endif /* CONFIG_IEEE80211R */
167
168
169 #ifdef CONFIG_WPS
170 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
171                                              char *cmd)
172 {
173         u8 bssid[ETH_ALEN], *_bssid = bssid;
174
175         if (cmd == NULL || os_strcmp(cmd, "any") == 0)
176                 _bssid = NULL;
177         else if (hwaddr_aton(cmd, bssid)) {
178                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
179                            cmd);
180                 return -1;
181         }
182
183 #ifdef CONFIG_AP
184         if (wpa_s->ap_iface)
185                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
186 #endif /* CONFIG_AP */
187
188         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
189 }
190
191
192 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
193                                              char *cmd, char *buf,
194                                              size_t buflen)
195 {
196         u8 bssid[ETH_ALEN], *_bssid = bssid;
197         char *pin;
198         int ret;
199
200         pin = os_strchr(cmd, ' ');
201         if (pin)
202                 *pin++ = '\0';
203
204         if (os_strcmp(cmd, "any") == 0)
205                 _bssid = NULL;
206         else if (hwaddr_aton(cmd, bssid)) {
207                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
208                            cmd);
209                 return -1;
210         }
211
212 #ifdef CONFIG_AP
213         if (wpa_s->ap_iface)
214                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
215                                                  buf, buflen);
216 #endif /* CONFIG_AP */
217
218         if (pin) {
219                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0);
220                 if (ret < 0)
221                         return -1;
222                 ret = os_snprintf(buf, buflen, "%s", pin);
223                 if (ret < 0 || (size_t) ret >= buflen)
224                         return -1;
225                 return ret;
226         }
227
228         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0);
229         if (ret < 0)
230                 return -1;
231
232         /* Return the generated PIN */
233         ret = os_snprintf(buf, buflen, "%08d", ret);
234         if (ret < 0 || (size_t) ret >= buflen)
235                 return -1;
236         return ret;
237 }
238
239
240 #ifdef CONFIG_WPS_OOB
241 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
242                                              char *cmd)
243 {
244         char *path, *method, *name;
245
246         path = os_strchr(cmd, ' ');
247         if (path == NULL)
248                 return -1;
249         *path++ = '\0';
250
251         method = os_strchr(path, ' ');
252         if (method == NULL)
253                 return -1;
254         *method++ = '\0';
255
256         name = os_strchr(method, ' ');
257         if (name != NULL)
258                 *name++ = '\0';
259
260         return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
261 }
262 #endif /* CONFIG_WPS_OOB */
263
264
265 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
266                                              char *cmd)
267 {
268         u8 bssid[ETH_ALEN], *_bssid = bssid;
269         char *pin;
270         char *new_ssid;
271         char *new_auth;
272         char *new_encr;
273         char *new_key;
274         struct wps_new_ap_settings ap;
275
276         pin = os_strchr(cmd, ' ');
277         if (pin == NULL)
278                 return -1;
279         *pin++ = '\0';
280
281         if (os_strcmp(cmd, "any") == 0)
282                 _bssid = NULL;
283         else if (hwaddr_aton(cmd, bssid)) {
284                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
285                            cmd);
286                 return -1;
287         }
288
289         new_ssid = os_strchr(pin, ' ');
290         if (new_ssid == NULL)
291                 return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL);
292         *new_ssid++ = '\0';
293
294         new_auth = os_strchr(new_ssid, ' ');
295         if (new_auth == NULL)
296                 return -1;
297         *new_auth++ = '\0';
298
299         new_encr = os_strchr(new_auth, ' ');
300         if (new_encr == NULL)
301                 return -1;
302         *new_encr++ = '\0';
303
304         new_key = os_strchr(new_encr, ' ');
305         if (new_key == NULL)
306                 return -1;
307         *new_key++ = '\0';
308
309         os_memset(&ap, 0, sizeof(ap));
310         ap.ssid_hex = new_ssid;
311         ap.auth = new_auth;
312         ap.encr = new_encr;
313         ap.key_hex = new_key;
314         return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap);
315 }
316
317
318 #ifdef CONFIG_WPS_ER
319 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
320                                                 char *cmd)
321 {
322         char *uuid = cmd, *pin, *pos;
323         u8 addr_buf[ETH_ALEN], *addr = NULL;
324         pin = os_strchr(uuid, ' ');
325         if (pin == NULL)
326                 return -1;
327         *pin++ = '\0';
328         pos = os_strchr(pin, ' ');
329         if (pos) {
330                 *pos++ = '\0';
331                 if (hwaddr_aton(pos, addr_buf) == 0)
332                         addr = addr_buf;
333         }
334         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
335 }
336
337
338 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
339                                                   char *cmd)
340 {
341         char *uuid = cmd, *pin;
342         pin = os_strchr(uuid, ' ');
343         if (pin == NULL)
344                 return -1;
345         *pin++ = '\0';
346         return wpas_wps_er_learn(wpa_s, uuid, pin);
347 }
348
349
350 static int wpa_supplicant_ctrl_iface_wps_er_config(
351         struct wpa_supplicant *wpa_s, char *cmd)
352 {
353         char *pin;
354         char *new_ssid;
355         char *new_auth;
356         char *new_encr;
357         char *new_key;
358         struct wps_new_ap_settings ap;
359
360         pin = os_strchr(cmd, ' ');
361         if (pin == NULL)
362                 return -1;
363         *pin++ = '\0';
364
365         new_ssid = os_strchr(pin, ' ');
366         if (new_ssid == NULL)
367                 return -1;
368         *new_ssid++ = '\0';
369
370         new_auth = os_strchr(new_ssid, ' ');
371         if (new_auth == NULL)
372                 return -1;
373         *new_auth++ = '\0';
374
375         new_encr = os_strchr(new_auth, ' ');
376         if (new_encr == NULL)
377                 return -1;
378         *new_encr++ = '\0';
379
380         new_key = os_strchr(new_encr, ' ');
381         if (new_key == NULL)
382                 return -1;
383         *new_key++ = '\0';
384
385         os_memset(&ap, 0, sizeof(ap));
386         ap.ssid_hex = new_ssid;
387         ap.auth = new_auth;
388         ap.encr = new_encr;
389         ap.key_hex = new_key;
390         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
391 }
392 #endif /* CONFIG_WPS_ER */
393
394 #endif /* CONFIG_WPS */
395
396
397 #ifdef CONFIG_IBSS_RSN
398 static int wpa_supplicant_ctrl_iface_ibss_rsn(
399         struct wpa_supplicant *wpa_s, char *addr)
400 {
401         u8 peer[ETH_ALEN];
402
403         if (hwaddr_aton(addr, peer)) {
404                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
405                            "address '%s'", addr);
406                 return -1;
407         }
408
409         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
410                    MAC2STR(peer));
411
412         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
413 }
414 #endif /* CONFIG_IBSS_RSN */
415
416
417 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
418                                               char *rsp)
419 {
420 #ifdef IEEE8021X_EAPOL
421         char *pos, *id_pos;
422         int id;
423         struct wpa_ssid *ssid;
424         struct eap_peer_config *eap;
425
426         pos = os_strchr(rsp, '-');
427         if (pos == NULL)
428                 return -1;
429         *pos++ = '\0';
430         id_pos = pos;
431         pos = os_strchr(pos, ':');
432         if (pos == NULL)
433                 return -1;
434         *pos++ = '\0';
435         id = atoi(id_pos);
436         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
437         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
438                               (u8 *) pos, os_strlen(pos));
439
440         ssid = wpa_config_get_network(wpa_s->conf, id);
441         if (ssid == NULL) {
442                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
443                            "to update", id);
444                 return -1;
445         }
446         eap = &ssid->eap;
447
448         if (os_strcmp(rsp, "IDENTITY") == 0) {
449                 os_free(eap->identity);
450                 eap->identity = (u8 *) os_strdup(pos);
451                 eap->identity_len = os_strlen(pos);
452                 eap->pending_req_identity = 0;
453                 if (ssid == wpa_s->current_ssid)
454                         wpa_s->reassociate = 1;
455         } else if (os_strcmp(rsp, "PASSWORD") == 0) {
456                 os_free(eap->password);
457                 eap->password = (u8 *) os_strdup(pos);
458                 eap->password_len = os_strlen(pos);
459                 eap->pending_req_password = 0;
460                 if (ssid == wpa_s->current_ssid)
461                         wpa_s->reassociate = 1;
462         } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
463                 os_free(eap->new_password);
464                 eap->new_password = (u8 *) os_strdup(pos);
465                 eap->new_password_len = os_strlen(pos);
466                 eap->pending_req_new_password = 0;
467                 if (ssid == wpa_s->current_ssid)
468                         wpa_s->reassociate = 1;
469         } else if (os_strcmp(rsp, "PIN") == 0) {
470                 os_free(eap->pin);
471                 eap->pin = os_strdup(pos);
472                 eap->pending_req_pin = 0;
473                 if (ssid == wpa_s->current_ssid)
474                         wpa_s->reassociate = 1;
475         } else if (os_strcmp(rsp, "OTP") == 0) {
476                 os_free(eap->otp);
477                 eap->otp = (u8 *) os_strdup(pos);
478                 eap->otp_len = os_strlen(pos);
479                 os_free(eap->pending_req_otp);
480                 eap->pending_req_otp = NULL;
481                 eap->pending_req_otp_len = 0;
482         } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
483                 os_free(eap->private_key_passwd);
484                 eap->private_key_passwd = (u8 *) os_strdup(pos);
485                 eap->pending_req_passphrase = 0;
486                 if (ssid == wpa_s->current_ssid)
487                         wpa_s->reassociate = 1;
488         } else {
489                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
490                 return -1;
491         }
492
493         return 0;
494 #else /* IEEE8021X_EAPOL */
495         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
496         return -1;
497 #endif /* IEEE8021X_EAPOL */
498 }
499
500
501 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
502                                             const char *params,
503                                             char *buf, size_t buflen)
504 {
505         char *pos, *end, tmp[30];
506         int res, verbose, ret;
507
508         verbose = os_strcmp(params, "-VERBOSE") == 0;
509         pos = buf;
510         end = buf + buflen;
511         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
512                 struct wpa_ssid *ssid = wpa_s->current_ssid;
513                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
514                                   MAC2STR(wpa_s->bssid));
515                 if (ret < 0 || ret >= end - pos)
516                         return pos - buf;
517                 pos += ret;
518                 if (ssid) {
519                         u8 *_ssid = ssid->ssid;
520                         size_t ssid_len = ssid->ssid_len;
521                         u8 ssid_buf[MAX_SSID_LEN];
522                         if (ssid_len == 0) {
523                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
524                                 if (_res < 0)
525                                         ssid_len = 0;
526                                 else
527                                         ssid_len = _res;
528                                 _ssid = ssid_buf;
529                         }
530                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
531                                           wpa_ssid_txt(_ssid, ssid_len),
532                                           ssid->id);
533                         if (ret < 0 || ret >= end - pos)
534                                 return pos - buf;
535                         pos += ret;
536
537                         if (ssid->id_str) {
538                                 ret = os_snprintf(pos, end - pos,
539                                                   "id_str=%s\n",
540                                                   ssid->id_str);
541                                 if (ret < 0 || ret >= end - pos)
542                                         return pos - buf;
543                                 pos += ret;
544                         }
545
546                         switch (ssid->mode) {
547                         case WPAS_MODE_INFRA:
548                                 ret = os_snprintf(pos, end - pos,
549                                                   "mode=station\n");
550                                 break;
551                         case WPAS_MODE_IBSS:
552                                 ret = os_snprintf(pos, end - pos,
553                                                   "mode=IBSS\n");
554                                 break;
555                         case WPAS_MODE_AP:
556                                 ret = os_snprintf(pos, end - pos,
557                                                   "mode=AP\n");
558                                 break;
559                         case WPAS_MODE_P2P_GO:
560                                 ret = os_snprintf(pos, end - pos,
561                                                   "mode=P2P GO\n");
562                                 break;
563                         case WPAS_MODE_P2P_GROUP_FORMATION:
564                                 ret = os_snprintf(pos, end - pos,
565                                                   "mode=P2P GO - group "
566                                                   "formation\n");
567                                 break;
568                         default:
569                                 ret = 0;
570                                 break;
571                         }
572                         if (ret < 0 || ret >= end - pos)
573                                 return pos - buf;
574                         pos += ret;
575                 }
576
577 #ifdef CONFIG_AP
578                 if (wpa_s->ap_iface) {
579                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
580                                                             end - pos,
581                                                             verbose);
582                 } else
583 #endif /* CONFIG_AP */
584                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
585         }
586         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
587                           wpa_supplicant_state_txt(wpa_s->wpa_state));
588         if (ret < 0 || ret >= end - pos)
589                 return pos - buf;
590         pos += ret;
591
592         if (wpa_s->l2 &&
593             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
594                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
595                 if (ret < 0 || ret >= end - pos)
596                         return pos - buf;
597                 pos += ret;
598         }
599
600         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
601             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
602                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
603                                           verbose);
604                 if (res >= 0)
605                         pos += res;
606         }
607
608         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
609         if (res >= 0)
610                 pos += res;
611
612         return pos - buf;
613 }
614
615
616 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
617                                            char *cmd)
618 {
619         char *pos;
620         int id;
621         struct wpa_ssid *ssid;
622         u8 bssid[ETH_ALEN];
623
624         /* cmd: "<network id> <BSSID>" */
625         pos = os_strchr(cmd, ' ');
626         if (pos == NULL)
627                 return -1;
628         *pos++ = '\0';
629         id = atoi(cmd);
630         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
631         if (hwaddr_aton(pos, bssid)) {
632                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
633                 return -1;
634         }
635
636         ssid = wpa_config_get_network(wpa_s->conf, id);
637         if (ssid == NULL) {
638                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
639                            "to update", id);
640                 return -1;
641         }
642
643         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
644         ssid->bssid_set = !is_zero_ether_addr(bssid);
645
646         return 0;
647 }
648
649
650 static int wpa_supplicant_ctrl_iface_list_networks(
651         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
652 {
653         char *pos, *end;
654         struct wpa_ssid *ssid;
655         int ret;
656
657         pos = buf;
658         end = buf + buflen;
659         ret = os_snprintf(pos, end - pos,
660                           "network id / ssid / bssid / flags\n");
661         if (ret < 0 || ret >= end - pos)
662                 return pos - buf;
663         pos += ret;
664
665         ssid = wpa_s->conf->ssid;
666         while (ssid) {
667                 ret = os_snprintf(pos, end - pos, "%d\t%s",
668                                   ssid->id,
669                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
670                 if (ret < 0 || ret >= end - pos)
671                         return pos - buf;
672                 pos += ret;
673                 if (ssid->bssid_set) {
674                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
675                                           MAC2STR(ssid->bssid));
676                 } else {
677                         ret = os_snprintf(pos, end - pos, "\tany");
678                 }
679                 if (ret < 0 || ret >= end - pos)
680                         return pos - buf;
681                 pos += ret;
682                 ret = os_snprintf(pos, end - pos, "\t%s%s%s",
683                                   ssid == wpa_s->current_ssid ?
684                                   "[CURRENT]" : "",
685                                   ssid->disabled ? "[DISABLED]" : "",
686                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
687                                   "");
688                 if (ret < 0 || ret >= end - pos)
689                         return pos - buf;
690                 pos += ret;
691                 ret = os_snprintf(pos, end - pos, "\n");
692                 if (ret < 0 || ret >= end - pos)
693                         return pos - buf;
694                 pos += ret;
695
696                 ssid = ssid->next;
697         }
698
699         return pos - buf;
700 }
701
702
703 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
704 {
705         int first = 1, ret;
706         ret = os_snprintf(pos, end - pos, "-");
707         if (ret < 0 || ret >= end - pos)
708                 return pos;
709         pos += ret;
710         if (cipher & WPA_CIPHER_NONE) {
711                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
712                 if (ret < 0 || ret >= end - pos)
713                         return pos;
714                 pos += ret;
715                 first = 0;
716         }
717         if (cipher & WPA_CIPHER_WEP40) {
718                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
719                 if (ret < 0 || ret >= end - pos)
720                         return pos;
721                 pos += ret;
722                 first = 0;
723         }
724         if (cipher & WPA_CIPHER_WEP104) {
725                 ret = os_snprintf(pos, end - pos, "%sWEP104",
726                                   first ? "" : "+");
727                 if (ret < 0 || ret >= end - pos)
728                         return pos;
729                 pos += ret;
730                 first = 0;
731         }
732         if (cipher & WPA_CIPHER_TKIP) {
733                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
734                 if (ret < 0 || ret >= end - pos)
735                         return pos;
736                 pos += ret;
737                 first = 0;
738         }
739         if (cipher & WPA_CIPHER_CCMP) {
740                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
741                 if (ret < 0 || ret >= end - pos)
742                         return pos;
743                 pos += ret;
744                 first = 0;
745         }
746         return pos;
747 }
748
749
750 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
751                                     const u8 *ie, size_t ie_len)
752 {
753         struct wpa_ie_data data;
754         int first, ret;
755
756         ret = os_snprintf(pos, end - pos, "[%s-", proto);
757         if (ret < 0 || ret >= end - pos)
758                 return pos;
759         pos += ret;
760
761         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
762                 ret = os_snprintf(pos, end - pos, "?]");
763                 if (ret < 0 || ret >= end - pos)
764                         return pos;
765                 pos += ret;
766                 return pos;
767         }
768
769         first = 1;
770         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
771                 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
772                 if (ret < 0 || ret >= end - pos)
773                         return pos;
774                 pos += ret;
775                 first = 0;
776         }
777         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
778                 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
779                 if (ret < 0 || ret >= end - pos)
780                         return pos;
781                 pos += ret;
782                 first = 0;
783         }
784         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
785                 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
786                 if (ret < 0 || ret >= end - pos)
787                         return pos;
788                 pos += ret;
789                 first = 0;
790         }
791 #ifdef CONFIG_IEEE80211R
792         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
793                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
794                                   first ? "" : "+");
795                 if (ret < 0 || ret >= end - pos)
796                         return pos;
797                 pos += ret;
798                 first = 0;
799         }
800         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
801                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
802                                   first ? "" : "+");
803                 if (ret < 0 || ret >= end - pos)
804                         return pos;
805                 pos += ret;
806                 first = 0;
807         }
808 #endif /* CONFIG_IEEE80211R */
809 #ifdef CONFIG_IEEE80211W
810         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
811                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
812                                   first ? "" : "+");
813                 if (ret < 0 || ret >= end - pos)
814                         return pos;
815                 pos += ret;
816                 first = 0;
817         }
818         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
819                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
820                                   first ? "" : "+");
821                 if (ret < 0 || ret >= end - pos)
822                         return pos;
823                 pos += ret;
824                 first = 0;
825         }
826 #endif /* CONFIG_IEEE80211W */
827
828         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
829
830         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
831                 ret = os_snprintf(pos, end - pos, "-preauth");
832                 if (ret < 0 || ret >= end - pos)
833                         return pos;
834                 pos += ret;
835         }
836
837         ret = os_snprintf(pos, end - pos, "]");
838         if (ret < 0 || ret >= end - pos)
839                 return pos;
840         pos += ret;
841
842         return pos;
843 }
844
845
846 #ifdef CONFIG_WPS
847 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
848                                             char *pos, char *end,
849                                             struct wpabuf *wps_ie)
850 {
851         int ret;
852         const char *txt;
853
854         if (wps_ie == NULL)
855                 return pos;
856         if (wps_is_selected_pbc_registrar(wps_ie))
857                 txt = "[WPS-PBC]";
858 #ifdef CONFIG_WPS2
859         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
860                 txt = "[WPS-AUTH]";
861 #endif /* CONFIG_WPS2 */
862         else if (wps_is_selected_pin_registrar(wps_ie))
863                 txt = "[WPS-PIN]";
864         else
865                 txt = "[WPS]";
866
867         ret = os_snprintf(pos, end - pos, "%s", txt);
868         if (ret >= 0 && ret < end - pos)
869                 pos += ret;
870         wpabuf_free(wps_ie);
871         return pos;
872 }
873 #endif /* CONFIG_WPS */
874
875
876 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
877                                         char *pos, char *end,
878                                         const struct wpa_bss *bss)
879 {
880 #ifdef CONFIG_WPS
881         struct wpabuf *wps_ie;
882         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
883         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
884 #else /* CONFIG_WPS */
885         return pos;
886 #endif /* CONFIG_WPS */
887 }
888
889
890 /* Format one result on one text line into a buffer. */
891 static int wpa_supplicant_ctrl_iface_scan_result(
892         struct wpa_supplicant *wpa_s,
893         const struct wpa_bss *bss, char *buf, size_t buflen)
894 {
895         char *pos, *end;
896         int ret;
897         const u8 *ie, *ie2;
898
899         pos = buf;
900         end = buf + buflen;
901
902         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
903                           MAC2STR(bss->bssid), bss->freq, bss->level);
904         if (ret < 0 || ret >= end - pos)
905                 return pos - buf;
906         pos += ret;
907         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
908         if (ie)
909                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
910         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
911         if (ie2)
912                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
913         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
914         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
915                 ret = os_snprintf(pos, end - pos, "[WEP]");
916                 if (ret < 0 || ret >= end - pos)
917                         return pos - buf;
918                 pos += ret;
919         }
920         if (bss->caps & IEEE80211_CAP_IBSS) {
921                 ret = os_snprintf(pos, end - pos, "[IBSS]");
922                 if (ret < 0 || ret >= end - pos)
923                         return pos - buf;
924                 pos += ret;
925         }
926         if (bss->caps & IEEE80211_CAP_ESS) {
927                 ret = os_snprintf(pos, end - pos, "[ESS]");
928                 if (ret < 0 || ret >= end - pos)
929                         return pos - buf;
930                 pos += ret;
931         }
932
933         ret = os_snprintf(pos, end - pos, "\t%s",
934                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
935         if (ret < 0 || ret >= end - pos)
936                 return pos - buf;
937         pos += ret;
938
939         ret = os_snprintf(pos, end - pos, "\n");
940         if (ret < 0 || ret >= end - pos)
941                 return pos - buf;
942         pos += ret;
943
944         return pos - buf;
945 }
946
947
948 static int wpa_supplicant_ctrl_iface_scan_results(
949         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
950 {
951         char *pos, *end;
952         struct wpa_bss *bss;
953         int ret;
954
955         pos = buf;
956         end = buf + buflen;
957         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
958                           "flags / ssid\n");
959         if (ret < 0 || ret >= end - pos)
960                 return pos - buf;
961         pos += ret;
962
963         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
964                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
965                                                             end - pos);
966                 if (ret < 0 || ret >= end - pos)
967                         return pos - buf;
968                 pos += ret;
969         }
970
971         return pos - buf;
972 }
973
974
975 static int wpa_supplicant_ctrl_iface_select_network(
976         struct wpa_supplicant *wpa_s, char *cmd)
977 {
978         int id;
979         struct wpa_ssid *ssid;
980
981         /* cmd: "<network id>" or "any" */
982         if (os_strcmp(cmd, "any") == 0) {
983                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
984                 ssid = NULL;
985         } else {
986                 id = atoi(cmd);
987                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
988
989                 ssid = wpa_config_get_network(wpa_s->conf, id);
990                 if (ssid == NULL) {
991                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
992                                    "network id=%d", id);
993                         return -1;
994                 }
995                 if (ssid->disabled == 2) {
996                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
997                                    "SELECT_NETWORK with persistent P2P group");
998                         return -1;
999                 }
1000         }
1001
1002         wpa_supplicant_select_network(wpa_s, ssid);
1003
1004         return 0;
1005 }
1006
1007
1008 static int wpa_supplicant_ctrl_iface_enable_network(
1009         struct wpa_supplicant *wpa_s, char *cmd)
1010 {
1011         int id;
1012         struct wpa_ssid *ssid;
1013
1014         /* cmd: "<network id>" or "all" */
1015         if (os_strcmp(cmd, "all") == 0) {
1016                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1017                 ssid = NULL;
1018         } else {
1019                 id = atoi(cmd);
1020                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1021
1022                 ssid = wpa_config_get_network(wpa_s->conf, id);
1023                 if (ssid == NULL) {
1024                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1025                                    "network id=%d", id);
1026                         return -1;
1027                 }
1028                 if (ssid->disabled == 2) {
1029                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1030                                    "ENABLE_NETWORK with persistent P2P group");
1031                         return -1;
1032                 }
1033         }
1034         wpa_supplicant_enable_network(wpa_s, ssid);
1035
1036         return 0;
1037 }
1038
1039
1040 static int wpa_supplicant_ctrl_iface_disable_network(
1041         struct wpa_supplicant *wpa_s, char *cmd)
1042 {
1043         int id;
1044         struct wpa_ssid *ssid;
1045
1046         /* cmd: "<network id>" or "all" */
1047         if (os_strcmp(cmd, "all") == 0) {
1048                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1049                 ssid = NULL;
1050         } else {
1051                 id = atoi(cmd);
1052                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1053
1054                 ssid = wpa_config_get_network(wpa_s->conf, id);
1055                 if (ssid == NULL) {
1056                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1057                                    "network id=%d", id);
1058                         return -1;
1059                 }
1060                 if (ssid->disabled == 2) {
1061                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1062                                    "DISABLE_NETWORK with persistent P2P "
1063                                    "group");
1064                         return -1;
1065                 }
1066         }
1067         wpa_supplicant_disable_network(wpa_s, ssid);
1068
1069         return 0;
1070 }
1071
1072
1073 static int wpa_supplicant_ctrl_iface_add_network(
1074         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1075 {
1076         struct wpa_ssid *ssid;
1077         int ret;
1078
1079         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1080
1081         ssid = wpa_config_add_network(wpa_s->conf);
1082         if (ssid == NULL)
1083                 return -1;
1084
1085         wpas_notify_network_added(wpa_s, ssid);
1086
1087         ssid->disabled = 1;
1088         wpa_config_set_network_defaults(ssid);
1089
1090         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1091         if (ret < 0 || (size_t) ret >= buflen)
1092                 return -1;
1093         return ret;
1094 }
1095
1096
1097 static int wpa_supplicant_ctrl_iface_remove_network(
1098         struct wpa_supplicant *wpa_s, char *cmd)
1099 {
1100         int id;
1101         struct wpa_ssid *ssid;
1102
1103         /* cmd: "<network id>" or "all" */
1104         if (os_strcmp(cmd, "all") == 0) {
1105                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1106                 ssid = wpa_s->conf->ssid;
1107                 while (ssid) {
1108                         struct wpa_ssid *remove_ssid = ssid;
1109                         id = ssid->id;
1110                         ssid = ssid->next;
1111                         wpas_notify_network_removed(wpa_s, remove_ssid);
1112                         wpa_config_remove_network(wpa_s->conf, id);
1113                 }
1114                 if (wpa_s->current_ssid) {
1115                         eapol_sm_invalidate_cached_session(wpa_s->eapol);
1116                         wpa_supplicant_disassociate(wpa_s,
1117                                                     WLAN_REASON_DEAUTH_LEAVING);
1118                 }
1119                 return 0;
1120         }
1121
1122         id = atoi(cmd);
1123         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1124
1125         ssid = wpa_config_get_network(wpa_s->conf, id);
1126         if (ssid == NULL ||
1127             wpa_config_remove_network(wpa_s->conf, id) < 0) {
1128                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1129                            "id=%d", id);
1130                 return -1;
1131         }
1132
1133         if (ssid == wpa_s->current_ssid) {
1134                 /*
1135                  * Invalidate the EAP session cache if the current network is
1136                  * removed.
1137                  */
1138                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1139
1140                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1141         }
1142
1143         return 0;
1144 }
1145
1146
1147 static int wpa_supplicant_ctrl_iface_set_network(
1148         struct wpa_supplicant *wpa_s, char *cmd)
1149 {
1150         int id;
1151         struct wpa_ssid *ssid;
1152         char *name, *value;
1153
1154         /* cmd: "<network id> <variable name> <value>" */
1155         name = os_strchr(cmd, ' ');
1156         if (name == NULL)
1157                 return -1;
1158         *name++ = '\0';
1159
1160         value = os_strchr(name, ' ');
1161         if (value == NULL)
1162                 return -1;
1163         *value++ = '\0';
1164
1165         id = atoi(cmd);
1166         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1167                    id, name);
1168         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1169                               (u8 *) value, os_strlen(value));
1170
1171         ssid = wpa_config_get_network(wpa_s->conf, id);
1172         if (ssid == NULL) {
1173                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1174                            "id=%d", id);
1175                 return -1;
1176         }
1177
1178         if (wpa_config_set(ssid, name, value, 0) < 0) {
1179                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1180                            "variable '%s'", name);
1181                 return -1;
1182         }
1183
1184         if (wpa_s->current_ssid == ssid) {
1185                 /*
1186                  * Invalidate the EAP session cache if anything in the current
1187                  * configuration changes.
1188                  */
1189                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1190         }
1191
1192         if ((os_strcmp(name, "psk") == 0 &&
1193              value[0] == '"' && ssid->ssid_len) ||
1194             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1195                 wpa_config_update_psk(ssid);
1196         else if (os_strcmp(name, "priority") == 0)
1197                 wpa_config_update_prio_list(wpa_s->conf);
1198
1199         return 0;
1200 }
1201
1202
1203 static int wpa_supplicant_ctrl_iface_get_network(
1204         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1205 {
1206         int id;
1207         size_t res;
1208         struct wpa_ssid *ssid;
1209         char *name, *value;
1210
1211         /* cmd: "<network id> <variable name>" */
1212         name = os_strchr(cmd, ' ');
1213         if (name == NULL || buflen == 0)
1214                 return -1;
1215         *name++ = '\0';
1216
1217         id = atoi(cmd);
1218         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1219                    id, name);
1220
1221         ssid = wpa_config_get_network(wpa_s->conf, id);
1222         if (ssid == NULL) {
1223                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1224                            "id=%d", id);
1225                 return -1;
1226         }
1227
1228         value = wpa_config_get_no_key(ssid, name);
1229         if (value == NULL) {
1230                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1231                            "variable '%s'", name);
1232                 return -1;
1233         }
1234
1235         res = os_strlcpy(buf, value, buflen);
1236         if (res >= buflen) {
1237                 os_free(value);
1238                 return -1;
1239         }
1240
1241         os_free(value);
1242
1243         return res;
1244 }
1245
1246
1247 #ifndef CONFIG_NO_CONFIG_WRITE
1248 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
1249 {
1250         int ret;
1251
1252         if (!wpa_s->conf->update_config) {
1253                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
1254                            "to update configuration (update_config=0)");
1255                 return -1;
1256         }
1257
1258         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
1259         if (ret) {
1260                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
1261                            "update configuration");
1262         } else {
1263                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
1264                            " updated");
1265         }
1266
1267         return ret;
1268 }
1269 #endif /* CONFIG_NO_CONFIG_WRITE */
1270
1271
1272 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
1273                                               struct wpa_driver_capa *capa,
1274                                               char *buf, size_t buflen)
1275 {
1276         int ret, first = 1;
1277         char *pos, *end;
1278         size_t len;
1279
1280         pos = buf;
1281         end = pos + buflen;
1282
1283         if (res < 0) {
1284                 if (strict)
1285                         return 0;
1286                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
1287                 if (len >= buflen)
1288                         return -1;
1289                 return len;
1290         }
1291
1292         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1293                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1294                 if (ret < 0 || ret >= end - pos)
1295                         return pos - buf;
1296                 pos += ret;
1297                 first = 0;
1298         }
1299
1300         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1301                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1302                 if (ret < 0 || ret >= end - pos)
1303                         return pos - buf;
1304                 pos += ret;
1305                 first = 0;
1306         }
1307
1308         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1309                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
1310                 if (ret < 0 || ret >= end - pos)
1311                         return pos - buf;
1312                 pos += ret;
1313                 first = 0;
1314         }
1315
1316         return pos - buf;
1317 }
1318
1319
1320 static int ctrl_iface_get_capability_group(int res, char *strict,
1321                                            struct wpa_driver_capa *capa,
1322                                            char *buf, size_t buflen)
1323 {
1324         int ret, first = 1;
1325         char *pos, *end;
1326         size_t len;
1327
1328         pos = buf;
1329         end = pos + buflen;
1330
1331         if (res < 0) {
1332                 if (strict)
1333                         return 0;
1334                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
1335                 if (len >= buflen)
1336                         return -1;
1337                 return len;
1338         }
1339
1340         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1341                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
1342                 if (ret < 0 || ret >= end - pos)
1343                         return pos - buf;
1344                 pos += ret;
1345                 first = 0;
1346         }
1347
1348         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1349                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
1350                 if (ret < 0 || ret >= end - pos)
1351                         return pos - buf;
1352                 pos += ret;
1353                 first = 0;
1354         }
1355
1356         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1357                 ret = os_snprintf(pos, end - pos, "%sWEP104",
1358                                   first ? "" : " ");
1359                 if (ret < 0 || ret >= end - pos)
1360                         return pos - buf;
1361                 pos += ret;
1362                 first = 0;
1363         }
1364
1365         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1366                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
1367                 if (ret < 0 || ret >= end - pos)
1368                         return pos - buf;
1369                 pos += ret;
1370                 first = 0;
1371         }
1372
1373         return pos - buf;
1374 }
1375
1376
1377 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
1378                                               struct wpa_driver_capa *capa,
1379                                               char *buf, size_t buflen)
1380 {
1381         int ret;
1382         char *pos, *end;
1383         size_t len;
1384
1385         pos = buf;
1386         end = pos + buflen;
1387
1388         if (res < 0) {
1389                 if (strict)
1390                         return 0;
1391                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
1392                                  "NONE", buflen);
1393                 if (len >= buflen)
1394                         return -1;
1395                 return len;
1396         }
1397
1398         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
1399         if (ret < 0 || ret >= end - pos)
1400                 return pos - buf;
1401         pos += ret;
1402
1403         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1404                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1405                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
1406                 if (ret < 0 || ret >= end - pos)
1407                         return pos - buf;
1408                 pos += ret;
1409         }
1410
1411         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1412                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1413                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
1414                 if (ret < 0 || ret >= end - pos)
1415                         return pos - buf;
1416                 pos += ret;
1417         }
1418
1419         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1420                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
1421                 if (ret < 0 || ret >= end - pos)
1422                         return pos - buf;
1423                 pos += ret;
1424         }
1425
1426         return pos - buf;
1427 }
1428
1429
1430 static int ctrl_iface_get_capability_proto(int res, char *strict,
1431                                            struct wpa_driver_capa *capa,
1432                                            char *buf, size_t buflen)
1433 {
1434         int ret, first = 1;
1435         char *pos, *end;
1436         size_t len;
1437
1438         pos = buf;
1439         end = pos + buflen;
1440
1441         if (res < 0) {
1442                 if (strict)
1443                         return 0;
1444                 len = os_strlcpy(buf, "RSN WPA", buflen);
1445                 if (len >= buflen)
1446                         return -1;
1447                 return len;
1448         }
1449
1450         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1451                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1452                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
1453                 if (ret < 0 || ret >= end - pos)
1454                         return pos - buf;
1455                 pos += ret;
1456                 first = 0;
1457         }
1458
1459         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1460                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1461                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
1462                 if (ret < 0 || ret >= end - pos)
1463                         return pos - buf;
1464                 pos += ret;
1465                 first = 0;
1466         }
1467
1468         return pos - buf;
1469 }
1470
1471
1472 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
1473                                               struct wpa_driver_capa *capa,
1474                                               char *buf, size_t buflen)
1475 {
1476         int ret, first = 1;
1477         char *pos, *end;
1478         size_t len;
1479
1480         pos = buf;
1481         end = pos + buflen;
1482
1483         if (res < 0) {
1484                 if (strict)
1485                         return 0;
1486                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
1487                 if (len >= buflen)
1488                         return -1;
1489                 return len;
1490         }
1491
1492         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
1493                 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
1494                 if (ret < 0 || ret >= end - pos)
1495                         return pos - buf;
1496                 pos += ret;
1497                 first = 0;
1498         }
1499
1500         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
1501                 ret = os_snprintf(pos, end - pos, "%sSHARED",
1502                                   first ? "" : " ");
1503                 if (ret < 0 || ret >= end - pos)
1504                         return pos - buf;
1505                 pos += ret;
1506                 first = 0;
1507         }
1508
1509         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
1510                 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
1511                 if (ret < 0 || ret >= end - pos)
1512                         return pos - buf;
1513                 pos += ret;
1514                 first = 0;
1515         }
1516
1517         return pos - buf;
1518 }
1519
1520
1521 static int wpa_supplicant_ctrl_iface_get_capability(
1522         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
1523         size_t buflen)
1524 {
1525         struct wpa_driver_capa capa;
1526         int res;
1527         char *strict;
1528         char field[30];
1529         size_t len;
1530
1531         /* Determine whether or not strict checking was requested */
1532         len = os_strlcpy(field, _field, sizeof(field));
1533         if (len >= sizeof(field))
1534                 return -1;
1535         strict = os_strchr(field, ' ');
1536         if (strict != NULL) {
1537                 *strict++ = '\0';
1538                 if (os_strcmp(strict, "strict") != 0)
1539                         return -1;
1540         }
1541
1542         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
1543                 field, strict ? strict : "");
1544
1545         if (os_strcmp(field, "eap") == 0) {
1546                 return eap_get_names(buf, buflen);
1547         }
1548
1549         res = wpa_drv_get_capa(wpa_s, &capa);
1550
1551         if (os_strcmp(field, "pairwise") == 0)
1552                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
1553                                                           buf, buflen);
1554
1555         if (os_strcmp(field, "group") == 0)
1556                 return ctrl_iface_get_capability_group(res, strict, &capa,
1557                                                        buf, buflen);
1558
1559         if (os_strcmp(field, "key_mgmt") == 0)
1560                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
1561                                                           buf, buflen);
1562
1563         if (os_strcmp(field, "proto") == 0)
1564                 return ctrl_iface_get_capability_proto(res, strict, &capa,
1565                                                        buf, buflen);
1566
1567         if (os_strcmp(field, "auth_alg") == 0)
1568                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
1569                                                           buf, buflen);
1570
1571         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
1572                    field);
1573
1574         return -1;
1575 }
1576
1577
1578 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
1579                                          const char *cmd, char *buf,
1580                                          size_t buflen)
1581 {
1582         u8 bssid[ETH_ALEN];
1583         size_t i;
1584         struct wpa_bss *bss;
1585         int ret;
1586         char *pos, *end;
1587         const u8 *ie, *ie2;
1588
1589         if (os_strcmp(cmd, "FIRST") == 0)
1590                 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
1591         else if (os_strncmp(cmd, "ID-", 3) == 0) {
1592                 i = atoi(cmd + 3);
1593                 bss = wpa_bss_get_id(wpa_s, i);
1594         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
1595                 i = atoi(cmd + 5);
1596                 bss = wpa_bss_get_id(wpa_s, i);
1597                 if (bss) {
1598                         struct dl_list *next = bss->list_id.next;
1599                         if (next == &wpa_s->bss_id)
1600                                 bss = NULL;
1601                         else
1602                                 bss = dl_list_entry(next, struct wpa_bss,
1603                                                     list_id);
1604                 }
1605         } else if (hwaddr_aton(cmd, bssid) == 0)
1606                 bss = wpa_bss_get_bssid(wpa_s, bssid);
1607         else {
1608                 struct wpa_bss *tmp;
1609                 i = atoi(cmd);
1610                 bss = NULL;
1611                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
1612                 {
1613                         if (i-- == 0) {
1614                                 bss = tmp;
1615                                 break;
1616                         }
1617                 }
1618         }
1619
1620         if (bss == NULL)
1621                 return 0;
1622
1623         pos = buf;
1624         end = buf + buflen;
1625         ret = os_snprintf(pos, end - pos,
1626                           "id=%u\n"
1627                           "bssid=" MACSTR "\n"
1628                           "freq=%d\n"
1629                           "beacon_int=%d\n"
1630                           "capabilities=0x%04x\n"
1631                           "qual=%d\n"
1632                           "noise=%d\n"
1633                           "level=%d\n"
1634                           "tsf=%016llu\n"
1635                           "ie=",
1636                           bss->id,
1637                           MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
1638                           bss->caps, bss->qual, bss->noise, bss->level,
1639                           (unsigned long long) bss->tsf);
1640         if (ret < 0 || ret >= end - pos)
1641                 return pos - buf;
1642         pos += ret;
1643
1644         ie = (const u8 *) (bss + 1);
1645         for (i = 0; i < bss->ie_len; i++) {
1646                 ret = os_snprintf(pos, end - pos, "%02x", *ie++);
1647                 if (ret < 0 || ret >= end - pos)
1648                         return pos - buf;
1649                 pos += ret;
1650         }
1651
1652         ret = os_snprintf(pos, end - pos, "\n");
1653         if (ret < 0 || ret >= end - pos)
1654                 return pos - buf;
1655         pos += ret;
1656
1657         ret = os_snprintf(pos, end - pos, "flags=");
1658         if (ret < 0 || ret >= end - pos)
1659                 return pos - buf;
1660         pos += ret;
1661
1662         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1663         if (ie)
1664                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1665         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1666         if (ie2)
1667                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1668         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1669         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1670                 ret = os_snprintf(pos, end - pos, "[WEP]");
1671                 if (ret < 0 || ret >= end - pos)
1672                         return pos - buf;
1673                 pos += ret;
1674         }
1675         if (bss->caps & IEEE80211_CAP_IBSS) {
1676                 ret = os_snprintf(pos, end - pos, "[IBSS]");
1677                 if (ret < 0 || ret >= end - pos)
1678                         return pos - buf;
1679                 pos += ret;
1680         }
1681         if (bss->caps & IEEE80211_CAP_ESS) {
1682                 ret = os_snprintf(pos, end - pos, "[ESS]");
1683                 if (ret < 0 || ret >= end - pos)
1684                         return pos - buf;
1685                 pos += ret;
1686         }
1687
1688         ret = os_snprintf(pos, end - pos, "\n");
1689         if (ret < 0 || ret >= end - pos)
1690                 return pos - buf;
1691         pos += ret;
1692
1693         ret = os_snprintf(pos, end - pos, "ssid=%s\n",
1694                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
1695         if (ret < 0 || ret >= end - pos)
1696                 return pos - buf;
1697         pos += ret;
1698
1699 #ifdef CONFIG_WPS
1700         ie = (const u8 *) (bss + 1);
1701         ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
1702         if (ret < 0 || ret >= end - pos)
1703                 return pos - buf;
1704         pos += ret;
1705 #endif /* CONFIG_WPS */
1706
1707         return pos - buf;
1708 }
1709
1710
1711 static int wpa_supplicant_ctrl_iface_ap_scan(
1712         struct wpa_supplicant *wpa_s, char *cmd)
1713 {
1714         int ap_scan = atoi(cmd);
1715         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
1716 }
1717
1718
1719 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
1720 {
1721         u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff";
1722
1723         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
1724         /* MLME-DELETEKEYS.request */
1725         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0);
1726         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0);
1727         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0);
1728         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0);
1729 #ifdef CONFIG_IEEE80211W
1730         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 4, 0, NULL, 0, NULL, 0);
1731         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 5, 0, NULL, 0, NULL, 0);
1732 #endif /* CONFIG_IEEE80211W */
1733
1734         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
1735                         0);
1736         /* MLME-SETPROTECTION.request(None) */
1737         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
1738                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
1739                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
1740         wpa_sm_drop_sa(wpa_s->wpa);
1741 }
1742
1743
1744 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
1745                                           char *addr)
1746 {
1747         u8 bssid[ETH_ALEN];
1748         struct wpa_bss *bss;
1749         struct wpa_ssid *ssid = wpa_s->current_ssid;
1750
1751         if (hwaddr_aton(addr, bssid)) {
1752                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
1753                            "address '%s'", addr);
1754                 return -1;
1755         }
1756
1757         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
1758
1759         bss = wpa_bss_get_bssid(wpa_s, bssid);
1760         if (!bss) {
1761                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
1762                            "from BSS table");
1763                 return -1;
1764         }
1765
1766         /*
1767          * TODO: Find best network configuration block from configuration to
1768          * allow roaming to other networks
1769          */
1770
1771         if (!ssid) {
1772                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
1773                            "configuration known for the target AP");
1774                 return -1;
1775         }
1776
1777         wpa_s->reassociate = 1;
1778         wpa_supplicant_connect(wpa_s, bss, ssid);
1779
1780         return 0;
1781 }
1782
1783
1784 #ifdef CONFIG_P2P
1785 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
1786 {
1787         unsigned int timeout = atoi(cmd);
1788         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
1789
1790         if (os_strstr(cmd, "type=social"))
1791                 type = P2P_FIND_ONLY_SOCIAL;
1792         else if (os_strstr(cmd, "type=progressive"))
1793                 type = P2P_FIND_PROGRESSIVE;
1794
1795         wpas_p2p_find(wpa_s, timeout, type);
1796         return 0;
1797 }
1798
1799
1800 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
1801                             char *buf, size_t buflen)
1802 {
1803         u8 addr[ETH_ALEN];
1804         char *pos, *pos2;
1805         char *pin = NULL;
1806         enum p2p_wps_method wps_method;
1807         int new_pin;
1808         int ret;
1809         int persistent_group;
1810         int join;
1811         int auth;
1812         int go_intent = -1;
1813         int freq = 0;
1814
1815         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
1816          * [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
1817
1818         if (hwaddr_aton(cmd, addr))
1819                 return -1;
1820
1821         pos = cmd + 17;
1822         if (*pos != ' ')
1823                 return -1;
1824         pos++;
1825
1826         persistent_group = os_strstr(pos, " persistent") != NULL;
1827         join = os_strstr(pos, " join") != NULL;
1828         auth = os_strstr(pos, " auth") != NULL;
1829
1830         pos2 = os_strstr(pos, " go_intent=");
1831         if (pos2) {
1832                 pos2 += 11;
1833                 go_intent = atoi(pos2);
1834                 if (go_intent < 0 || go_intent > 15)
1835                         return -1;
1836         }
1837
1838         pos2 = os_strstr(pos, " freq=");
1839         if (pos2) {
1840                 pos2 += 6;
1841                 freq = atoi(pos2);
1842                 if (freq <= 0)
1843                         return -1;
1844         }
1845
1846         if (os_strncmp(pos, "pin", 3) == 0) {
1847                 /* Request random PIN (to be displayed) and enable the PIN */
1848                 wps_method = WPS_PIN_DISPLAY;
1849         } else if (os_strncmp(pos, "pbc", 3) == 0) {
1850                 wps_method = WPS_PBC;
1851         } else {
1852                 pin = pos;
1853                 pos = os_strchr(pin, ' ');
1854                 wps_method = WPS_PIN_KEYPAD;
1855                 if (pos) {
1856                         *pos++ = '\0';
1857                         if (os_strncmp(pos, "label", 5) == 0)
1858                                 wps_method = WPS_PIN_LABEL;
1859                         else if (os_strncmp(pos, "display", 7) == 0)
1860                                 wps_method = WPS_PIN_DISPLAY;
1861                 }
1862         }
1863
1864         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
1865                                    persistent_group, join, auth, go_intent,
1866                                    freq);
1867         if (new_pin < 0)
1868                 return -1;
1869         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
1870                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
1871                 if (ret < 0 || (size_t) ret >= buflen)
1872                         return -1;
1873                 return ret;
1874         }
1875
1876         os_memcpy(buf, "OK\n", 3);
1877         return 3;
1878 }
1879
1880
1881 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
1882 {
1883         unsigned int timeout = atoi(cmd);
1884         return wpas_p2p_listen(wpa_s, timeout);
1885 }
1886
1887
1888 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
1889 {
1890         u8 addr[ETH_ALEN];
1891         char *pos;
1892
1893         /* <addr> <config method> */
1894
1895         if (hwaddr_aton(cmd, addr))
1896                 return -1;
1897
1898         pos = cmd + 17;
1899         if (*pos != ' ')
1900                 return -1;
1901         pos++;
1902
1903         return wpas_p2p_prov_disc(wpa_s, addr, pos);
1904 }
1905
1906
1907 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
1908                               size_t buflen)
1909 {
1910         struct wpa_ssid *ssid = wpa_s->current_ssid;
1911
1912         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
1913             ssid->passphrase == NULL)
1914                 return -1;
1915
1916         os_strlcpy(buf, ssid->passphrase, buflen);
1917         return os_strlen(buf);
1918 }
1919
1920
1921 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
1922                                   char *buf, size_t buflen)
1923 {
1924         u64 ref;
1925         int res;
1926         u8 dst_buf[ETH_ALEN], *dst;
1927         struct wpabuf *tlvs;
1928         char *pos;
1929         size_t len;
1930
1931         if (hwaddr_aton(cmd, dst_buf))
1932                 return -1;
1933         dst = dst_buf;
1934         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
1935             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
1936                 dst = NULL;
1937         pos = cmd + 17;
1938         if (*pos != ' ')
1939                 return -1;
1940         pos++;
1941
1942         if (os_strncmp(pos, "upnp ", 5) == 0) {
1943                 u8 version;
1944                 pos += 5;
1945                 if (hexstr2bin(pos, &version, 1) < 0)
1946                         return -1;
1947                 pos += 2;
1948                 if (*pos != ' ')
1949                         return -1;
1950                 pos++;
1951                 ref = (u64) wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
1952         } else {
1953                 len = os_strlen(pos);
1954                 if (len & 1)
1955                         return -1;
1956                 len /= 2;
1957                 tlvs = wpabuf_alloc(len);
1958                 if (tlvs == NULL)
1959                         return -1;
1960                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
1961                         wpabuf_free(tlvs);
1962                         return -1;
1963                 }
1964
1965                 ref = (u64) wpas_p2p_sd_request(wpa_s, dst, tlvs);
1966                 wpabuf_free(tlvs);
1967         }
1968         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
1969         if (res < 0 || (unsigned) res >= buflen)
1970                 return -1;
1971         return res;
1972 }
1973
1974
1975 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
1976                                          char *cmd)
1977 {
1978         long long unsigned val;
1979         u64 req;
1980         if (sscanf(cmd, "%llx", &val) != 1)
1981                 return -1;
1982         req = val;
1983         return wpas_p2p_sd_cancel_request(wpa_s, (void *) req);
1984 }
1985
1986
1987 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
1988 {
1989         int freq;
1990         u8 dst_buf[ETH_ALEN], *dst;
1991         u8 dialog_token;
1992         struct wpabuf *resp_tlvs;
1993         char *pos, *pos2;
1994         size_t len;
1995
1996         pos = os_strchr(cmd, ' ');
1997         if (pos == NULL)
1998                 return -1;
1999         *pos++ = '\0';
2000         freq = atoi(cmd);
2001         if (freq == 0)
2002                 return -1;
2003
2004         if (hwaddr_aton(pos, dst_buf))
2005                 return -1;
2006         dst = dst_buf;
2007         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
2008             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
2009                 dst = NULL;
2010         pos += 17;
2011         if (*pos != ' ')
2012                 return -1;
2013         pos++;
2014
2015         pos2 = os_strchr(pos, ' ');
2016         if (pos2 == NULL)
2017                 return -1;
2018         *pos2++ = '\0';
2019         dialog_token = atoi(pos);
2020
2021         len = os_strlen(pos2);
2022         if (len & 1)
2023                 return -1;
2024         len /= 2;
2025         resp_tlvs = wpabuf_alloc(len);
2026         if (resp_tlvs == NULL)
2027                 return -1;
2028         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
2029                 wpabuf_free(resp_tlvs);
2030                 return -1;
2031         }
2032
2033         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
2034         wpabuf_free(resp_tlvs);
2035         return 0;
2036 }
2037
2038
2039 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
2040                                        char *cmd)
2041 {
2042         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
2043         return 0;
2044 }
2045
2046
2047 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
2048                                         char *cmd)
2049 {
2050         char *pos;
2051         size_t len;
2052         struct wpabuf *query, *resp;
2053
2054         pos = os_strchr(cmd, ' ');
2055         if (pos == NULL)
2056                 return -1;
2057         *pos++ = '\0';
2058
2059         len = os_strlen(cmd);
2060         if (len & 1)
2061                 return -1;
2062         len /= 2;
2063         query = wpabuf_alloc(len);
2064         if (query == NULL)
2065                 return -1;
2066         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2067                 wpabuf_free(query);
2068                 return -1;
2069         }
2070
2071         len = os_strlen(pos);
2072         if (len & 1) {
2073                 wpabuf_free(query);
2074                 return -1;
2075         }
2076         len /= 2;
2077         resp = wpabuf_alloc(len);
2078         if (resp == NULL) {
2079                 wpabuf_free(query);
2080                 return -1;
2081         }
2082         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
2083                 wpabuf_free(query);
2084                 wpabuf_free(resp);
2085                 return -1;
2086         }
2087
2088         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
2089                 wpabuf_free(query);
2090                 wpabuf_free(resp);
2091                 return -1;
2092         }
2093         return 0;
2094 }
2095
2096
2097 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2098 {
2099         char *pos;
2100         u8 version;
2101
2102         pos = os_strchr(cmd, ' ');
2103         if (pos == NULL)
2104                 return -1;
2105         *pos++ = '\0';
2106
2107         if (hexstr2bin(cmd, &version, 1) < 0)
2108                 return -1;
2109
2110         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
2111 }
2112
2113
2114 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
2115 {
2116         char *pos;
2117
2118         pos = os_strchr(cmd, ' ');
2119         if (pos == NULL)
2120                 return -1;
2121         *pos++ = '\0';
2122
2123         if (os_strcmp(cmd, "bonjour") == 0)
2124                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
2125         if (os_strcmp(cmd, "upnp") == 0)
2126                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
2127         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2128         return -1;
2129 }
2130
2131
2132 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
2133                                         char *cmd)
2134 {
2135         size_t len;
2136         struct wpabuf *query;
2137         int ret;
2138
2139         len = os_strlen(cmd);
2140         if (len & 1)
2141                 return -1;
2142         len /= 2;
2143         query = wpabuf_alloc(len);
2144         if (query == NULL)
2145                 return -1;
2146         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
2147                 wpabuf_free(query);
2148                 return -1;
2149         }
2150
2151         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2152         wpabuf_free(query);
2153         return ret;
2154 }
2155
2156
2157 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
2158 {
2159         char *pos;
2160         u8 version;
2161
2162         pos = os_strchr(cmd, ' ');
2163         if (pos == NULL)
2164                 return -1;
2165         *pos++ = '\0';
2166
2167         if (hexstr2bin(cmd, &version, 1) < 0)
2168                 return -1;
2169
2170         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
2171 }
2172
2173
2174 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
2175 {
2176         char *pos;
2177
2178         pos = os_strchr(cmd, ' ');
2179         if (pos == NULL)
2180                 return -1;
2181         *pos++ = '\0';
2182
2183         if (os_strcmp(cmd, "bonjour") == 0)
2184                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
2185         if (os_strcmp(cmd, "upnp") == 0)
2186                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
2187         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
2188         return -1;
2189 }
2190
2191
2192 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
2193 {
2194         u8 addr[ETH_ALEN];
2195
2196         /* <addr> */
2197
2198         if (hwaddr_aton(cmd, addr))
2199                 return -1;
2200
2201         return wpas_p2p_reject(wpa_s, addr);
2202 }
2203
2204
2205 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
2206 {
2207         char *pos;
2208         int id;
2209         struct wpa_ssid *ssid;
2210         u8 peer[ETH_ALEN];
2211
2212         id = atoi(cmd);
2213         pos = os_strstr(cmd, " peer=");
2214         if (pos) {
2215                 pos += 6;
2216                 if (hwaddr_aton(pos, peer))
2217                         return -1;
2218         }
2219         ssid = wpa_config_get_network(wpa_s->conf, id);
2220         if (ssid == NULL || ssid->disabled != 2) {
2221                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2222                            "for persistent P2P group",
2223                            id);
2224                 return -1;
2225         }
2226
2227         return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
2228 }
2229
2230
2231 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
2232 {
2233         char *pos;
2234         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
2235
2236         pos = os_strstr(cmd, " peer=");
2237         if (!pos)
2238                 return -1;
2239
2240         *pos = '\0';
2241         pos += 6;
2242         if (hwaddr_aton(pos, peer)) {
2243                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
2244                 return -1;
2245         }
2246
2247         pos = os_strstr(pos, " go_dev_addr=");
2248         if (pos) {
2249                 pos += 13;
2250                 if (hwaddr_aton(pos, go_dev_addr)) {
2251                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
2252                                    pos);
2253                         return -1;
2254                 }
2255                 go_dev = go_dev_addr;
2256         }
2257
2258         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
2259 }
2260
2261
2262 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
2263 {
2264         if (os_strncmp(cmd, "persistent=", 11) == 0)
2265                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
2266         if (os_strncmp(cmd, "group=", 6) == 0)
2267                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
2268
2269         return -1;
2270 }
2271
2272
2273 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
2274                                          char *cmd, int freq)
2275 {
2276         int id;
2277         struct wpa_ssid *ssid;
2278
2279         id = atoi(cmd);
2280         ssid = wpa_config_get_network(wpa_s->conf, id);
2281         if (ssid == NULL || ssid->disabled != 2) {
2282                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
2283                            "for persistent P2P group",
2284                            id);
2285                 return -1;
2286         }
2287
2288         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq);
2289 }
2290
2291
2292 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
2293 {
2294         int freq = 0;
2295         char *pos;
2296
2297         pos = os_strstr(cmd, "freq=");
2298         if (pos)
2299                 freq = atoi(pos + 5);
2300
2301         if (os_strncmp(cmd, "persistent=", 11) == 0)
2302                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq);
2303         if (os_strcmp(cmd, "persistent") == 0 ||
2304             os_strncmp(cmd, "persistent ", 11) == 0)
2305                 return wpas_p2p_group_add(wpa_s, 1, freq);
2306         if (os_strncmp(cmd, "freq=", 5) == 0)
2307                 return wpas_p2p_group_add(wpa_s, 0, freq);
2308
2309         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
2310                    cmd);
2311         return -1;
2312 }
2313
2314
2315 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
2316                          char *buf, size_t buflen)
2317 {
2318         u8 addr[ETH_ALEN], *addr_ptr;
2319         int next;
2320
2321         if (!wpa_s->global->p2p)
2322                 return -1;
2323
2324         if (os_strcmp(cmd, "FIRST") == 0) {
2325                 addr_ptr = NULL;
2326                 next = 0;
2327         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2328                 if (hwaddr_aton(cmd + 5, addr) < 0)
2329                         return -1;
2330                 addr_ptr = addr;
2331                 next = 1;
2332         } else {
2333                 if (hwaddr_aton(cmd, addr) < 0)
2334                         return -1;
2335                 addr_ptr = addr;
2336                 next = 0;
2337         }
2338
2339         return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next,
2340                                  buf, buflen);
2341 }
2342
2343
2344 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
2345 {
2346         char *param;
2347
2348         if (wpa_s->global->p2p == NULL)
2349                 return -1;
2350
2351         param = os_strchr(cmd, ' ');
2352         if (param == NULL)
2353                 return -1;
2354         *param++ = '\0';
2355
2356         if (os_strcmp(cmd, "discoverability") == 0) {
2357                 p2p_set_client_discoverability(wpa_s->global->p2p,
2358                                                atoi(param));
2359                 return 0;
2360         }
2361
2362         if (os_strcmp(cmd, "managed") == 0) {
2363                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
2364                 return 0;
2365         }
2366
2367         if (os_strcmp(cmd, "listen_channel") == 0) {
2368                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
2369                                               atoi(param));
2370         }
2371
2372         if (os_strcmp(cmd, "ssid_postfix") == 0) {
2373                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
2374                                             os_strlen(param));
2375         }
2376
2377         if (os_strcmp(cmd, "noa") == 0) {
2378                 char *pos;
2379                 int count, start, duration;
2380                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
2381                 count = atoi(param);
2382                 pos = os_strchr(param, ',');
2383                 if (pos == NULL)
2384                         return -1;
2385                 pos++;
2386                 start = atoi(pos);
2387                 pos = os_strchr(pos, ',');
2388                 if (pos == NULL)
2389                         return -1;
2390                 pos++;
2391                 duration = atoi(pos);
2392                 if (count < 0 || count > 255 || start < 0 || duration < 0)
2393                         return -1;
2394                 if (count == 0 && duration > 0)
2395                         return -1;
2396                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
2397                            "start=%d duration=%d", count, start, duration);
2398                 return wpa_drv_set_noa(wpa_s, count, start, duration);
2399         }
2400
2401         if (os_strcmp(cmd, "disabled") == 0) {
2402                 wpa_s->global->p2p_disabled = atoi(param);
2403                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
2404                            wpa_s->global->p2p_disabled ?
2405                            "disabled" : "enabled");
2406                 if (wpa_s->global->p2p_disabled) {
2407                         wpas_p2p_stop_find(wpa_s);
2408                         p2p_flush(wpa_s->global->p2p);
2409                 }
2410                 return 0;
2411         }
2412
2413         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
2414                    cmd);
2415
2416         return -1;
2417 }
2418
2419
2420 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
2421 {
2422         char *pos, *pos2;
2423         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
2424
2425         if (cmd[0]) {
2426                 pos = os_strchr(cmd, ' ');
2427                 if (pos == NULL)
2428                         return -1;
2429                 *pos++ = '\0';
2430                 dur1 = atoi(cmd);
2431
2432                 pos2 = os_strchr(pos, ' ');
2433                 if (pos2)
2434                         *pos2++ = '\0';
2435                 int1 = atoi(pos);
2436         } else
2437                 pos2 = NULL;
2438
2439         if (pos2) {
2440                 pos = os_strchr(pos2, ' ');
2441                 if (pos == NULL)
2442                         return -1;
2443                 *pos++ = '\0';
2444                 dur2 = atoi(pos2);
2445                 int2 = atoi(pos);
2446         }
2447
2448         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
2449 }
2450
2451
2452 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
2453 {
2454         char *pos;
2455         unsigned int period = 0, interval = 0;
2456
2457         if (cmd[0]) {
2458                 pos = os_strchr(cmd, ' ');
2459                 if (pos == NULL)
2460                         return -1;
2461                 *pos++ = '\0';
2462                 period = atoi(cmd);
2463                 interval = atoi(pos);
2464         }
2465
2466         return wpas_p2p_ext_listen(wpa_s, period, interval);
2467 }
2468
2469 #endif /* CONFIG_P2P */
2470
2471
2472 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
2473                                          char *buf, size_t *resp_len)
2474 {
2475         char *reply;
2476         const int reply_size = 4096;
2477         int ctrl_rsp = 0;
2478         int reply_len;
2479
2480         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
2481             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
2482                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
2483                                       (const u8 *) buf, os_strlen(buf));
2484         } else {
2485                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
2486                                   (const u8 *) buf, os_strlen(buf));
2487         }
2488
2489         reply = os_malloc(reply_size);
2490         if (reply == NULL) {
2491                 *resp_len = 1;
2492                 return NULL;
2493         }
2494
2495         os_memcpy(reply, "OK\n", 3);
2496         reply_len = 3;
2497
2498         if (os_strcmp(buf, "PING") == 0) {
2499                 os_memcpy(reply, "PONG\n", 5);
2500                 reply_len = 5;
2501         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
2502                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
2503         } else if (os_strcmp(buf, "MIB") == 0) {
2504                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
2505                 if (reply_len >= 0) {
2506                         int res;
2507                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
2508                                                reply_size - reply_len);
2509                         if (res < 0)
2510                                 reply_len = -1;
2511                         else
2512                                 reply_len += res;
2513                 }
2514         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
2515                 reply_len = wpa_supplicant_ctrl_iface_status(
2516                         wpa_s, buf + 6, reply, reply_size);
2517         } else if (os_strcmp(buf, "PMKSA") == 0) {
2518                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
2519                                                     reply_size);
2520         } else if (os_strncmp(buf, "SET ", 4) == 0) {
2521                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
2522                         reply_len = -1;
2523         } else if (os_strcmp(buf, "LOGON") == 0) {
2524                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2525         } else if (os_strcmp(buf, "LOGOFF") == 0) {
2526                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2527         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
2528                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
2529                         reply_len = -1;
2530                 else {
2531                         wpa_s->disconnected = 0;
2532                         wpa_s->reassociate = 1;
2533                         wpa_supplicant_req_scan(wpa_s, 0, 0);
2534                 }
2535         } else if (os_strcmp(buf, "RECONNECT") == 0) {
2536                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
2537                         reply_len = -1;
2538                 else if (wpa_s->disconnected) {
2539                         wpa_s->disconnected = 0;
2540                         wpa_s->reassociate = 1;
2541                         wpa_supplicant_req_scan(wpa_s, 0, 0);
2542                 }
2543 #ifdef IEEE8021X_EAPOL
2544         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
2545                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
2546                         reply_len = -1;
2547 #endif /* IEEE8021X_EAPOL */
2548 #ifdef CONFIG_PEERKEY
2549         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
2550                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
2551                         reply_len = -1;
2552 #endif /* CONFIG_PEERKEY */
2553 #ifdef CONFIG_IEEE80211R
2554         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
2555                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
2556                         reply_len = -1;
2557 #endif /* CONFIG_IEEE80211R */
2558 #ifdef CONFIG_WPS
2559         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
2560                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
2561                         reply_len = -1;
2562         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
2563                 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
2564                         reply_len = -1;
2565         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
2566                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
2567                                                               reply,
2568                                                               reply_size);
2569 #ifdef CONFIG_WPS_OOB
2570         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
2571                 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
2572                         reply_len = -1;
2573 #endif /* CONFIG_WPS_OOB */
2574         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
2575                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
2576                         reply_len = -1;
2577 #ifdef CONFIG_WPS_ER
2578         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
2579                 if (wpas_wps_er_start(wpa_s, NULL))
2580                         reply_len = -1;
2581         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
2582                 if (wpas_wps_er_start(wpa_s, buf + 13))
2583                         reply_len = -1;
2584         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
2585                 if (wpas_wps_er_stop(wpa_s))
2586                         reply_len = -1;
2587         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
2588                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
2589                         reply_len = -1;
2590         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
2591                 if (wpas_wps_er_pbc(wpa_s, buf + 11))
2592                         reply_len = -1;
2593         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
2594                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
2595                         reply_len = -1;
2596         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
2597                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
2598                         reply_len = -1;
2599 #endif /* CONFIG_WPS_ER */
2600 #endif /* CONFIG_WPS */
2601 #ifdef CONFIG_IBSS_RSN
2602         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
2603                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
2604                         reply_len = -1;
2605 #endif /* CONFIG_IBSS_RSN */
2606 #ifdef CONFIG_P2P
2607         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
2608                 if (p2p_ctrl_find(wpa_s, buf + 9))
2609                         reply_len = -1;
2610         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
2611                 if (p2p_ctrl_find(wpa_s, ""))
2612                         reply_len = -1;
2613         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
2614                 wpas_p2p_stop_find(wpa_s);
2615         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
2616                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
2617                                              reply_size);
2618         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
2619                 if (p2p_ctrl_listen(wpa_s, buf + 11))
2620                         reply_len = -1;
2621         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
2622                 if (p2p_ctrl_listen(wpa_s, ""))
2623                         reply_len = -1;
2624         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
2625                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
2626                         reply_len = -1;
2627         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
2628                 if (wpas_p2p_group_add(wpa_s, 0, 0))
2629                         reply_len = -1;
2630         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
2631                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
2632                         reply_len = -1;
2633         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
2634                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
2635                         reply_len = -1;
2636         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
2637                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
2638         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
2639                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
2640                                                    reply_size);
2641         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
2642                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
2643                         reply_len = -1;
2644         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
2645                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
2646                         reply_len = -1;
2647         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
2648                 wpas_p2p_sd_service_update(wpa_s);
2649         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
2650                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
2651                         reply_len = -1;
2652         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
2653                 wpas_p2p_service_flush(wpa_s);
2654         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
2655                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
2656                         reply_len = -1;
2657         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
2658                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
2659                         reply_len = -1;
2660         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
2661                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
2662                         reply_len = -1;
2663         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
2664                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
2665                         reply_len = -1;
2666         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
2667                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
2668                                               reply_size);
2669         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
2670                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
2671                         reply_len = -1;
2672         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
2673                 p2p_flush(wpa_s->global->p2p);
2674         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
2675                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
2676                         reply_len = -1;
2677         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
2678                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
2679                         reply_len = -1;
2680         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
2681                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
2682                         reply_len = -1;
2683         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
2684                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
2685                         reply_len = -1;
2686 #endif /* CONFIG_P2P */
2687         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
2688         {
2689                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
2690                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
2691                         reply_len = -1;
2692                 else
2693                         ctrl_rsp = 1;
2694         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
2695                 if (wpa_supplicant_reload_configuration(wpa_s))
2696                         reply_len = -1;
2697         } else if (os_strcmp(buf, "TERMINATE") == 0) {
2698                 wpa_supplicant_terminate_proc(wpa_s->global);
2699         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
2700                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
2701                         reply_len = -1;
2702         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
2703                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
2704                         wpa_s, reply, reply_size);
2705         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
2706                 wpa_s->reassociate = 0;
2707                 wpa_s->disconnected = 1;
2708                 wpa_supplicant_deauthenticate(wpa_s,
2709                                               WLAN_REASON_DEAUTH_LEAVING);
2710         } else if (os_strcmp(buf, "SCAN") == 0) {
2711                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
2712                         reply_len = -1;
2713                 else {
2714                         wpa_s->scan_req = 2;
2715                         wpa_supplicant_req_scan(wpa_s, 0, 0);
2716                 }
2717         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
2718                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
2719                         wpa_s, reply, reply_size);
2720         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
2721                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
2722                         reply_len = -1;
2723         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
2724                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
2725                         reply_len = -1;
2726         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
2727                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
2728                         reply_len = -1;
2729         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
2730                 reply_len = wpa_supplicant_ctrl_iface_add_network(
2731                         wpa_s, reply, reply_size);
2732         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
2733                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
2734                         reply_len = -1;
2735         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
2736                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
2737                         reply_len = -1;
2738         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
2739                 reply_len = wpa_supplicant_ctrl_iface_get_network(
2740                         wpa_s, buf + 12, reply, reply_size);
2741 #ifndef CONFIG_NO_CONFIG_WRITE
2742         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
2743                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
2744                         reply_len = -1;
2745 #endif /* CONFIG_NO_CONFIG_WRITE */
2746         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
2747                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
2748                         wpa_s, buf + 15, reply, reply_size);
2749         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
2750                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
2751                         reply_len = -1;
2752         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
2753                 reply_len = wpa_supplicant_global_iface_list(
2754                         wpa_s->global, reply, reply_size);
2755         } else if (os_strcmp(buf, "INTERFACES") == 0) {
2756                 reply_len = wpa_supplicant_global_iface_interfaces(
2757                         wpa_s->global, reply, reply_size);
2758         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
2759                 reply_len = wpa_supplicant_ctrl_iface_bss(
2760                         wpa_s, buf + 4, reply, reply_size);
2761 #ifdef CONFIG_AP
2762         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
2763                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
2764         } else if (os_strncmp(buf, "STA ", 4) == 0) {
2765                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
2766                                               reply_size);
2767         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
2768                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
2769                                                    reply_size);
2770 #endif /* CONFIG_AP */
2771         } else if (os_strcmp(buf, "SUSPEND") == 0) {
2772                 wpas_notify_suspend(wpa_s->global);
2773         } else if (os_strcmp(buf, "RESUME") == 0) {
2774                 wpas_notify_resume(wpa_s->global);
2775         } else if (os_strcmp(buf, "DROP_SA") == 0) {
2776                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
2777         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
2778                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
2779                         reply_len = -1;
2780         } else {
2781                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
2782                 reply_len = 16;
2783         }
2784
2785         if (reply_len < 0) {
2786                 os_memcpy(reply, "FAIL\n", 5);
2787                 reply_len = 5;
2788         }
2789
2790         if (ctrl_rsp)
2791                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
2792
2793         *resp_len = reply_len;
2794         return reply;
2795 }
2796
2797
2798 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
2799                                            char *cmd)
2800 {
2801         struct wpa_interface iface;
2802         char *pos;
2803
2804         /*
2805          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
2806          * TAB<bridge_ifname>
2807          */
2808         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
2809
2810         os_memset(&iface, 0, sizeof(iface));
2811
2812         do {
2813                 iface.ifname = pos = cmd;
2814                 pos = os_strchr(pos, '\t');
2815                 if (pos)
2816                         *pos++ = '\0';
2817                 if (iface.ifname[0] == '\0')
2818                         return -1;
2819                 if (pos == NULL)
2820                         break;
2821
2822                 iface.confname = pos;
2823                 pos = os_strchr(pos, '\t');
2824                 if (pos)
2825                         *pos++ = '\0';
2826                 if (iface.confname[0] == '\0')
2827                         iface.confname = NULL;
2828                 if (pos == NULL)
2829                         break;
2830
2831                 iface.driver = pos;
2832                 pos = os_strchr(pos, '\t');
2833                 if (pos)
2834                         *pos++ = '\0';
2835                 if (iface.driver[0] == '\0')
2836                         iface.driver = NULL;
2837                 if (pos == NULL)
2838                         break;
2839
2840                 iface.ctrl_interface = pos;
2841                 pos = os_strchr(pos, '\t');
2842                 if (pos)
2843                         *pos++ = '\0';
2844                 if (iface.ctrl_interface[0] == '\0')
2845                         iface.ctrl_interface = NULL;
2846                 if (pos == NULL)
2847                         break;
2848
2849                 iface.driver_param = pos;
2850                 pos = os_strchr(pos, '\t');
2851                 if (pos)
2852                         *pos++ = '\0';
2853                 if (iface.driver_param[0] == '\0')
2854                         iface.driver_param = NULL;
2855                 if (pos == NULL)
2856                         break;
2857
2858                 iface.bridge_ifname = pos;
2859                 pos = os_strchr(pos, '\t');
2860                 if (pos)
2861                         *pos++ = '\0';
2862                 if (iface.bridge_ifname[0] == '\0')
2863                         iface.bridge_ifname = NULL;
2864                 if (pos == NULL)
2865                         break;
2866         } while (0);
2867
2868         if (wpa_supplicant_get_iface(global, iface.ifname))
2869                 return -1;
2870
2871         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
2872 }
2873
2874
2875 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
2876                                               char *cmd)
2877 {
2878         struct wpa_supplicant *wpa_s;
2879
2880         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
2881
2882         wpa_s = wpa_supplicant_get_iface(global, cmd);
2883         if (wpa_s == NULL)
2884                 return -1;
2885         return wpa_supplicant_remove_iface(global, wpa_s);
2886 }
2887
2888
2889 static void wpa_free_iface_info(struct wpa_interface_info *iface)
2890 {
2891         struct wpa_interface_info *prev;
2892
2893         while (iface) {
2894                 prev = iface;
2895                 iface = iface->next;
2896
2897                 os_free(prev->ifname);
2898                 os_free(prev->desc);
2899                 os_free(prev);
2900         }
2901 }
2902
2903
2904 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
2905                                             char *buf, int len)
2906 {
2907         int i, res;
2908         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
2909         char *pos, *end;
2910
2911         for (i = 0; wpa_drivers[i]; i++) {
2912                 struct wpa_driver_ops *drv = wpa_drivers[i];
2913                 if (drv->get_interfaces == NULL)
2914                         continue;
2915                 tmp = drv->get_interfaces(global->drv_priv[i]);
2916                 if (tmp == NULL)
2917                         continue;
2918
2919                 if (last == NULL)
2920                         iface = last = tmp;
2921                 else
2922                         last->next = tmp;
2923                 while (last->next)
2924                         last = last->next;
2925         }
2926
2927         pos = buf;
2928         end = buf + len;
2929         for (tmp = iface; tmp; tmp = tmp->next) {
2930                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
2931                                   tmp->drv_name, tmp->ifname,
2932                                   tmp->desc ? tmp->desc : "");
2933                 if (res < 0 || res >= end - pos) {
2934                         *pos = '\0';
2935                         break;
2936                 }
2937                 pos += res;
2938         }
2939
2940         wpa_free_iface_info(iface);
2941
2942         return pos - buf;
2943 }
2944
2945
2946 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
2947                                                   char *buf, int len)
2948 {
2949         int res;
2950         char *pos, *end;
2951         struct wpa_supplicant *wpa_s;
2952
2953         wpa_s = global->ifaces;
2954         pos = buf;
2955         end = buf + len;
2956
2957         while (wpa_s) {
2958                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
2959                 if (res < 0 || res >= end - pos) {
2960                         *pos = '\0';
2961                         break;
2962                 }
2963                 pos += res;
2964                 wpa_s = wpa_s->next;
2965         }
2966         return pos - buf;
2967 }
2968
2969
2970 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
2971                                                 char *buf, size_t *resp_len)
2972 {
2973         char *reply;
2974         const int reply_size = 2048;
2975         int reply_len;
2976
2977         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
2978                           (const u8 *) buf, os_strlen(buf));
2979
2980         reply = os_malloc(reply_size);
2981         if (reply == NULL) {
2982                 *resp_len = 1;
2983                 return NULL;
2984         }
2985
2986         os_memcpy(reply, "OK\n", 3);
2987         reply_len = 3;
2988
2989         if (os_strcmp(buf, "PING") == 0) {
2990                 os_memcpy(reply, "PONG\n", 5);
2991                 reply_len = 5;
2992         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
2993                 if (wpa_supplicant_global_iface_add(global, buf + 14))
2994                         reply_len = -1;
2995         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
2996                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
2997                         reply_len = -1;
2998         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
2999                 reply_len = wpa_supplicant_global_iface_list(
3000                         global, reply, reply_size);
3001         } else if (os_strcmp(buf, "INTERFACES") == 0) {
3002                 reply_len = wpa_supplicant_global_iface_interfaces(
3003                         global, reply, reply_size);
3004         } else if (os_strcmp(buf, "TERMINATE") == 0) {
3005                 wpa_supplicant_terminate_proc(global);
3006         } else if (os_strcmp(buf, "SUSPEND") == 0) {
3007                 wpas_notify_suspend(global);
3008         } else if (os_strcmp(buf, "RESUME") == 0) {
3009                 wpas_notify_resume(global);
3010         } else {
3011                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
3012                 reply_len = 16;
3013         }
3014
3015         if (reply_len < 0) {
3016                 os_memcpy(reply, "FAIL\n", 5);
3017                 reply_len = 5;
3018         }
3019
3020         *resp_len = reply_len;
3021         return reply;
3022 }