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