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