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