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