P2P: Enable 40 MHz support for autonomous P2P group addition
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/version.h"
14 #include "common/ieee802_11_defs.h"
15 #include "common/wpa_ctrl.h"
16 #include "eap_peer/eap.h"
17 #include "eapol_supp/eapol_supp_sm.h"
18 #include "rsn_supp/wpa.h"
19 #include "rsn_supp/preauth.h"
20 #include "rsn_supp/pmksa_cache.h"
21 #include "l2_packet/l2_packet.h"
22 #include "wps/wps.h"
23 #include "config.h"
24 #include "wpa_supplicant_i.h"
25 #include "driver_i.h"
26 #include "wps_supplicant.h"
27 #include "ibss_rsn.h"
28 #include "ap.h"
29 #include "p2p_supplicant.h"
30 #include "p2p/p2p.h"
31 #include "hs20_supplicant.h"
32 #include "notify.h"
33 #include "bss.h"
34 #include "scan.h"
35 #include "ctrl_iface.h"
36 #include "interworking.h"
37 #include "blacklist.h"
38 #include "wpas_glue.h"
39 #include "autoscan.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 pno_start(struct wpa_supplicant *wpa_s)
50 {
51         int ret;
52         size_t i, num_ssid;
53         struct wpa_ssid *ssid;
54         struct wpa_driver_scan_params params;
55
56         if (wpa_s->pno)
57                 return 0;
58
59         os_memset(&params, 0, sizeof(params));
60
61         num_ssid = 0;
62         ssid = wpa_s->conf->ssid;
63         while (ssid) {
64                 if (!wpas_network_disabled(wpa_s, ssid))
65                         num_ssid++;
66                 ssid = ssid->next;
67         }
68         if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
69                 wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
70                            "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
71                 num_ssid = WPAS_MAX_SCAN_SSIDS;
72         }
73
74         if (num_ssid == 0) {
75                 wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
76                 return -1;
77         }
78
79         params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
80                                         num_ssid);
81         if (params.filter_ssids == NULL)
82                 return -1;
83         i = 0;
84         ssid = wpa_s->conf->ssid;
85         while (ssid) {
86                 if (!wpas_network_disabled(wpa_s, ssid)) {
87                         params.ssids[i].ssid = ssid->ssid;
88                         params.ssids[i].ssid_len = ssid->ssid_len;
89                         params.num_ssids++;
90                         os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
91                                   ssid->ssid_len);
92                         params.filter_ssids[i].ssid_len = ssid->ssid_len;
93                         params.num_filter_ssids++;
94                         i++;
95                         if (i == num_ssid)
96                                 break;
97                 }
98                 ssid = ssid->next;
99         }
100
101         if (wpa_s->conf->filter_rssi)
102                 params.filter_rssi = wpa_s->conf->filter_rssi;
103
104         ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
105         os_free(params.filter_ssids);
106         if (ret == 0)
107                 wpa_s->pno = 1;
108         return ret;
109 }
110
111
112 static int pno_stop(struct wpa_supplicant *wpa_s)
113 {
114         if (wpa_s->pno) {
115                 wpa_s->pno = 0;
116                 return wpa_drv_stop_sched_scan(wpa_s);
117         }
118         return 0;
119 }
120
121
122 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
123 {
124         char *pos;
125         u8 addr[ETH_ALEN], *filter = NULL, *n;
126         size_t count = 0;
127
128         pos = val;
129         while (pos) {
130                 if (*pos == '\0')
131                         break;
132                 if (hwaddr_aton(pos, addr)) {
133                         os_free(filter);
134                         return -1;
135                 }
136                 n = os_realloc_array(filter, count + 1, ETH_ALEN);
137                 if (n == NULL) {
138                         os_free(filter);
139                         return -1;
140                 }
141                 filter = n;
142                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
143                 count++;
144
145                 pos = os_strchr(pos, ' ');
146                 if (pos)
147                         pos++;
148         }
149
150         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
151         os_free(wpa_s->bssid_filter);
152         wpa_s->bssid_filter = filter;
153         wpa_s->bssid_filter_count = count;
154
155         return 0;
156 }
157
158
159 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
160                                          char *cmd)
161 {
162         char *value;
163         int ret = 0;
164
165         value = os_strchr(cmd, ' ');
166         if (value == NULL)
167                 return -1;
168         *value++ = '\0';
169
170         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
171         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
172                 eapol_sm_configure(wpa_s->eapol,
173                                    atoi(value), -1, -1, -1);
174         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
175                 eapol_sm_configure(wpa_s->eapol,
176                                    -1, atoi(value), -1, -1);
177         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
178                 eapol_sm_configure(wpa_s->eapol,
179                                    -1, -1, atoi(value), -1);
180         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
181                 eapol_sm_configure(wpa_s->eapol,
182                                    -1, -1, -1, atoi(value));
183         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
184                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
185                                      atoi(value)))
186                         ret = -1;
187         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
188                    0) {
189                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
190                                      atoi(value)))
191                         ret = -1;
192         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
193                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
194                         ret = -1;
195         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
196                 wpa_s->wps_fragment_size = atoi(value);
197 #ifdef CONFIG_WPS_TESTING
198         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
199                 long int val;
200                 val = strtol(value, NULL, 0);
201                 if (val < 0 || val > 0xff) {
202                         ret = -1;
203                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
204                                    "wps_version_number %ld", val);
205                 } else {
206                         wps_version_number = val;
207                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
208                                    "version %u.%u",
209                                    (wps_version_number & 0xf0) >> 4,
210                                    wps_version_number & 0x0f);
211                 }
212         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
213                 wps_testing_dummy_cred = atoi(value);
214                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
215                            wps_testing_dummy_cred);
216 #endif /* CONFIG_WPS_TESTING */
217         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
218                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
219                         ret = -1;
220 #ifdef CONFIG_TDLS_TESTING
221         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
222                 extern unsigned int tdls_testing;
223                 tdls_testing = strtol(value, NULL, 0);
224                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
225 #endif /* CONFIG_TDLS_TESTING */
226 #ifdef CONFIG_TDLS
227         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
228                 int disabled = atoi(value);
229                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
230                 if (disabled) {
231                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
232                                 ret = -1;
233                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
234                         ret = -1;
235                 wpa_tdls_enable(wpa_s->wpa, !disabled);
236 #endif /* CONFIG_TDLS */
237         } else if (os_strcasecmp(cmd, "pno") == 0) {
238                 if (atoi(value))
239                         ret = pno_start(wpa_s);
240                 else
241                         ret = pno_stop(wpa_s);
242         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
243                 int disabled = atoi(value);
244                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
245                         ret = -1;
246                 else if (disabled)
247                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
248         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
249                 if (os_strcmp(value, "disable") == 0)
250                         wpa_s->set_sta_uapsd = 0;
251                 else {
252                         int be, bk, vi, vo;
253                         char *pos;
254                         /* format: BE,BK,VI,VO;max SP Length */
255                         be = atoi(value);
256                         pos = os_strchr(value, ',');
257                         if (pos == NULL)
258                                 return -1;
259                         pos++;
260                         bk = atoi(pos);
261                         pos = os_strchr(pos, ',');
262                         if (pos == NULL)
263                                 return -1;
264                         pos++;
265                         vi = atoi(pos);
266                         pos = os_strchr(pos, ',');
267                         if (pos == NULL)
268                                 return -1;
269                         pos++;
270                         vo = atoi(pos);
271                         /* ignore max SP Length for now */
272
273                         wpa_s->set_sta_uapsd = 1;
274                         wpa_s->sta_uapsd = 0;
275                         if (be)
276                                 wpa_s->sta_uapsd |= BIT(0);
277                         if (bk)
278                                 wpa_s->sta_uapsd |= BIT(1);
279                         if (vi)
280                                 wpa_s->sta_uapsd |= BIT(2);
281                         if (vo)
282                                 wpa_s->sta_uapsd |= BIT(3);
283                 }
284         } else if (os_strcasecmp(cmd, "ps") == 0) {
285                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
286         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
287                 ret = set_bssid_filter(wpa_s, value);
288         } else {
289                 value[-1] = '=';
290                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
291                 if (ret == 0)
292                         wpa_supplicant_update_config(wpa_s);
293         }
294
295         return ret;
296 }
297
298
299 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
300                                          char *cmd, char *buf, size_t buflen)
301 {
302         int res = -1;
303
304         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
305
306         if (os_strcmp(cmd, "version") == 0) {
307                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
308         } else if (os_strcasecmp(cmd, "country") == 0) {
309                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
310                         res = os_snprintf(buf, buflen, "%c%c",
311                                           wpa_s->conf->country[0],
312                                           wpa_s->conf->country[1]);
313         }
314
315         if (res < 0 || (unsigned int) res >= buflen)
316                 return -1;
317         return res;
318 }
319
320
321 #ifdef IEEE8021X_EAPOL
322 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
323                                              char *addr)
324 {
325         u8 bssid[ETH_ALEN];
326         struct wpa_ssid *ssid = wpa_s->current_ssid;
327
328         if (hwaddr_aton(addr, bssid)) {
329                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
330                            "'%s'", addr);
331                 return -1;
332         }
333
334         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
335         rsn_preauth_deinit(wpa_s->wpa);
336         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
337                 return -1;
338
339         return 0;
340 }
341 #endif /* IEEE8021X_EAPOL */
342
343
344 #ifdef CONFIG_PEERKEY
345 /* MLME-STKSTART.request(peer) */
346 static int wpa_supplicant_ctrl_iface_stkstart(
347         struct wpa_supplicant *wpa_s, char *addr)
348 {
349         u8 peer[ETH_ALEN];
350
351         if (hwaddr_aton(addr, peer)) {
352                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
353                            "address '%s'", addr);
354                 return -1;
355         }
356
357         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
358                    MAC2STR(peer));
359
360         return wpa_sm_stkstart(wpa_s->wpa, peer);
361 }
362 #endif /* CONFIG_PEERKEY */
363
364
365 #ifdef CONFIG_TDLS
366
367 static int wpa_supplicant_ctrl_iface_tdls_discover(
368         struct wpa_supplicant *wpa_s, char *addr)
369 {
370         u8 peer[ETH_ALEN];
371         int ret;
372
373         if (hwaddr_aton(addr, peer)) {
374                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
375                            "address '%s'", addr);
376                 return -1;
377         }
378
379         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
380                    MAC2STR(peer));
381
382         if (wpa_tdls_is_external_setup(wpa_s->wpa))
383                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
384         else
385                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
386
387         return ret;
388 }
389
390
391 static int wpa_supplicant_ctrl_iface_tdls_setup(
392         struct wpa_supplicant *wpa_s, char *addr)
393 {
394         u8 peer[ETH_ALEN];
395         int ret;
396
397         if (hwaddr_aton(addr, peer)) {
398                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
399                            "address '%s'", addr);
400                 return -1;
401         }
402
403         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
404                    MAC2STR(peer));
405
406         ret = wpa_tdls_reneg(wpa_s->wpa, peer);
407         if (ret) {
408                 if (wpa_tdls_is_external_setup(wpa_s->wpa))
409                         ret = wpa_tdls_start(wpa_s->wpa, peer);
410                 else
411                         ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
412         }
413
414         return ret;
415 }
416
417
418 static int wpa_supplicant_ctrl_iface_tdls_teardown(
419         struct wpa_supplicant *wpa_s, char *addr)
420 {
421         u8 peer[ETH_ALEN];
422
423         if (hwaddr_aton(addr, peer)) {
424                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
425                            "address '%s'", addr);
426                 return -1;
427         }
428
429         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
430                    MAC2STR(peer));
431
432         return wpa_tdls_teardown_link(wpa_s->wpa, peer,
433                                       WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
434 }
435
436 #endif /* CONFIG_TDLS */
437
438
439 #ifdef CONFIG_IEEE80211R
440 static int wpa_supplicant_ctrl_iface_ft_ds(
441         struct wpa_supplicant *wpa_s, char *addr)
442 {
443         u8 target_ap[ETH_ALEN];
444         struct wpa_bss *bss;
445         const u8 *mdie;
446
447         if (hwaddr_aton(addr, target_ap)) {
448                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
449                            "address '%s'", addr);
450                 return -1;
451         }
452
453         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
454
455         bss = wpa_bss_get_bssid(wpa_s, target_ap);
456         if (bss)
457                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
458         else
459                 mdie = NULL;
460
461         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
462 }
463 #endif /* CONFIG_IEEE80211R */
464
465
466 #ifdef CONFIG_WPS
467 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
468                                              char *cmd)
469 {
470         u8 bssid[ETH_ALEN], *_bssid = bssid;
471 #ifdef CONFIG_P2P
472         u8 p2p_dev_addr[ETH_ALEN];
473 #endif /* CONFIG_P2P */
474 #ifdef CONFIG_AP
475         u8 *_p2p_dev_addr = NULL;
476 #endif /* CONFIG_AP */
477
478         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
479                 _bssid = NULL;
480 #ifdef CONFIG_P2P
481         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
482                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
483                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
484                                    "P2P Device Address '%s'",
485                                    cmd + 13);
486                         return -1;
487                 }
488                 _p2p_dev_addr = p2p_dev_addr;
489 #endif /* CONFIG_P2P */
490         } else if (hwaddr_aton(cmd, bssid)) {
491                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
492                            cmd);
493                 return -1;
494         }
495
496 #ifdef CONFIG_AP
497         if (wpa_s->ap_iface)
498                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
499 #endif /* CONFIG_AP */
500
501         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
502 }
503
504
505 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
506                                              char *cmd, char *buf,
507                                              size_t buflen)
508 {
509         u8 bssid[ETH_ALEN], *_bssid = bssid;
510         char *pin;
511         int ret;
512
513         pin = os_strchr(cmd, ' ');
514         if (pin)
515                 *pin++ = '\0';
516
517         if (os_strcmp(cmd, "any") == 0)
518                 _bssid = NULL;
519         else if (os_strcmp(cmd, "get") == 0) {
520                 ret = wps_generate_pin();
521                 goto done;
522         } else if (hwaddr_aton(cmd, bssid)) {
523                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
524                            cmd);
525                 return -1;
526         }
527
528 #ifdef CONFIG_AP
529         if (wpa_s->ap_iface)
530                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
531                                                  buf, buflen);
532 #endif /* CONFIG_AP */
533
534         if (pin) {
535                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
536                                          DEV_PW_DEFAULT);
537                 if (ret < 0)
538                         return -1;
539                 ret = os_snprintf(buf, buflen, "%s", pin);
540                 if (ret < 0 || (size_t) ret >= buflen)
541                         return -1;
542                 return ret;
543         }
544
545         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
546         if (ret < 0)
547                 return -1;
548
549 done:
550         /* Return the generated PIN */
551         ret = os_snprintf(buf, buflen, "%08d", ret);
552         if (ret < 0 || (size_t) ret >= buflen)
553                 return -1;
554         return ret;
555 }
556
557
558 static int wpa_supplicant_ctrl_iface_wps_check_pin(
559         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
560 {
561         char pin[9];
562         size_t len;
563         char *pos;
564         int ret;
565
566         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
567                               (u8 *) cmd, os_strlen(cmd));
568         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
569                 if (*pos < '0' || *pos > '9')
570                         continue;
571                 pin[len++] = *pos;
572                 if (len == 9) {
573                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
574                         return -1;
575                 }
576         }
577         if (len != 4 && len != 8) {
578                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
579                 return -1;
580         }
581         pin[len] = '\0';
582
583         if (len == 8) {
584                 unsigned int pin_val;
585                 pin_val = atoi(pin);
586                 if (!wps_pin_valid(pin_val)) {
587                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
588                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
589                         if (ret < 0 || (size_t) ret >= buflen)
590                                 return -1;
591                         return ret;
592                 }
593         }
594
595         ret = os_snprintf(buf, buflen, "%s", pin);
596         if (ret < 0 || (size_t) ret >= buflen)
597                 return -1;
598
599         return ret;
600 }
601
602
603 #ifdef CONFIG_WPS_OOB
604 static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
605                                              char *cmd)
606 {
607         char *path, *method, *name;
608
609         path = os_strchr(cmd, ' ');
610         if (path == NULL)
611                 return -1;
612         *path++ = '\0';
613
614         method = os_strchr(path, ' ');
615         if (method == NULL)
616                 return -1;
617         *method++ = '\0';
618
619         name = os_strchr(method, ' ');
620         if (name != NULL)
621                 *name++ = '\0';
622
623         return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
624 }
625 #endif /* CONFIG_WPS_OOB */
626
627
628 #ifdef CONFIG_WPS_NFC
629
630 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
631                                              char *cmd)
632 {
633         u8 bssid[ETH_ALEN], *_bssid = bssid;
634
635         if (cmd == NULL || cmd[0] == '\0')
636                 _bssid = NULL;
637         else if (hwaddr_aton(cmd, bssid))
638                 return -1;
639
640         return wpas_wps_start_nfc(wpa_s, _bssid);
641 }
642
643
644 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
645         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
646 {
647         int ndef;
648         struct wpabuf *buf;
649         int res;
650
651         if (os_strcmp(cmd, "WPS") == 0)
652                 ndef = 0;
653         else if (os_strcmp(cmd, "NDEF") == 0)
654                 ndef = 1;
655         else
656                 return -1;
657
658         buf = wpas_wps_nfc_token(wpa_s, ndef);
659         if (buf == NULL)
660                 return -1;
661
662         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
663                                          wpabuf_len(buf));
664         reply[res++] = '\n';
665         reply[res] = '\0';
666
667         wpabuf_free(buf);
668
669         return res;
670 }
671
672
673 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
674         struct wpa_supplicant *wpa_s, char *pos)
675 {
676         size_t len;
677         struct wpabuf *buf;
678         int ret;
679
680         len = os_strlen(pos);
681         if (len & 0x01)
682                 return -1;
683         len /= 2;
684
685         buf = wpabuf_alloc(len);
686         if (buf == NULL)
687                 return -1;
688         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
689                 wpabuf_free(buf);
690                 return -1;
691         }
692
693         ret = wpas_wps_nfc_tag_read(wpa_s, buf);
694         wpabuf_free(buf);
695
696         return ret;
697 }
698
699 #endif /* CONFIG_WPS_NFC */
700
701
702 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
703                                              char *cmd)
704 {
705         u8 bssid[ETH_ALEN];
706         char *pin;
707         char *new_ssid;
708         char *new_auth;
709         char *new_encr;
710         char *new_key;
711         struct wps_new_ap_settings ap;
712
713         pin = os_strchr(cmd, ' ');
714         if (pin == NULL)
715                 return -1;
716         *pin++ = '\0';
717
718         if (hwaddr_aton(cmd, bssid)) {
719                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
720                            cmd);
721                 return -1;
722         }
723
724         new_ssid = os_strchr(pin, ' ');
725         if (new_ssid == NULL)
726                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
727         *new_ssid++ = '\0';
728
729         new_auth = os_strchr(new_ssid, ' ');
730         if (new_auth == NULL)
731                 return -1;
732         *new_auth++ = '\0';
733
734         new_encr = os_strchr(new_auth, ' ');
735         if (new_encr == NULL)
736                 return -1;
737         *new_encr++ = '\0';
738
739         new_key = os_strchr(new_encr, ' ');
740         if (new_key == NULL)
741                 return -1;
742         *new_key++ = '\0';
743
744         os_memset(&ap, 0, sizeof(ap));
745         ap.ssid_hex = new_ssid;
746         ap.auth = new_auth;
747         ap.encr = new_encr;
748         ap.key_hex = new_key;
749         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
750 }
751
752
753 #ifdef CONFIG_AP
754 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
755                                                 char *cmd, char *buf,
756                                                 size_t buflen)
757 {
758         int timeout = 300;
759         char *pos;
760         const char *pin_txt;
761
762         if (!wpa_s->ap_iface)
763                 return -1;
764
765         pos = os_strchr(cmd, ' ');
766         if (pos)
767                 *pos++ = '\0';
768
769         if (os_strcmp(cmd, "disable") == 0) {
770                 wpas_wps_ap_pin_disable(wpa_s);
771                 return os_snprintf(buf, buflen, "OK\n");
772         }
773
774         if (os_strcmp(cmd, "random") == 0) {
775                 if (pos)
776                         timeout = atoi(pos);
777                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
778                 if (pin_txt == NULL)
779                         return -1;
780                 return os_snprintf(buf, buflen, "%s", pin_txt);
781         }
782
783         if (os_strcmp(cmd, "get") == 0) {
784                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
785                 if (pin_txt == NULL)
786                         return -1;
787                 return os_snprintf(buf, buflen, "%s", pin_txt);
788         }
789
790         if (os_strcmp(cmd, "set") == 0) {
791                 char *pin;
792                 if (pos == NULL)
793                         return -1;
794                 pin = pos;
795                 pos = os_strchr(pos, ' ');
796                 if (pos) {
797                         *pos++ = '\0';
798                         timeout = atoi(pos);
799                 }
800                 if (os_strlen(pin) > buflen)
801                         return -1;
802                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
803                         return -1;
804                 return os_snprintf(buf, buflen, "%s", pin);
805         }
806
807         return -1;
808 }
809 #endif /* CONFIG_AP */
810
811
812 #ifdef CONFIG_WPS_ER
813 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
814                                                 char *cmd)
815 {
816         char *uuid = cmd, *pin, *pos;
817         u8 addr_buf[ETH_ALEN], *addr = NULL;
818         pin = os_strchr(uuid, ' ');
819         if (pin == NULL)
820                 return -1;
821         *pin++ = '\0';
822         pos = os_strchr(pin, ' ');
823         if (pos) {
824                 *pos++ = '\0';
825                 if (hwaddr_aton(pos, addr_buf) == 0)
826                         addr = addr_buf;
827         }
828         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
829 }
830
831
832 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
833                                                   char *cmd)
834 {
835         char *uuid = cmd, *pin;
836         pin = os_strchr(uuid, ' ');
837         if (pin == NULL)
838                 return -1;
839         *pin++ = '\0';
840         return wpas_wps_er_learn(wpa_s, uuid, pin);
841 }
842
843
844 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
845         struct wpa_supplicant *wpa_s, char *cmd)
846 {
847         char *uuid = cmd, *id;
848         id = os_strchr(uuid, ' ');
849         if (id == NULL)
850                 return -1;
851         *id++ = '\0';
852         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
853 }
854
855
856 static int wpa_supplicant_ctrl_iface_wps_er_config(
857         struct wpa_supplicant *wpa_s, char *cmd)
858 {
859         char *pin;
860         char *new_ssid;
861         char *new_auth;
862         char *new_encr;
863         char *new_key;
864         struct wps_new_ap_settings ap;
865
866         pin = os_strchr(cmd, ' ');
867         if (pin == NULL)
868                 return -1;
869         *pin++ = '\0';
870
871         new_ssid = os_strchr(pin, ' ');
872         if (new_ssid == NULL)
873                 return -1;
874         *new_ssid++ = '\0';
875
876         new_auth = os_strchr(new_ssid, ' ');
877         if (new_auth == NULL)
878                 return -1;
879         *new_auth++ = '\0';
880
881         new_encr = os_strchr(new_auth, ' ');
882         if (new_encr == NULL)
883                 return -1;
884         *new_encr++ = '\0';
885
886         new_key = os_strchr(new_encr, ' ');
887         if (new_key == NULL)
888                 return -1;
889         *new_key++ = '\0';
890
891         os_memset(&ap, 0, sizeof(ap));
892         ap.ssid_hex = new_ssid;
893         ap.auth = new_auth;
894         ap.encr = new_encr;
895         ap.key_hex = new_key;
896         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
897 }
898
899
900 #ifdef CONFIG_WPS_NFC
901 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
902         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
903 {
904         int ndef;
905         struct wpabuf *buf;
906         int res;
907         char *uuid;
908
909         uuid = os_strchr(cmd, ' ');
910         if (uuid == NULL)
911                 return -1;
912         *uuid++ = '\0';
913
914         if (os_strcmp(cmd, "WPS") == 0)
915                 ndef = 0;
916         else if (os_strcmp(cmd, "NDEF") == 0)
917                 ndef = 1;
918         else
919                 return -1;
920
921         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
922         if (buf == NULL)
923                 return -1;
924
925         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
926                                          wpabuf_len(buf));
927         reply[res++] = '\n';
928         reply[res] = '\0';
929
930         wpabuf_free(buf);
931
932         return res;
933 }
934 #endif /* CONFIG_WPS_NFC */
935 #endif /* CONFIG_WPS_ER */
936
937 #endif /* CONFIG_WPS */
938
939
940 #ifdef CONFIG_IBSS_RSN
941 static int wpa_supplicant_ctrl_iface_ibss_rsn(
942         struct wpa_supplicant *wpa_s, char *addr)
943 {
944         u8 peer[ETH_ALEN];
945
946         if (hwaddr_aton(addr, peer)) {
947                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
948                            "address '%s'", addr);
949                 return -1;
950         }
951
952         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
953                    MAC2STR(peer));
954
955         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
956 }
957 #endif /* CONFIG_IBSS_RSN */
958
959
960 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
961                                               char *rsp)
962 {
963 #ifdef IEEE8021X_EAPOL
964         char *pos, *id_pos;
965         int id;
966         struct wpa_ssid *ssid;
967
968         pos = os_strchr(rsp, '-');
969         if (pos == NULL)
970                 return -1;
971         *pos++ = '\0';
972         id_pos = pos;
973         pos = os_strchr(pos, ':');
974         if (pos == NULL)
975                 return -1;
976         *pos++ = '\0';
977         id = atoi(id_pos);
978         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
979         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
980                               (u8 *) pos, os_strlen(pos));
981
982         ssid = wpa_config_get_network(wpa_s->conf, id);
983         if (ssid == NULL) {
984                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
985                            "to update", id);
986                 return -1;
987         }
988
989         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
990                                                          pos);
991 #else /* IEEE8021X_EAPOL */
992         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
993         return -1;
994 #endif /* IEEE8021X_EAPOL */
995 }
996
997
998 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
999                                             const char *params,
1000                                             char *buf, size_t buflen)
1001 {
1002         char *pos, *end, tmp[30];
1003         int res, verbose, wps, ret;
1004
1005         verbose = os_strcmp(params, "-VERBOSE") == 0;
1006         wps = os_strcmp(params, "-WPS") == 0;
1007         pos = buf;
1008         end = buf + buflen;
1009         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1010                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1011                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1012                                   MAC2STR(wpa_s->bssid));
1013                 if (ret < 0 || ret >= end - pos)
1014                         return pos - buf;
1015                 pos += ret;
1016                 if (ssid) {
1017                         u8 *_ssid = ssid->ssid;
1018                         size_t ssid_len = ssid->ssid_len;
1019                         u8 ssid_buf[MAX_SSID_LEN];
1020                         if (ssid_len == 0) {
1021                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1022                                 if (_res < 0)
1023                                         ssid_len = 0;
1024                                 else
1025                                         ssid_len = _res;
1026                                 _ssid = ssid_buf;
1027                         }
1028                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1029                                           wpa_ssid_txt(_ssid, ssid_len),
1030                                           ssid->id);
1031                         if (ret < 0 || ret >= end - pos)
1032                                 return pos - buf;
1033                         pos += ret;
1034
1035                         if (wps && ssid->passphrase &&
1036                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1037                             (ssid->mode == WPAS_MODE_AP ||
1038                              ssid->mode == WPAS_MODE_P2P_GO)) {
1039                                 ret = os_snprintf(pos, end - pos,
1040                                                   "passphrase=%s\n",
1041                                                   ssid->passphrase);
1042                                 if (ret < 0 || ret >= end - pos)
1043                                         return pos - buf;
1044                                 pos += ret;
1045                         }
1046                         if (ssid->id_str) {
1047                                 ret = os_snprintf(pos, end - pos,
1048                                                   "id_str=%s\n",
1049                                                   ssid->id_str);
1050                                 if (ret < 0 || ret >= end - pos)
1051                                         return pos - buf;
1052                                 pos += ret;
1053                         }
1054
1055                         switch (ssid->mode) {
1056                         case WPAS_MODE_INFRA:
1057                                 ret = os_snprintf(pos, end - pos,
1058                                                   "mode=station\n");
1059                                 break;
1060                         case WPAS_MODE_IBSS:
1061                                 ret = os_snprintf(pos, end - pos,
1062                                                   "mode=IBSS\n");
1063                                 break;
1064                         case WPAS_MODE_AP:
1065                                 ret = os_snprintf(pos, end - pos,
1066                                                   "mode=AP\n");
1067                                 break;
1068                         case WPAS_MODE_P2P_GO:
1069                                 ret = os_snprintf(pos, end - pos,
1070                                                   "mode=P2P GO\n");
1071                                 break;
1072                         case WPAS_MODE_P2P_GROUP_FORMATION:
1073                                 ret = os_snprintf(pos, end - pos,
1074                                                   "mode=P2P GO - group "
1075                                                   "formation\n");
1076                                 break;
1077                         default:
1078                                 ret = 0;
1079                                 break;
1080                         }
1081                         if (ret < 0 || ret >= end - pos)
1082                                 return pos - buf;
1083                         pos += ret;
1084                 }
1085
1086 #ifdef CONFIG_AP
1087                 if (wpa_s->ap_iface) {
1088                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1089                                                             end - pos,
1090                                                             verbose);
1091                 } else
1092 #endif /* CONFIG_AP */
1093                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1094         }
1095         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1096                           wpa_supplicant_state_txt(wpa_s->wpa_state));
1097         if (ret < 0 || ret >= end - pos)
1098                 return pos - buf;
1099         pos += ret;
1100
1101         if (wpa_s->l2 &&
1102             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1103                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1104                 if (ret < 0 || ret >= end - pos)
1105                         return pos - buf;
1106                 pos += ret;
1107         }
1108
1109 #ifdef CONFIG_P2P
1110         if (wpa_s->global->p2p) {
1111                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1112                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1113                 if (ret < 0 || ret >= end - pos)
1114                         return pos - buf;
1115                 pos += ret;
1116         }
1117 #endif /* CONFIG_P2P */
1118
1119         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1120                           MAC2STR(wpa_s->own_addr));
1121         if (ret < 0 || ret >= end - pos)
1122                 return pos - buf;
1123         pos += ret;
1124
1125 #ifdef CONFIG_HS20
1126         if (wpa_s->current_bss &&
1127             wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE)) {
1128                 ret = os_snprintf(pos, end - pos, "hs20=1\n");
1129                 if (ret < 0 || ret >= end - pos)
1130                         return pos - buf;
1131                 pos += ret;
1132         }
1133 #endif /* CONFIG_HS20 */
1134
1135         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1136             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1137                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1138                                           verbose);
1139                 if (res >= 0)
1140                         pos += res;
1141         }
1142
1143         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1144         if (res >= 0)
1145                 pos += res;
1146
1147         return pos - buf;
1148 }
1149
1150
1151 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
1152                                            char *cmd)
1153 {
1154         char *pos;
1155         int id;
1156         struct wpa_ssid *ssid;
1157         u8 bssid[ETH_ALEN];
1158
1159         /* cmd: "<network id> <BSSID>" */
1160         pos = os_strchr(cmd, ' ');
1161         if (pos == NULL)
1162                 return -1;
1163         *pos++ = '\0';
1164         id = atoi(cmd);
1165         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
1166         if (hwaddr_aton(pos, bssid)) {
1167                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
1168                 return -1;
1169         }
1170
1171         ssid = wpa_config_get_network(wpa_s->conf, id);
1172         if (ssid == NULL) {
1173                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1174                            "to update", id);
1175                 return -1;
1176         }
1177
1178         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
1179         ssid->bssid_set = !is_zero_ether_addr(bssid);
1180
1181         return 0;
1182 }
1183
1184
1185 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1186                                                char *cmd, char *buf,
1187                                                size_t buflen)
1188 {
1189         u8 bssid[ETH_ALEN];
1190         struct wpa_blacklist *e;
1191         char *pos, *end;
1192         int ret;
1193
1194         /* cmd: "BLACKLIST [<BSSID>]" */
1195         if (*cmd == '\0') {
1196                 pos = buf;
1197                 end = buf + buflen;
1198                 e = wpa_s->blacklist;
1199                 while (e) {
1200                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
1201                                           MAC2STR(e->bssid));
1202                         if (ret < 0 || ret >= end - pos)
1203                                 return pos - buf;
1204                         pos += ret;
1205                         e = e->next;
1206                 }
1207                 return pos - buf;
1208         }
1209
1210         cmd++;
1211         if (os_strncmp(cmd, "clear", 5) == 0) {
1212                 wpa_blacklist_clear(wpa_s);
1213                 os_memcpy(buf, "OK\n", 3);
1214                 return 3;
1215         }
1216
1217         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1218         if (hwaddr_aton(cmd, bssid)) {
1219                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
1220                 return -1;
1221         }
1222
1223         /*
1224          * Add the BSSID twice, so its count will be 2, causing it to be
1225          * skipped when processing scan results.
1226          */
1227         ret = wpa_blacklist_add(wpa_s, bssid);
1228         if (ret != 0)
1229                 return -1;
1230         ret = wpa_blacklist_add(wpa_s, bssid);
1231         if (ret != 0)
1232                 return -1;
1233         os_memcpy(buf, "OK\n", 3);
1234         return 3;
1235 }
1236
1237
1238 extern int wpa_debug_level;
1239 extern int wpa_debug_timestamp;
1240
1241 static const char * debug_level_str(int level)
1242 {
1243         switch (level) {
1244         case MSG_EXCESSIVE:
1245                 return "EXCESSIVE";
1246         case MSG_MSGDUMP:
1247                 return "MSGDUMP";
1248         case MSG_DEBUG:
1249                 return "DEBUG";
1250         case MSG_INFO:
1251                 return "INFO";
1252         case MSG_WARNING:
1253                 return "WARNING";
1254         case MSG_ERROR:
1255                 return "ERROR";
1256         default:
1257                 return "?";
1258         }
1259 }
1260
1261
1262 static int str_to_debug_level(const char *s)
1263 {
1264         if (os_strcasecmp(s, "EXCESSIVE") == 0)
1265                 return MSG_EXCESSIVE;
1266         if (os_strcasecmp(s, "MSGDUMP") == 0)
1267                 return MSG_MSGDUMP;
1268         if (os_strcasecmp(s, "DEBUG") == 0)
1269                 return MSG_DEBUG;
1270         if (os_strcasecmp(s, "INFO") == 0)
1271                 return MSG_INFO;
1272         if (os_strcasecmp(s, "WARNING") == 0)
1273                 return MSG_WARNING;
1274         if (os_strcasecmp(s, "ERROR") == 0)
1275                 return MSG_ERROR;
1276         return -1;
1277 }
1278
1279
1280 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
1281                                                char *cmd, char *buf,
1282                                                size_t buflen)
1283 {
1284         char *pos, *end, *stamp;
1285         int ret;
1286
1287         if (cmd == NULL) {
1288                 return -1;
1289         }
1290
1291         /* cmd: "LOG_LEVEL [<level>]" */
1292         if (*cmd == '\0') {
1293                 pos = buf;
1294                 end = buf + buflen;
1295                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1296                                   "Timestamp: %d\n",
1297                                   debug_level_str(wpa_debug_level),
1298                                   wpa_debug_timestamp);
1299                 if (ret < 0 || ret >= end - pos)
1300                         ret = 0;
1301
1302                 return ret;
1303         }
1304
1305         while (*cmd == ' ')
1306                 cmd++;
1307
1308         stamp = os_strchr(cmd, ' ');
1309         if (stamp) {
1310                 *stamp++ = '\0';
1311                 while (*stamp == ' ') {
1312                         stamp++;
1313                 }
1314         }
1315
1316         if (cmd && os_strlen(cmd)) {
1317                 int level = str_to_debug_level(cmd);
1318                 if (level < 0)
1319                         return -1;
1320                 wpa_debug_level = level;
1321         }
1322
1323         if (stamp && os_strlen(stamp))
1324                 wpa_debug_timestamp = atoi(stamp);
1325
1326         os_memcpy(buf, "OK\n", 3);
1327         return 3;
1328 }
1329
1330
1331 static int wpa_supplicant_ctrl_iface_list_networks(
1332         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1333 {
1334         char *pos, *end;
1335         struct wpa_ssid *ssid;
1336         int ret;
1337
1338         pos = buf;
1339         end = buf + buflen;
1340         ret = os_snprintf(pos, end - pos,
1341                           "network id / ssid / bssid / flags\n");
1342         if (ret < 0 || ret >= end - pos)
1343                 return pos - buf;
1344         pos += ret;
1345
1346         ssid = wpa_s->conf->ssid;
1347         while (ssid) {
1348                 ret = os_snprintf(pos, end - pos, "%d\t%s",
1349                                   ssid->id,
1350                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1351                 if (ret < 0 || ret >= end - pos)
1352                         return pos - buf;
1353                 pos += ret;
1354                 if (ssid->bssid_set) {
1355                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
1356                                           MAC2STR(ssid->bssid));
1357                 } else {
1358                         ret = os_snprintf(pos, end - pos, "\tany");
1359                 }
1360                 if (ret < 0 || ret >= end - pos)
1361                         return pos - buf;
1362                 pos += ret;
1363                 ret = os_snprintf(pos, end - pos, "\t%s%s%s",
1364                                   ssid == wpa_s->current_ssid ?
1365                                   "[CURRENT]" : "",
1366                                   ssid->disabled ? "[DISABLED]" : "",
1367                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
1368                                   "");
1369                 if (ret < 0 || ret >= end - pos)
1370                         return pos - buf;
1371                 pos += ret;
1372                 ret = os_snprintf(pos, end - pos, "\n");
1373                 if (ret < 0 || ret >= end - pos)
1374                         return pos - buf;
1375                 pos += ret;
1376
1377                 ssid = ssid->next;
1378         }
1379
1380         return pos - buf;
1381 }
1382
1383
1384 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
1385 {
1386         int first = 1, ret;
1387         ret = os_snprintf(pos, end - pos, "-");
1388         if (ret < 0 || ret >= end - pos)
1389                 return pos;
1390         pos += ret;
1391         if (cipher & WPA_CIPHER_NONE) {
1392                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
1393                 if (ret < 0 || ret >= end - pos)
1394                         return pos;
1395                 pos += ret;
1396                 first = 0;
1397         }
1398         if (cipher & WPA_CIPHER_WEP40) {
1399                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
1400                 if (ret < 0 || ret >= end - pos)
1401                         return pos;
1402                 pos += ret;
1403                 first = 0;
1404         }
1405         if (cipher & WPA_CIPHER_WEP104) {
1406                 ret = os_snprintf(pos, end - pos, "%sWEP104",
1407                                   first ? "" : "+");
1408                 if (ret < 0 || ret >= end - pos)
1409                         return pos;
1410                 pos += ret;
1411                 first = 0;
1412         }
1413         if (cipher & WPA_CIPHER_TKIP) {
1414                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
1415                 if (ret < 0 || ret >= end - pos)
1416                         return pos;
1417                 pos += ret;
1418                 first = 0;
1419         }
1420         if (cipher & WPA_CIPHER_CCMP) {
1421                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
1422                 if (ret < 0 || ret >= end - pos)
1423                         return pos;
1424                 pos += ret;
1425                 first = 0;
1426         }
1427         return pos;
1428 }
1429
1430
1431 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
1432                                     const u8 *ie, size_t ie_len)
1433 {
1434         struct wpa_ie_data data;
1435         int first, ret;
1436
1437         ret = os_snprintf(pos, end - pos, "[%s-", proto);
1438         if (ret < 0 || ret >= end - pos)
1439                 return pos;
1440         pos += ret;
1441
1442         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
1443                 ret = os_snprintf(pos, end - pos, "?]");
1444                 if (ret < 0 || ret >= end - pos)
1445                         return pos;
1446                 pos += ret;
1447                 return pos;
1448         }
1449
1450         first = 1;
1451         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
1452                 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
1453                 if (ret < 0 || ret >= end - pos)
1454                         return pos;
1455                 pos += ret;
1456                 first = 0;
1457         }
1458         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
1459                 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
1460                 if (ret < 0 || ret >= end - pos)
1461                         return pos;
1462                 pos += ret;
1463                 first = 0;
1464         }
1465         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
1466                 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
1467                 if (ret < 0 || ret >= end - pos)
1468                         return pos;
1469                 pos += ret;
1470                 first = 0;
1471         }
1472 #ifdef CONFIG_IEEE80211R
1473         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
1474                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
1475                                   first ? "" : "+");
1476                 if (ret < 0 || ret >= end - pos)
1477                         return pos;
1478                 pos += ret;
1479                 first = 0;
1480         }
1481         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
1482                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
1483                                   first ? "" : "+");
1484                 if (ret < 0 || ret >= end - pos)
1485                         return pos;
1486                 pos += ret;
1487                 first = 0;
1488         }
1489 #endif /* CONFIG_IEEE80211R */
1490 #ifdef CONFIG_IEEE80211W
1491         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1492                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
1493                                   first ? "" : "+");
1494                 if (ret < 0 || ret >= end - pos)
1495                         return pos;
1496                 pos += ret;
1497                 first = 0;
1498         }
1499         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
1500                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
1501                                   first ? "" : "+");
1502                 if (ret < 0 || ret >= end - pos)
1503                         return pos;
1504                 pos += ret;
1505                 first = 0;
1506         }
1507 #endif /* CONFIG_IEEE80211W */
1508
1509         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
1510
1511         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
1512                 ret = os_snprintf(pos, end - pos, "-preauth");
1513                 if (ret < 0 || ret >= end - pos)
1514                         return pos;
1515                 pos += ret;
1516         }
1517
1518         ret = os_snprintf(pos, end - pos, "]");
1519         if (ret < 0 || ret >= end - pos)
1520                 return pos;
1521         pos += ret;
1522
1523         return pos;
1524 }
1525
1526
1527 #ifdef CONFIG_WPS
1528 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
1529                                             char *pos, char *end,
1530                                             struct wpabuf *wps_ie)
1531 {
1532         int ret;
1533         const char *txt;
1534
1535         if (wps_ie == NULL)
1536                 return pos;
1537         if (wps_is_selected_pbc_registrar(wps_ie))
1538                 txt = "[WPS-PBC]";
1539 #ifdef CONFIG_WPS2
1540         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
1541                 txt = "[WPS-AUTH]";
1542 #endif /* CONFIG_WPS2 */
1543         else if (wps_is_selected_pin_registrar(wps_ie))
1544                 txt = "[WPS-PIN]";
1545         else
1546                 txt = "[WPS]";
1547
1548         ret = os_snprintf(pos, end - pos, "%s", txt);
1549         if (ret >= 0 && ret < end - pos)
1550                 pos += ret;
1551         wpabuf_free(wps_ie);
1552         return pos;
1553 }
1554 #endif /* CONFIG_WPS */
1555
1556
1557 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
1558                                         char *pos, char *end,
1559                                         const struct wpa_bss *bss)
1560 {
1561 #ifdef CONFIG_WPS
1562         struct wpabuf *wps_ie;
1563         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1564         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
1565 #else /* CONFIG_WPS */
1566         return pos;
1567 #endif /* CONFIG_WPS */
1568 }
1569
1570
1571 /* Format one result on one text line into a buffer. */
1572 static int wpa_supplicant_ctrl_iface_scan_result(
1573         struct wpa_supplicant *wpa_s,
1574         const struct wpa_bss *bss, char *buf, size_t buflen)
1575 {
1576         char *pos, *end;
1577         int ret;
1578         const u8 *ie, *ie2, *p2p;
1579
1580         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
1581         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
1582             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
1583             0)
1584                 return 0; /* Do not show P2P listen discovery results here */
1585
1586         pos = buf;
1587         end = buf + buflen;
1588
1589         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1590                           MAC2STR(bss->bssid), bss->freq, bss->level);
1591         if (ret < 0 || ret >= end - pos)
1592                 return -1;
1593         pos += ret;
1594         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1595         if (ie)
1596                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
1597         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1598         if (ie2)
1599                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
1600         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
1601         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
1602                 ret = os_snprintf(pos, end - pos, "[WEP]");
1603                 if (ret < 0 || ret >= end - pos)
1604                         return -1;
1605                 pos += ret;
1606         }
1607         if (bss->caps & IEEE80211_CAP_IBSS) {
1608                 ret = os_snprintf(pos, end - pos, "[IBSS]");
1609                 if (ret < 0 || ret >= end - pos)
1610                         return -1;
1611                 pos += ret;
1612         }
1613         if (bss->caps & IEEE80211_CAP_ESS) {
1614                 ret = os_snprintf(pos, end - pos, "[ESS]");
1615                 if (ret < 0 || ret >= end - pos)
1616                         return -1;
1617                 pos += ret;
1618         }
1619         if (p2p) {
1620                 ret = os_snprintf(pos, end - pos, "[P2P]");
1621                 if (ret < 0 || ret >= end - pos)
1622                         return -1;
1623                 pos += ret;
1624         }
1625 #ifdef CONFIG_HS20
1626         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
1627                 ret = os_snprintf(pos, end - pos, "[HS20]");
1628                 if (ret < 0 || ret >= end - pos)
1629                         return -1;
1630                 pos += ret;
1631         }
1632 #endif /* CONFIG_HS20 */
1633
1634         ret = os_snprintf(pos, end - pos, "\t%s",
1635                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
1636         if (ret < 0 || ret >= end - pos)
1637                 return -1;
1638         pos += ret;
1639
1640         ret = os_snprintf(pos, end - pos, "\n");
1641         if (ret < 0 || ret >= end - pos)
1642                 return -1;
1643         pos += ret;
1644
1645         return pos - buf;
1646 }
1647
1648
1649 static int wpa_supplicant_ctrl_iface_scan_results(
1650         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1651 {
1652         char *pos, *end;
1653         struct wpa_bss *bss;
1654         int ret;
1655
1656         pos = buf;
1657         end = buf + buflen;
1658         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
1659                           "flags / ssid\n");
1660         if (ret < 0 || ret >= end - pos)
1661                 return pos - buf;
1662         pos += ret;
1663
1664         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1665                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
1666                                                             end - pos);
1667                 if (ret < 0 || ret >= end - pos)
1668                         return pos - buf;
1669                 pos += ret;
1670         }
1671
1672         return pos - buf;
1673 }
1674
1675
1676 static int wpa_supplicant_ctrl_iface_select_network(
1677         struct wpa_supplicant *wpa_s, char *cmd)
1678 {
1679         int id;
1680         struct wpa_ssid *ssid;
1681
1682         /* cmd: "<network id>" or "any" */
1683         if (os_strcmp(cmd, "any") == 0) {
1684                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
1685                 ssid = NULL;
1686         } else {
1687                 id = atoi(cmd);
1688                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
1689
1690                 ssid = wpa_config_get_network(wpa_s->conf, id);
1691                 if (ssid == NULL) {
1692                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1693                                    "network id=%d", id);
1694                         return -1;
1695                 }
1696                 if (ssid->disabled == 2) {
1697                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1698                                    "SELECT_NETWORK with persistent P2P group");
1699                         return -1;
1700                 }
1701         }
1702
1703         wpa_supplicant_select_network(wpa_s, ssid);
1704
1705         return 0;
1706 }
1707
1708
1709 static int wpa_supplicant_ctrl_iface_enable_network(
1710         struct wpa_supplicant *wpa_s, char *cmd)
1711 {
1712         int id;
1713         struct wpa_ssid *ssid;
1714
1715         /* cmd: "<network id>" or "all" */
1716         if (os_strcmp(cmd, "all") == 0) {
1717                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
1718                 ssid = NULL;
1719         } else {
1720                 id = atoi(cmd);
1721                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
1722
1723                 ssid = wpa_config_get_network(wpa_s->conf, id);
1724                 if (ssid == NULL) {
1725                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1726                                    "network id=%d", id);
1727                         return -1;
1728                 }
1729                 if (ssid->disabled == 2) {
1730                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1731                                    "ENABLE_NETWORK with persistent P2P group");
1732                         return -1;
1733                 }
1734
1735                 if (os_strstr(cmd, " no-connect")) {
1736                         ssid->disabled = 0;
1737                         return 0;
1738                 }
1739         }
1740         wpa_supplicant_enable_network(wpa_s, ssid);
1741
1742         return 0;
1743 }
1744
1745
1746 static int wpa_supplicant_ctrl_iface_disable_network(
1747         struct wpa_supplicant *wpa_s, char *cmd)
1748 {
1749         int id;
1750         struct wpa_ssid *ssid;
1751
1752         /* cmd: "<network id>" or "all" */
1753         if (os_strcmp(cmd, "all") == 0) {
1754                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
1755                 ssid = NULL;
1756         } else {
1757                 id = atoi(cmd);
1758                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
1759
1760                 ssid = wpa_config_get_network(wpa_s->conf, id);
1761                 if (ssid == NULL) {
1762                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
1763                                    "network id=%d", id);
1764                         return -1;
1765                 }
1766                 if (ssid->disabled == 2) {
1767                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
1768                                    "DISABLE_NETWORK with persistent P2P "
1769                                    "group");
1770                         return -1;
1771                 }
1772         }
1773         wpa_supplicant_disable_network(wpa_s, ssid);
1774
1775         return 0;
1776 }
1777
1778
1779 static int wpa_supplicant_ctrl_iface_add_network(
1780         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1781 {
1782         struct wpa_ssid *ssid;
1783         int ret;
1784
1785         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
1786
1787         ssid = wpa_config_add_network(wpa_s->conf);
1788         if (ssid == NULL)
1789                 return -1;
1790
1791         wpas_notify_network_added(wpa_s, ssid);
1792
1793         ssid->disabled = 1;
1794         wpa_config_set_network_defaults(ssid);
1795
1796         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
1797         if (ret < 0 || (size_t) ret >= buflen)
1798                 return -1;
1799         return ret;
1800 }
1801
1802
1803 static int wpa_supplicant_ctrl_iface_remove_network(
1804         struct wpa_supplicant *wpa_s, char *cmd)
1805 {
1806         int id;
1807         struct wpa_ssid *ssid;
1808
1809         /* cmd: "<network id>" or "all" */
1810         if (os_strcmp(cmd, "all") == 0) {
1811                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
1812                 ssid = wpa_s->conf->ssid;
1813                 while (ssid) {
1814                         struct wpa_ssid *remove_ssid = ssid;
1815                         id = ssid->id;
1816                         ssid = ssid->next;
1817                         wpas_notify_network_removed(wpa_s, remove_ssid);
1818                         wpa_config_remove_network(wpa_s->conf, id);
1819                 }
1820                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1821                 if (wpa_s->current_ssid) {
1822 #ifdef CONFIG_SME
1823                         wpa_s->sme.prev_bssid_set = 0;
1824 #endif /* CONFIG_SME */
1825                         wpa_sm_set_config(wpa_s->wpa, NULL);
1826                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1827                         wpa_supplicant_disassociate(wpa_s,
1828                                                     WLAN_REASON_DEAUTH_LEAVING);
1829                 }
1830                 return 0;
1831         }
1832
1833         id = atoi(cmd);
1834         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
1835
1836         ssid = wpa_config_get_network(wpa_s->conf, id);
1837         if (ssid)
1838                 wpas_notify_network_removed(wpa_s, ssid);
1839         if (ssid == NULL ||
1840             wpa_config_remove_network(wpa_s->conf, id) < 0) {
1841                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1842                            "id=%d", id);
1843                 return -1;
1844         }
1845
1846         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
1847 #ifdef CONFIG_SME
1848                 wpa_s->sme.prev_bssid_set = 0;
1849 #endif /* CONFIG_SME */
1850                 /*
1851                  * Invalidate the EAP session cache if the current or
1852                  * previously used network is removed.
1853                  */
1854                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1855         }
1856
1857         if (ssid == wpa_s->current_ssid) {
1858                 wpa_sm_set_config(wpa_s->wpa, NULL);
1859                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1860
1861                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1862         }
1863
1864         return 0;
1865 }
1866
1867
1868 static int wpa_supplicant_ctrl_iface_set_network(
1869         struct wpa_supplicant *wpa_s, char *cmd)
1870 {
1871         int id;
1872         struct wpa_ssid *ssid;
1873         char *name, *value;
1874
1875         /* cmd: "<network id> <variable name> <value>" */
1876         name = os_strchr(cmd, ' ');
1877         if (name == NULL)
1878                 return -1;
1879         *name++ = '\0';
1880
1881         value = os_strchr(name, ' ');
1882         if (value == NULL)
1883                 return -1;
1884         *value++ = '\0';
1885
1886         id = atoi(cmd);
1887         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
1888                    id, name);
1889         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1890                               (u8 *) value, os_strlen(value));
1891
1892         ssid = wpa_config_get_network(wpa_s->conf, id);
1893         if (ssid == NULL) {
1894                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1895                            "id=%d", id);
1896                 return -1;
1897         }
1898
1899         if (wpa_config_set(ssid, name, value, 0) < 0) {
1900                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
1901                            "variable '%s'", name);
1902                 return -1;
1903         }
1904
1905         wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1906
1907         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
1908                 /*
1909                  * Invalidate the EAP session cache if anything in the current
1910                  * or previously used configuration changes.
1911                  */
1912                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1913         }
1914
1915         if ((os_strcmp(name, "psk") == 0 &&
1916              value[0] == '"' && ssid->ssid_len) ||
1917             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
1918                 wpa_config_update_psk(ssid);
1919         else if (os_strcmp(name, "priority") == 0)
1920                 wpa_config_update_prio_list(wpa_s->conf);
1921
1922         return 0;
1923 }
1924
1925
1926 static int wpa_supplicant_ctrl_iface_get_network(
1927         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1928 {
1929         int id;
1930         size_t res;
1931         struct wpa_ssid *ssid;
1932         char *name, *value;
1933
1934         /* cmd: "<network id> <variable name>" */
1935         name = os_strchr(cmd, ' ');
1936         if (name == NULL || buflen == 0)
1937                 return -1;
1938         *name++ = '\0';
1939
1940         id = atoi(cmd);
1941         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
1942                    id, name);
1943
1944         ssid = wpa_config_get_network(wpa_s->conf, id);
1945         if (ssid == NULL) {
1946                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
1947                            "id=%d", id);
1948                 return -1;
1949         }
1950
1951         value = wpa_config_get_no_key(ssid, name);
1952         if (value == NULL) {
1953                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
1954                            "variable '%s'", name);
1955                 return -1;
1956         }
1957
1958         res = os_strlcpy(buf, value, buflen);
1959         if (res >= buflen) {
1960                 os_free(value);
1961                 return -1;
1962         }
1963
1964         os_free(value);
1965
1966         return res;
1967 }
1968
1969
1970 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
1971                                                 char *buf, size_t buflen)
1972 {
1973         char *pos, *end;
1974         struct wpa_cred *cred;
1975         int ret;
1976
1977         pos = buf;
1978         end = buf + buflen;
1979         ret = os_snprintf(pos, end - pos,
1980                           "cred id / realm / username / domain / imsi\n");
1981         if (ret < 0 || ret >= end - pos)
1982                 return pos - buf;
1983         pos += ret;
1984
1985         cred = wpa_s->conf->cred;
1986         while (cred) {
1987                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
1988                                   cred->id, cred->realm ? cred->realm : "",
1989                                   cred->username ? cred->username : "",
1990                                   cred->domain ? cred->domain : "",
1991                                   cred->imsi ? cred->imsi : "");
1992                 if (ret < 0 || ret >= end - pos)
1993                         return pos - buf;
1994                 pos += ret;
1995
1996                 cred = cred->next;
1997         }
1998
1999         return pos - buf;
2000 }
2001
2002
2003 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2004                                               char *buf, size_t buflen)
2005 {
2006         struct wpa_cred *cred;
2007         int ret;
2008
2009         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2010
2011         cred = wpa_config_add_cred(wpa_s->conf);
2012         if (cred == NULL)
2013                 return -1;
2014
2015         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2016         if (ret < 0 || (size_t) ret >= buflen)
2017                 return -1;
2018         return ret;
2019 }
2020
2021
2022 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2023                                                  char *cmd)
2024 {
2025         int id;
2026         struct wpa_cred *cred;
2027
2028         /* cmd: "<cred id>" or "all" */
2029         if (os_strcmp(cmd, "all") == 0) {
2030                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2031                 cred = wpa_s->conf->cred;
2032                 while (cred) {
2033                         id = cred->id;
2034                         cred = cred->next;
2035                         wpa_config_remove_cred(wpa_s->conf, id);
2036                 }
2037                 return 0;
2038         }
2039
2040         id = atoi(cmd);
2041         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2042
2043         cred = wpa_config_get_cred(wpa_s->conf, id);
2044         if (cred == NULL ||
2045             wpa_config_remove_cred(wpa_s->conf, id) < 0) {
2046                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2047                            id);
2048                 return -1;
2049         }
2050
2051         return 0;
2052 }
2053
2054
2055 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2056                                               char *cmd)
2057 {
2058         int id;
2059         struct wpa_cred *cred;
2060         char *name, *value;
2061
2062         /* cmd: "<cred id> <variable name> <value>" */
2063         name = os_strchr(cmd, ' ');
2064         if (name == NULL)
2065                 return -1;
2066         *name++ = '\0';
2067
2068         value = os_strchr(name, ' ');
2069         if (value == NULL)
2070                 return -1;
2071         *value++ = '\0';
2072
2073         id = atoi(cmd);
2074         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2075                    id, name);
2076         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2077                               (u8 *) value, os_strlen(value));
2078
2079         cred = wpa_config_get_cred(wpa_s->conf, id);
2080         if (cred == NULL) {
2081                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2082                            id);
2083                 return -1;
2084         }
2085
2086         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2087                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2088                            "variable '%s'", name);
2089                 return -1;
2090         }
2091
2092         return 0;
2093 }
2094
2095
2096 #ifndef CONFIG_NO_CONFIG_WRITE
2097 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2098 {
2099         int ret;
2100
2101         if (!wpa_s->conf->update_config) {
2102                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2103                            "to update configuration (update_config=0)");
2104                 return -1;
2105         }
2106
2107         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2108         if (ret) {
2109                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2110                            "update configuration");
2111         } else {
2112                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2113                            " updated");
2114         }
2115
2116         return ret;
2117 }
2118 #endif /* CONFIG_NO_CONFIG_WRITE */
2119
2120
2121 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2122                                               struct wpa_driver_capa *capa,
2123                                               char *buf, size_t buflen)
2124 {
2125         int ret, first = 1;
2126         char *pos, *end;
2127         size_t len;
2128
2129         pos = buf;
2130         end = pos + buflen;
2131
2132         if (res < 0) {
2133                 if (strict)
2134                         return 0;
2135                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2136                 if (len >= buflen)
2137                         return -1;
2138                 return len;
2139         }
2140
2141         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2142                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2143                 if (ret < 0 || ret >= end - pos)
2144                         return pos - buf;
2145                 pos += ret;
2146                 first = 0;
2147         }
2148
2149         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2150                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2151                 if (ret < 0 || ret >= end - pos)
2152                         return pos - buf;
2153                 pos += ret;
2154                 first = 0;
2155         }
2156
2157         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2158                 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
2159                 if (ret < 0 || ret >= end - pos)
2160                         return pos - buf;
2161                 pos += ret;
2162                 first = 0;
2163         }
2164
2165         return pos - buf;
2166 }
2167
2168
2169 static int ctrl_iface_get_capability_group(int res, char *strict,
2170                                            struct wpa_driver_capa *capa,
2171                                            char *buf, size_t buflen)
2172 {
2173         int ret, first = 1;
2174         char *pos, *end;
2175         size_t len;
2176
2177         pos = buf;
2178         end = pos + buflen;
2179
2180         if (res < 0) {
2181                 if (strict)
2182                         return 0;
2183                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2184                 if (len >= buflen)
2185                         return -1;
2186                 return len;
2187         }
2188
2189         if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2190                 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
2191                 if (ret < 0 || ret >= end - pos)
2192                         return pos - buf;
2193                 pos += ret;
2194                 first = 0;
2195         }
2196
2197         if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2198                 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
2199                 if (ret < 0 || ret >= end - pos)
2200                         return pos - buf;
2201                 pos += ret;
2202                 first = 0;
2203         }
2204
2205         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2206                 ret = os_snprintf(pos, end - pos, "%sWEP104",
2207                                   first ? "" : " ");
2208                 if (ret < 0 || ret >= end - pos)
2209                         return pos - buf;
2210                 pos += ret;
2211                 first = 0;
2212         }
2213
2214         if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2215                 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
2216                 if (ret < 0 || ret >= end - pos)
2217                         return pos - buf;
2218                 pos += ret;
2219                 first = 0;
2220         }
2221
2222         return pos - buf;
2223 }
2224
2225
2226 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2227                                               struct wpa_driver_capa *capa,
2228                                               char *buf, size_t buflen)
2229 {
2230         int ret;
2231         char *pos, *end;
2232         size_t len;
2233
2234         pos = buf;
2235         end = pos + buflen;
2236
2237         if (res < 0) {
2238                 if (strict)
2239                         return 0;
2240                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
2241                                  "NONE", buflen);
2242                 if (len >= buflen)
2243                         return -1;
2244                 return len;
2245         }
2246
2247         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
2248         if (ret < 0 || ret >= end - pos)
2249                 return pos - buf;
2250         pos += ret;
2251
2252         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2253                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2254                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
2255                 if (ret < 0 || ret >= end - pos)
2256                         return pos - buf;
2257                 pos += ret;
2258         }
2259
2260         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2261                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2262                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
2263                 if (ret < 0 || ret >= end - pos)
2264                         return pos - buf;
2265                 pos += ret;
2266         }
2267
2268         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2269                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
2270                 if (ret < 0 || ret >= end - pos)
2271                         return pos - buf;
2272                 pos += ret;
2273         }
2274
2275         return pos - buf;
2276 }
2277
2278
2279 static int ctrl_iface_get_capability_proto(int res, char *strict,
2280                                            struct wpa_driver_capa *capa,
2281                                            char *buf, size_t buflen)
2282 {
2283         int ret, first = 1;
2284         char *pos, *end;
2285         size_t len;
2286
2287         pos = buf;
2288         end = pos + buflen;
2289
2290         if (res < 0) {
2291                 if (strict)
2292                         return 0;
2293                 len = os_strlcpy(buf, "RSN WPA", buflen);
2294                 if (len >= buflen)
2295                         return -1;
2296                 return len;
2297         }
2298
2299         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2300                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2301                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
2302                 if (ret < 0 || ret >= end - pos)
2303                         return pos - buf;
2304                 pos += ret;
2305                 first = 0;
2306         }
2307
2308         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2309                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2310                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
2311                 if (ret < 0 || ret >= end - pos)
2312                         return pos - buf;
2313                 pos += ret;
2314                 first = 0;
2315         }
2316
2317         return pos - buf;
2318 }
2319
2320
2321 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
2322                                               struct wpa_driver_capa *capa,
2323                                               char *buf, size_t buflen)
2324 {
2325         int ret, first = 1;
2326         char *pos, *end;
2327         size_t len;
2328
2329         pos = buf;
2330         end = pos + buflen;
2331
2332         if (res < 0) {
2333                 if (strict)
2334                         return 0;
2335                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
2336                 if (len >= buflen)
2337                         return -1;
2338                 return len;
2339         }
2340
2341         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
2342                 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
2343                 if (ret < 0 || ret >= end - pos)
2344                         return pos - buf;
2345                 pos += ret;
2346                 first = 0;
2347         }
2348
2349         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
2350                 ret = os_snprintf(pos, end - pos, "%sSHARED",
2351                                   first ? "" : " ");
2352                 if (ret < 0 || ret >= end - pos)
2353                         return pos - buf;
2354                 pos += ret;
2355                 first = 0;
2356         }
2357
2358         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
2359                 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
2360                 if (ret < 0 || ret >= end - pos)
2361                         return pos - buf;
2362                 pos += ret;
2363                 first = 0;
2364         }
2365
2366         return pos - buf;
2367 }
2368
2369
2370 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
2371                                               char *buf, size_t buflen)
2372 {
2373         struct hostapd_channel_data *chnl;
2374         int ret, i, j;
2375         char *pos, *end, *hmode;
2376
2377         pos = buf;
2378         end = pos + buflen;
2379
2380         for (j = 0; j < wpa_s->hw.num_modes; j++) {
2381                 switch (wpa_s->hw.modes[j].mode) {
2382                 case HOSTAPD_MODE_IEEE80211B:
2383                         hmode = "B";
2384                         break;
2385                 case HOSTAPD_MODE_IEEE80211G:
2386                         hmode = "G";
2387                         break;
2388                 case HOSTAPD_MODE_IEEE80211A:
2389                         hmode = "A";
2390                         break;
2391                 default:
2392                         continue;
2393                 }
2394                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
2395                 if (ret < 0 || ret >= end - pos)
2396                         return pos - buf;
2397                 pos += ret;
2398                 chnl = wpa_s->hw.modes[j].channels;
2399                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
2400                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
2401                                 continue;
2402                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
2403                         if (ret < 0 || ret >= end - pos)
2404                                 return pos - buf;
2405                         pos += ret;
2406                 }
2407                 ret = os_snprintf(pos, end - pos, "\n");
2408                 if (ret < 0 || ret >= end - pos)
2409                         return pos - buf;
2410                 pos += ret;
2411         }
2412
2413         return pos - buf;
2414 }
2415
2416
2417 static int wpa_supplicant_ctrl_iface_get_capability(
2418         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
2419         size_t buflen)
2420 {
2421         struct wpa_driver_capa capa;
2422         int res;
2423         char *strict;
2424         char field[30];
2425         size_t len;
2426
2427         /* Determine whether or not strict checking was requested */
2428         len = os_strlcpy(field, _field, sizeof(field));
2429         if (len >= sizeof(field))
2430                 return -1;
2431         strict = os_strchr(field, ' ');
2432         if (strict != NULL) {
2433                 *strict++ = '\0';
2434                 if (os_strcmp(strict, "strict") != 0)
2435                         return -1;
2436         }
2437
2438         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
2439                 field, strict ? strict : "");
2440
2441         if (os_strcmp(field, "eap") == 0) {
2442                 return eap_get_names(buf, buflen);
2443         }
2444
2445         res = wpa_drv_get_capa(wpa_s, &capa);
2446
2447         if (os_strcmp(field, "pairwise") == 0)
2448                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
2449                                                           buf, buflen);
2450
2451         if (os_strcmp(field, "group") == 0)
2452                 return ctrl_iface_get_capability_group(res, strict, &capa,
2453                                                        buf, buflen);
2454
2455         if (os_strcmp(field, "key_mgmt") == 0)
2456                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
2457                                                           buf, buflen);
2458
2459         if (os_strcmp(field, "proto") == 0)
2460                 return ctrl_iface_get_capability_proto(res, strict, &capa,
2461                                                        buf, buflen);
2462
2463         if (os_strcmp(field, "auth_alg") == 0)
2464                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
2465                                                           buf, buflen);
2466
2467         if (os_strcmp(field, "channels") == 0)
2468                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
2469
2470         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
2471                    field);
2472
2473         return -1;
2474 }
2475
2476
2477 #ifdef CONFIG_INTERWORKING
2478 static char * anqp_add_hex(char *pos, char *end, const char *title,
2479                            struct wpabuf *data)
2480 {
2481         char *start = pos;
2482         size_t i;
2483         int ret;
2484         const u8 *d;
2485
2486         if (data == NULL)
2487                 return start;
2488
2489         ret = os_snprintf(pos, end - pos, "%s=", title);
2490         if (ret < 0 || ret >= end - pos)
2491                 return start;
2492         pos += ret;
2493
2494         d = wpabuf_head_u8(data);
2495         for (i = 0; i < wpabuf_len(data); i++) {
2496                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
2497                 if (ret < 0 || ret >= end - pos)
2498                         return start;
2499                 pos += ret;
2500         }
2501
2502         ret = os_snprintf(pos, end - pos, "\n");
2503         if (ret < 0 || ret >= end - pos)
2504                 return start;
2505         pos += ret;
2506
2507         return pos;
2508 }
2509 #endif /* CONFIG_INTERWORKING */
2510
2511
2512 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
2513                           unsigned long mask, char *buf, size_t buflen)
2514 {
2515         size_t i;
2516         int ret;
2517         char *pos, *end;
2518         const u8 *ie, *ie2;
2519
2520         pos = buf;
2521         end = buf + buflen;
2522
2523         if (mask & WPA_BSS_MASK_ID) {
2524                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
2525                 if (ret < 0 || ret >= end - pos)
2526                         return 0;
2527                 pos += ret;
2528         }
2529
2530         if (mask & WPA_BSS_MASK_BSSID) {
2531                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
2532                                   MAC2STR(bss->bssid));
2533                 if (ret < 0 || ret >= end - pos)
2534                         return 0;
2535                 pos += ret;
2536         }
2537
2538         if (mask & WPA_BSS_MASK_FREQ) {
2539                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
2540                 if (ret < 0 || ret >= end - pos)
2541                         return 0;
2542                 pos += ret;
2543         }
2544
2545         if (mask & WPA_BSS_MASK_BEACON_INT) {
2546                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
2547                                   bss->beacon_int);
2548                 if (ret < 0 || ret >= end - pos)
2549                         return 0;
2550                 pos += ret;
2551         }
2552
2553         if (mask & WPA_BSS_MASK_CAPABILITIES) {
2554                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
2555                                   bss->caps);
2556                 if (ret < 0 || ret >= end - pos)
2557                         return 0;
2558                 pos += ret;
2559         }
2560
2561         if (mask & WPA_BSS_MASK_QUAL) {
2562                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
2563                 if (ret < 0 || ret >= end - pos)
2564                         return 0;
2565                 pos += ret;
2566         }
2567
2568         if (mask & WPA_BSS_MASK_NOISE) {
2569                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
2570                 if (ret < 0 || ret >= end - pos)
2571                         return 0;
2572                 pos += ret;
2573         }
2574
2575         if (mask & WPA_BSS_MASK_LEVEL) {
2576                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
2577                 if (ret < 0 || ret >= end - pos)
2578                         return 0;
2579                 pos += ret;
2580         }
2581
2582         if (mask & WPA_BSS_MASK_TSF) {
2583                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
2584                                   (unsigned long long) bss->tsf);
2585                 if (ret < 0 || ret >= end - pos)
2586                         return 0;
2587                 pos += ret;
2588         }
2589
2590         if (mask & WPA_BSS_MASK_AGE) {
2591                 struct os_time now;
2592
2593                 os_get_time(&now);
2594                 ret = os_snprintf(pos, end - pos, "age=%d\n",
2595                                   (int) (now.sec - bss->last_update.sec));
2596                 if (ret < 0 || ret >= end - pos)
2597                         return 0;
2598                 pos += ret;
2599         }
2600
2601         if (mask & WPA_BSS_MASK_IE) {
2602                 ret = os_snprintf(pos, end - pos, "ie=");
2603                 if (ret < 0 || ret >= end - pos)
2604                         return 0;
2605                 pos += ret;
2606
2607                 ie = (const u8 *) (bss + 1);
2608                 for (i = 0; i < bss->ie_len; i++) {
2609                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
2610                         if (ret < 0 || ret >= end - pos)
2611                                 return 0;
2612                         pos += ret;
2613                 }
2614
2615                 ret = os_snprintf(pos, end - pos, "\n");
2616                 if (ret < 0 || ret >= end - pos)
2617                         return 0;
2618                 pos += ret;
2619         }
2620
2621         if (mask & WPA_BSS_MASK_FLAGS) {
2622                 ret = os_snprintf(pos, end - pos, "flags=");
2623                 if (ret < 0 || ret >= end - pos)
2624                         return 0;
2625                 pos += ret;
2626
2627                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2628                 if (ie)
2629                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
2630                                                     2 + ie[1]);
2631                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2632                 if (ie2)
2633                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
2634                                                     2 + ie2[1]);
2635                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2636                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2637                         ret = os_snprintf(pos, end - pos, "[WEP]");
2638                         if (ret < 0 || ret >= end - pos)
2639                                 return 0;
2640                         pos += ret;
2641                 }
2642                 if (bss->caps & IEEE80211_CAP_IBSS) {
2643                         ret = os_snprintf(pos, end - pos, "[IBSS]");
2644                         if (ret < 0 || ret >= end - pos)
2645                                 return 0;
2646                         pos += ret;
2647                 }
2648                 if (bss->caps & IEEE80211_CAP_ESS) {
2649                         ret = os_snprintf(pos, end - pos, "[ESS]");
2650                         if (ret < 0 || ret >= end - pos)
2651                                 return 0;
2652                         pos += ret;
2653                 }
2654                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
2655                         ret = os_snprintf(pos, end - pos, "[P2P]");
2656                         if (ret < 0 || ret >= end - pos)
2657                                 return 0;
2658                         pos += ret;
2659                 }
2660 #ifdef CONFIG_HS20
2661                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
2662                         ret = os_snprintf(pos, end - pos, "[HS20]");
2663                         if (ret < 0 || ret >= end - pos)
2664                                 return -1;
2665                         pos += ret;
2666                 }
2667 #endif /* CONFIG_HS20 */
2668
2669                 ret = os_snprintf(pos, end - pos, "\n");
2670                 if (ret < 0 || ret >= end - pos)
2671                         return 0;
2672                 pos += ret;
2673         }
2674
2675         if (mask & WPA_BSS_MASK_SSID) {
2676                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
2677                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
2678                 if (ret < 0 || ret >= end - pos)
2679                         return 0;
2680                 pos += ret;
2681         }
2682
2683 #ifdef CONFIG_WPS
2684         if (mask & WPA_BSS_MASK_WPS_SCAN) {
2685                 ie = (const u8 *) (bss + 1);
2686                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
2687                 if (ret < 0 || ret >= end - pos)
2688                         return 0;
2689                 pos += ret;
2690         }
2691 #endif /* CONFIG_WPS */
2692
2693 #ifdef CONFIG_P2P
2694         if (mask & WPA_BSS_MASK_P2P_SCAN) {
2695                 ie = (const u8 *) (bss + 1);
2696                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
2697                 if (ret < 0 || ret >= end - pos)
2698                         return 0;
2699                 pos += ret;
2700         }
2701 #endif /* CONFIG_P2P */
2702
2703 #ifdef CONFIG_INTERWORKING
2704         if (mask & WPA_BSS_MASK_INTERNETW) {
2705                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
2706                                    bss->anqp_venue_name);
2707                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
2708                                    bss->anqp_network_auth_type);
2709                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
2710                                    bss->anqp_roaming_consortium);
2711                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
2712                                    bss->anqp_ip_addr_type_availability);
2713                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
2714                                    bss->anqp_nai_realm);
2715                 pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp);
2716                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
2717                                    bss->anqp_domain_name);
2718 #ifdef CONFIG_HS20
2719                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
2720                                    bss->hs20_operator_friendly_name);
2721                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
2722                                    bss->hs20_wan_metrics);
2723                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
2724                                    bss->hs20_connection_capability);
2725 #endif /* CONFIG_HS20 */
2726         }
2727 #endif /* CONFIG_INTERWORKING */
2728
2729         return pos - buf;
2730 }
2731
2732
2733 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
2734                                          const char *cmd, char *buf,
2735                                          size_t buflen)
2736 {
2737         u8 bssid[ETH_ALEN];
2738         size_t i;
2739         struct wpa_bss *bss;
2740         struct wpa_bss *bsslast = NULL;
2741         struct dl_list *next;
2742         int ret = 0;
2743         int len;
2744         char *ctmp;
2745         unsigned long mask = WPA_BSS_MASK_ALL;
2746
2747         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
2748                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
2749                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
2750                                             list_id);
2751                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
2752                                                list_id);
2753                 } else { /* N1-N2 */
2754                         unsigned int id1, id2;
2755
2756                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
2757                                 wpa_printf(MSG_INFO, "Wrong BSS range "
2758                                            "format");
2759                                 return 0;
2760                         }
2761
2762                         id1 = atoi(cmd + 6);
2763                         bss = wpa_bss_get_id(wpa_s, id1);
2764                         id2 = atoi(ctmp + 1);
2765                         if (id2 == 0)
2766                                 bsslast = dl_list_last(&wpa_s->bss_id,
2767                                                        struct wpa_bss,
2768                                                        list_id);
2769                         else {
2770                                 bsslast = wpa_bss_get_id(wpa_s, id2);
2771                                 if (bsslast == NULL && bss && id2 > id1) {
2772                                         struct wpa_bss *tmp = bss;
2773                                         for (;;) {
2774                                                 next = tmp->list_id.next;
2775                                                 if (next == &wpa_s->bss_id)
2776                                                         break;
2777                                                 tmp = dl_list_entry(
2778                                                         next, struct wpa_bss,
2779                                                         list_id);
2780                                                 if (tmp->id > id2)
2781                                                         break;
2782                                                 bsslast = tmp;
2783                                         }
2784                                 }
2785                         }
2786                 }
2787         } else if (os_strcmp(cmd, "FIRST") == 0)
2788                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
2789         else if (os_strncmp(cmd, "ID-", 3) == 0) {
2790                 i = atoi(cmd + 3);
2791                 bss = wpa_bss_get_id(wpa_s, i);
2792         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
2793                 i = atoi(cmd + 5);
2794                 bss = wpa_bss_get_id(wpa_s, i);
2795                 if (bss) {
2796                         next = bss->list_id.next;
2797                         if (next == &wpa_s->bss_id)
2798                                 bss = NULL;
2799                         else
2800                                 bss = dl_list_entry(next, struct wpa_bss,
2801                                                     list_id);
2802                 }
2803 #ifdef CONFIG_P2P
2804         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
2805                 if (hwaddr_aton(cmd + 13, bssid) == 0)
2806                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
2807                 else
2808                         bss = NULL;
2809 #endif /* CONFIG_P2P */
2810         } else if (hwaddr_aton(cmd, bssid) == 0)
2811                 bss = wpa_bss_get_bssid(wpa_s, bssid);
2812         else {
2813                 struct wpa_bss *tmp;
2814                 i = atoi(cmd);
2815                 bss = NULL;
2816                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
2817                 {
2818                         if (i-- == 0) {
2819                                 bss = tmp;
2820                                 break;
2821                         }
2822                 }
2823         }
2824
2825         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
2826                 mask = strtoul(ctmp + 5, NULL, 0x10);
2827                 if (mask == 0)
2828                         mask = WPA_BSS_MASK_ALL;
2829         }
2830
2831         if (bss == NULL)
2832                 return 0;
2833
2834         if (bsslast == NULL)
2835                 bsslast = bss;
2836         do {
2837                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
2838                 ret += len;
2839                 buf += len;
2840                 buflen -= len;
2841                 if (bss == bsslast)
2842                         break;
2843                 next = bss->list_id.next;
2844                 if (next == &wpa_s->bss_id)
2845                         break;
2846                 bss = dl_list_entry(next, struct wpa_bss, list_id);
2847         } while (bss && len);
2848
2849         return ret;
2850 }
2851
2852
2853 static int wpa_supplicant_ctrl_iface_ap_scan(
2854         struct wpa_supplicant *wpa_s, char *cmd)
2855 {
2856         int ap_scan = atoi(cmd);
2857         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
2858 }
2859
2860
2861 static int wpa_supplicant_ctrl_iface_scan_interval(
2862         struct wpa_supplicant *wpa_s, char *cmd)
2863 {
2864         int scan_int = atoi(cmd);
2865         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
2866 }
2867
2868
2869 static int wpa_supplicant_ctrl_iface_bss_expire_age(
2870         struct wpa_supplicant *wpa_s, char *cmd)
2871 {
2872         int expire_age = atoi(cmd);
2873         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
2874 }
2875
2876
2877 static int wpa_supplicant_ctrl_iface_bss_expire_count(
2878         struct wpa_supplicant *wpa_s, char *cmd)
2879 {
2880         int expire_count = atoi(cmd);
2881         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
2882 }
2883
2884
2885 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
2886 {
2887         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
2888         /* MLME-DELETEKEYS.request */
2889         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
2890         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
2891         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
2892         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
2893 #ifdef CONFIG_IEEE80211W
2894         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
2895         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
2896 #endif /* CONFIG_IEEE80211W */
2897
2898         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
2899                         0);
2900         /* MLME-SETPROTECTION.request(None) */
2901         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
2902                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
2903                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2904         wpa_sm_drop_sa(wpa_s->wpa);
2905 }
2906
2907
2908 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
2909                                           char *addr)
2910 {
2911 #ifdef CONFIG_NO_SCAN_PROCESSING
2912         return -1;
2913 #else /* CONFIG_NO_SCAN_PROCESSING */
2914         u8 bssid[ETH_ALEN];
2915         struct wpa_bss *bss;
2916         struct wpa_ssid *ssid = wpa_s->current_ssid;
2917
2918         if (hwaddr_aton(addr, bssid)) {
2919                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
2920                            "address '%s'", addr);
2921                 return -1;
2922         }
2923
2924         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
2925
2926         bss = wpa_bss_get_bssid(wpa_s, bssid);
2927         if (!bss) {
2928                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
2929                            "from BSS table");
2930                 return -1;
2931         }
2932
2933         /*
2934          * TODO: Find best network configuration block from configuration to
2935          * allow roaming to other networks
2936          */
2937
2938         if (!ssid) {
2939                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
2940                            "configuration known for the target AP");
2941                 return -1;
2942         }
2943
2944         wpa_s->reassociate = 1;
2945         wpa_supplicant_connect(wpa_s, bss, ssid);
2946
2947         return 0;
2948 #endif /* CONFIG_NO_SCAN_PROCESSING */
2949 }
2950
2951
2952 #ifdef CONFIG_P2P
2953 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
2954 {
2955         unsigned int timeout = atoi(cmd);
2956         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
2957         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
2958         char *pos;
2959
2960         if (os_strstr(cmd, "type=social"))
2961                 type = P2P_FIND_ONLY_SOCIAL;
2962         else if (os_strstr(cmd, "type=progressive"))
2963                 type = P2P_FIND_PROGRESSIVE;
2964
2965         pos = os_strstr(cmd, "dev_id=");
2966         if (pos) {
2967                 pos += 7;
2968                 if (hwaddr_aton(pos, dev_id))
2969                         return -1;
2970                 _dev_id = dev_id;
2971         }
2972
2973         return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id);
2974 }
2975
2976
2977 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
2978                             char *buf, size_t buflen)
2979 {
2980         u8 addr[ETH_ALEN];
2981         char *pos, *pos2;
2982         char *pin = NULL;
2983         enum p2p_wps_method wps_method;
2984         int new_pin;
2985         int ret;
2986         int persistent_group, persistent_id = -1;
2987         int join;
2988         int auth;
2989         int automatic;
2990         int go_intent = -1;
2991         int freq = 0;
2992         int pd;
2993
2994         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
2995          * [persistent|persistent=<network id>]
2996          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] */
2997
2998         if (hwaddr_aton(cmd, addr))
2999                 return -1;
3000
3001         pos = cmd + 17;
3002         if (*pos != ' ')
3003                 return -1;
3004         pos++;
3005
3006         persistent_group = os_strstr(pos, " persistent") != NULL;
3007         pos2 = os_strstr(pos, " persistent=");
3008         if (pos2) {
3009                 struct wpa_ssid *ssid;
3010                 persistent_id = atoi(pos2 + 12);
3011                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3012                 if (ssid == NULL || ssid->disabled != 2 ||
3013                     ssid->mode != WPAS_MODE_P2P_GO) {
3014                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3015                                    "SSID id=%d for persistent P2P group (GO)",
3016                                    persistent_id);
3017                         return -1;
3018                 }
3019         }
3020         join = os_strstr(pos, " join") != NULL;
3021         auth = os_strstr(pos, " auth") != NULL;
3022         automatic = os_strstr(pos, " auto") != NULL;
3023         pd = os_strstr(pos, " provdisc") != NULL;
3024
3025         pos2 = os_strstr(pos, " go_intent=");
3026         if (pos2) {
3027                 pos2 += 11;
3028                 go_intent = atoi(pos2);
3029                 if (go_intent < 0 || go_intent > 15)
3030                         return -1;
3031         }
3032
3033         pos2 = os_strstr(pos, " freq=");
3034         if (pos2) {
3035                 pos2 += 6;
3036                 freq = atoi(pos2);
3037                 if (freq <= 0)
3038                         return -1;
3039         }
3040
3041         if (os_strncmp(pos, "pin", 3) == 0) {
3042                 /* Request random PIN (to be displayed) and enable the PIN */
3043                 wps_method = WPS_PIN_DISPLAY;
3044         } else if (os_strncmp(pos, "pbc", 3) == 0) {
3045                 wps_method = WPS_PBC;
3046         } else {
3047                 pin = pos;
3048                 pos = os_strchr(pin, ' ');
3049                 wps_method = WPS_PIN_KEYPAD;
3050                 if (pos) {
3051                         *pos++ = '\0';
3052                         if (os_strncmp(pos, "display", 7) == 0)
3053                                 wps_method = WPS_PIN_DISPLAY;
3054                 }
3055                 if (!wps_pin_str_valid(pin)) {
3056                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
3057                         return 17;
3058                 }
3059         }
3060
3061         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
3062                                    persistent_group, automatic, join,
3063                                    auth, go_intent, freq, persistent_id, pd);
3064         if (new_pin == -2) {
3065                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
3066                 return 25;
3067         }
3068         if (new_pin == -3) {
3069                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
3070                 return 25;
3071         }
3072         if (new_pin < 0)
3073                 return -1;
3074         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
3075                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
3076                 if (ret < 0 || (size_t) ret >= buflen)
3077                         return -1;
3078                 return ret;
3079         }
3080
3081         os_memcpy(buf, "OK\n", 3);
3082         return 3;
3083 }
3084
3085
3086 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
3087 {
3088         unsigned int timeout = atoi(cmd);
3089         return wpas_p2p_listen(wpa_s, timeout);
3090 }
3091
3092
3093 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
3094 {
3095         u8 addr[ETH_ALEN];
3096         char *pos;
3097         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
3098
3099         /* <addr> <config method> [join|auto] */
3100
3101         if (hwaddr_aton(cmd, addr))
3102                 return -1;
3103
3104         pos = cmd + 17;
3105         if (*pos != ' ')
3106                 return -1;
3107         pos++;
3108
3109         if (os_strstr(pos, " join") != NULL)
3110                 use = WPAS_P2P_PD_FOR_JOIN;
3111         else if (os_strstr(pos, " auto") != NULL)
3112                 use = WPAS_P2P_PD_AUTO;
3113
3114         return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
3115 }
3116
3117
3118 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
3119                               size_t buflen)
3120 {
3121         struct wpa_ssid *ssid = wpa_s->current_ssid;
3122
3123         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
3124             ssid->passphrase == NULL)
3125                 return -1;
3126
3127         os_strlcpy(buf, ssid->passphrase, buflen);
3128         return os_strlen(buf);
3129 }
3130
3131
3132 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
3133                                   char *buf, size_t buflen)
3134 {
3135         u64 ref;
3136         int res;
3137         u8 dst_buf[ETH_ALEN], *dst;
3138         struct wpabuf *tlvs;
3139         char *pos;
3140         size_t len;
3141
3142         if (hwaddr_aton(cmd, dst_buf))
3143                 return -1;
3144         dst = dst_buf;
3145         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
3146             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
3147                 dst = NULL;
3148         pos = cmd + 17;
3149         if (*pos != ' ')
3150                 return -1;
3151         pos++;
3152
3153         if (os_strncmp(pos, "upnp ", 5) == 0) {
3154                 u8 version;
3155                 pos += 5;
3156                 if (hexstr2bin(pos, &version, 1) < 0)
3157                         return -1;
3158                 pos += 2;
3159                 if (*pos != ' ')
3160                         return -1;
3161                 pos++;
3162                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
3163         } else {
3164                 len = os_strlen(pos);
3165                 if (len & 1)
3166                         return -1;
3167                 len /= 2;
3168                 tlvs = wpabuf_alloc(len);
3169                 if (tlvs == NULL)
3170                         return -1;
3171                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
3172                         wpabuf_free(tlvs);
3173                         return -1;
3174                 }
3175
3176                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
3177                 wpabuf_free(tlvs);
3178         }
3179         if (ref == 0)
3180                 return -1;
3181         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
3182         if (res < 0 || (unsigned) res >= buflen)
3183                 return -1;
3184         return res;
3185 }
3186
3187
3188 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
3189                                          char *cmd)
3190 {
3191         long long unsigned val;
3192         u64 req;
3193         if (sscanf(cmd, "%llx", &val) != 1)
3194                 return -1;
3195         req = val;
3196         return wpas_p2p_sd_cancel_request(wpa_s, req);
3197 }
3198
3199
3200 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
3201 {
3202         int freq;
3203         u8 dst[ETH_ALEN];
3204         u8 dialog_token;
3205         struct wpabuf *resp_tlvs;
3206         char *pos, *pos2;
3207         size_t len;
3208
3209         pos = os_strchr(cmd, ' ');
3210         if (pos == NULL)
3211                 return -1;
3212         *pos++ = '\0';
3213         freq = atoi(cmd);
3214         if (freq == 0)
3215                 return -1;
3216
3217         if (hwaddr_aton(pos, dst))
3218                 return -1;
3219         pos += 17;
3220         if (*pos != ' ')
3221                 return -1;
3222         pos++;
3223
3224         pos2 = os_strchr(pos, ' ');
3225         if (pos2 == NULL)
3226                 return -1;
3227         *pos2++ = '\0';
3228         dialog_token = atoi(pos);
3229
3230         len = os_strlen(pos2);
3231         if (len & 1)
3232                 return -1;
3233         len /= 2;
3234         resp_tlvs = wpabuf_alloc(len);
3235         if (resp_tlvs == NULL)
3236                 return -1;
3237         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
3238                 wpabuf_free(resp_tlvs);
3239                 return -1;
3240         }
3241
3242         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
3243         wpabuf_free(resp_tlvs);
3244         return 0;
3245 }
3246
3247
3248 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
3249                                        char *cmd)
3250 {
3251         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
3252                 return -1;
3253         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
3254         return 0;
3255 }
3256
3257
3258 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
3259                                         char *cmd)
3260 {
3261         char *pos;
3262         size_t len;
3263         struct wpabuf *query, *resp;
3264
3265         pos = os_strchr(cmd, ' ');
3266         if (pos == NULL)
3267                 return -1;
3268         *pos++ = '\0';
3269
3270         len = os_strlen(cmd);
3271         if (len & 1)
3272                 return -1;
3273         len /= 2;
3274         query = wpabuf_alloc(len);
3275         if (query == NULL)
3276                 return -1;
3277         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3278                 wpabuf_free(query);
3279                 return -1;
3280         }
3281
3282         len = os_strlen(pos);
3283         if (len & 1) {
3284                 wpabuf_free(query);
3285                 return -1;
3286         }
3287         len /= 2;
3288         resp = wpabuf_alloc(len);
3289         if (resp == NULL) {
3290                 wpabuf_free(query);
3291                 return -1;
3292         }
3293         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
3294                 wpabuf_free(query);
3295                 wpabuf_free(resp);
3296                 return -1;
3297         }
3298
3299         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
3300                 wpabuf_free(query);
3301                 wpabuf_free(resp);
3302                 return -1;
3303         }
3304         return 0;
3305 }
3306
3307
3308 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
3309 {
3310         char *pos;
3311         u8 version;
3312
3313         pos = os_strchr(cmd, ' ');
3314         if (pos == NULL)
3315                 return -1;
3316         *pos++ = '\0';
3317
3318         if (hexstr2bin(cmd, &version, 1) < 0)
3319                 return -1;
3320
3321         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
3322 }
3323
3324
3325 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
3326 {
3327         char *pos;
3328
3329         pos = os_strchr(cmd, ' ');
3330         if (pos == NULL)
3331                 return -1;
3332         *pos++ = '\0';
3333
3334         if (os_strcmp(cmd, "bonjour") == 0)
3335                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
3336         if (os_strcmp(cmd, "upnp") == 0)
3337                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
3338         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
3339         return -1;
3340 }
3341
3342
3343 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
3344                                         char *cmd)
3345 {
3346         size_t len;
3347         struct wpabuf *query;
3348         int ret;
3349
3350         len = os_strlen(cmd);
3351         if (len & 1)
3352                 return -1;
3353         len /= 2;
3354         query = wpabuf_alloc(len);
3355         if (query == NULL)
3356                 return -1;
3357         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
3358                 wpabuf_free(query);
3359                 return -1;
3360         }
3361
3362         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
3363         wpabuf_free(query);
3364         return ret;
3365 }
3366
3367
3368 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
3369 {
3370         char *pos;
3371         u8 version;
3372
3373         pos = os_strchr(cmd, ' ');
3374         if (pos == NULL)
3375                 return -1;
3376         *pos++ = '\0';
3377
3378         if (hexstr2bin(cmd, &version, 1) < 0)
3379                 return -1;
3380
3381         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
3382 }
3383
3384
3385 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
3386 {
3387         char *pos;
3388
3389         pos = os_strchr(cmd, ' ');
3390         if (pos == NULL)
3391                 return -1;
3392         *pos++ = '\0';
3393
3394         if (os_strcmp(cmd, "bonjour") == 0)
3395                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
3396         if (os_strcmp(cmd, "upnp") == 0)
3397                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
3398         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
3399         return -1;
3400 }
3401
3402
3403 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
3404 {
3405         u8 addr[ETH_ALEN];
3406
3407         /* <addr> */
3408
3409         if (hwaddr_aton(cmd, addr))
3410                 return -1;
3411
3412         return wpas_p2p_reject(wpa_s, addr);
3413 }
3414
3415
3416 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
3417 {
3418         char *pos;
3419         int id;
3420         struct wpa_ssid *ssid;
3421         u8 peer[ETH_ALEN];
3422
3423         id = atoi(cmd);
3424         pos = os_strstr(cmd, " peer=");
3425         if (pos) {
3426                 pos += 6;
3427                 if (hwaddr_aton(pos, peer))
3428                         return -1;
3429         }
3430         ssid = wpa_config_get_network(wpa_s->conf, id);
3431         if (ssid == NULL || ssid->disabled != 2) {
3432                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
3433                            "for persistent P2P group",
3434                            id);
3435                 return -1;
3436         }
3437
3438         return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL);
3439 }
3440
3441
3442 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
3443 {
3444         char *pos;
3445         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
3446
3447         pos = os_strstr(cmd, " peer=");
3448         if (!pos)
3449                 return -1;
3450
3451         *pos = '\0';
3452         pos += 6;
3453         if (hwaddr_aton(pos, peer)) {
3454                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
3455                 return -1;
3456         }
3457
3458         pos = os_strstr(pos, " go_dev_addr=");
3459         if (pos) {
3460                 pos += 13;
3461                 if (hwaddr_aton(pos, go_dev_addr)) {
3462                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
3463                                    pos);
3464                         return -1;
3465                 }
3466                 go_dev = go_dev_addr;
3467         }
3468
3469         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
3470 }
3471
3472
3473 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
3474 {
3475         if (os_strncmp(cmd, "persistent=", 11) == 0)
3476                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
3477         if (os_strncmp(cmd, "group=", 6) == 0)
3478                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
3479
3480         return -1;
3481 }
3482
3483
3484 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
3485                                          char *cmd, int freq, int ht40)
3486 {
3487         int id;
3488         struct wpa_ssid *ssid;
3489
3490         id = atoi(cmd);
3491         ssid = wpa_config_get_network(wpa_s->conf, id);
3492         if (ssid == NULL || ssid->disabled != 2) {
3493                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
3494                            "for persistent P2P group",
3495                            id);
3496                 return -1;
3497         }
3498
3499         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40);
3500 }
3501
3502
3503 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
3504 {
3505         int freq = 0, ht40;
3506         char *pos;
3507
3508         pos = os_strstr(cmd, "freq=");
3509         if (pos)
3510                 freq = atoi(pos + 5);
3511
3512         ht40 = os_strstr(cmd, "ht40") != NULL;
3513
3514         if (os_strncmp(cmd, "persistent=", 11) == 0)
3515                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
3516                                                      ht40);
3517         if (os_strcmp(cmd, "persistent") == 0 ||
3518             os_strncmp(cmd, "persistent ", 11) == 0)
3519                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40);
3520         if (os_strncmp(cmd, "freq=", 5) == 0)
3521                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
3522         if (ht40)
3523                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40);
3524
3525         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
3526                    cmd);
3527         return -1;
3528 }
3529
3530
3531 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
3532                          char *buf, size_t buflen)
3533 {
3534         u8 addr[ETH_ALEN], *addr_ptr;
3535         int next, res;
3536         const struct p2p_peer_info *info;
3537         char *pos, *end;
3538         char devtype[WPS_DEV_TYPE_BUFSIZE];
3539         struct wpa_ssid *ssid;
3540
3541         if (!wpa_s->global->p2p)
3542                 return -1;
3543
3544         if (os_strcmp(cmd, "FIRST") == 0) {
3545                 addr_ptr = NULL;
3546                 next = 0;
3547         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3548                 if (hwaddr_aton(cmd + 5, addr) < 0)
3549                         return -1;
3550                 addr_ptr = addr;
3551                 next = 1;
3552         } else {
3553                 if (hwaddr_aton(cmd, addr) < 0)
3554                         return -1;
3555                 addr_ptr = addr;
3556                 next = 0;
3557         }
3558
3559         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
3560         if (info == NULL)
3561                 return -1;
3562
3563         pos = buf;
3564         end = buf + buflen;
3565
3566         res = os_snprintf(pos, end - pos, MACSTR "\n"
3567                           "pri_dev_type=%s\n"
3568                           "device_name=%s\n"
3569                           "manufacturer=%s\n"
3570                           "model_name=%s\n"
3571                           "model_number=%s\n"
3572                           "serial_number=%s\n"
3573                           "config_methods=0x%x\n"
3574                           "dev_capab=0x%x\n"
3575                           "group_capab=0x%x\n"
3576                           "level=%d\n",
3577                           MAC2STR(info->p2p_device_addr),
3578                           wps_dev_type_bin2str(info->pri_dev_type,
3579                                                devtype, sizeof(devtype)),
3580                           info->device_name,
3581                           info->manufacturer,
3582                           info->model_name,
3583                           info->model_number,
3584                           info->serial_number,
3585                           info->config_methods,
3586                           info->dev_capab,
3587                           info->group_capab,
3588                           info->level);
3589         if (res < 0 || res >= end - pos)
3590                 return pos - buf;
3591         pos += res;
3592
3593         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
3594         if (ssid) {
3595                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
3596                 if (res < 0 || res >= end - pos)
3597                         return pos - buf;
3598                 pos += res;
3599         }
3600
3601         res = p2p_get_peer_info_txt(info, pos, end - pos);
3602         if (res < 0)
3603                 return pos - buf;
3604         pos += res;
3605
3606         return pos - buf;
3607 }
3608
3609
3610 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
3611                                   const char *param)
3612 {
3613         struct wpa_freq_range *freq = NULL, *n;
3614         unsigned int count = 0, i;
3615         const char *pos, *pos2, *pos3;
3616
3617         if (wpa_s->global->p2p == NULL)
3618                 return -1;
3619
3620         /*
3621          * param includes comma separated frequency range.
3622          * For example: 2412-2432,2462,5000-6000
3623          */
3624         pos = param;
3625         while (pos && pos[0]) {
3626                 n = os_realloc_array(freq, count + 1,
3627                                      sizeof(struct wpa_freq_range));
3628                 if (n == NULL) {
3629                         os_free(freq);
3630                         return -1;
3631                 }
3632                 freq = n;
3633                 freq[count].min = atoi(pos);
3634                 pos2 = os_strchr(pos, '-');
3635                 pos3 = os_strchr(pos, ',');
3636                 if (pos2 && (!pos3 || pos2 < pos3)) {
3637                         pos2++;
3638                         freq[count].max = atoi(pos2);
3639                 } else
3640                         freq[count].max = freq[count].min;
3641                 pos = pos3;
3642                 if (pos)
3643                         pos++;
3644                 count++;
3645         }
3646
3647         for (i = 0; i < count; i++) {
3648                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
3649                            freq[i].min, freq[i].max);
3650         }
3651
3652         os_free(wpa_s->global->p2p_disallow_freq);
3653         wpa_s->global->p2p_disallow_freq = freq;
3654         wpa_s->global->num_p2p_disallow_freq = count;
3655         wpas_p2p_update_channel_list(wpa_s);
3656         return 0;
3657 }
3658
3659
3660 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
3661 {
3662         char *param;
3663
3664         if (wpa_s->global->p2p == NULL)
3665                 return -1;
3666
3667         param = os_strchr(cmd, ' ');
3668         if (param == NULL)
3669                 return -1;
3670         *param++ = '\0';
3671
3672         if (os_strcmp(cmd, "discoverability") == 0) {
3673                 p2p_set_client_discoverability(wpa_s->global->p2p,
3674                                                atoi(param));
3675                 return 0;
3676         }
3677
3678         if (os_strcmp(cmd, "managed") == 0) {
3679                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
3680                 return 0;
3681         }
3682
3683         if (os_strcmp(cmd, "listen_channel") == 0) {
3684                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
3685                                               atoi(param));
3686         }
3687
3688         if (os_strcmp(cmd, "ssid_postfix") == 0) {
3689                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
3690                                             os_strlen(param));
3691         }
3692
3693         if (os_strcmp(cmd, "noa") == 0) {
3694                 char *pos;
3695                 int count, start, duration;
3696                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
3697                 count = atoi(param);
3698                 pos = os_strchr(param, ',');
3699                 if (pos == NULL)
3700                         return -1;
3701                 pos++;
3702                 start = atoi(pos);
3703                 pos = os_strchr(pos, ',');
3704                 if (pos == NULL)
3705                         return -1;
3706                 pos++;
3707                 duration = atoi(pos);
3708                 if (count < 0 || count > 255 || start < 0 || duration < 0)
3709                         return -1;
3710                 if (count == 0 && duration > 0)
3711                         return -1;
3712                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
3713                            "start=%d duration=%d", count, start, duration);
3714                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
3715         }
3716
3717         if (os_strcmp(cmd, "ps") == 0)
3718                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
3719
3720         if (os_strcmp(cmd, "oppps") == 0)
3721                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
3722
3723         if (os_strcmp(cmd, "ctwindow") == 0)
3724                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
3725
3726         if (os_strcmp(cmd, "disabled") == 0) {
3727                 wpa_s->global->p2p_disabled = atoi(param);
3728                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
3729                            wpa_s->global->p2p_disabled ?
3730                            "disabled" : "enabled");
3731                 if (wpa_s->global->p2p_disabled) {
3732                         wpas_p2p_stop_find(wpa_s);
3733                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
3734                         p2p_flush(wpa_s->global->p2p);
3735                 }
3736                 return 0;
3737         }
3738
3739         if (os_strcmp(cmd, "conc_pref") == 0) {
3740                 if (os_strcmp(param, "sta") == 0)
3741                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
3742                 else if (os_strcmp(param, "p2p") == 0)
3743                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
3744                 else {
3745                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
3746                         return -1;
3747                 }
3748                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
3749                            "%s", param);
3750                 return 0;
3751         }
3752
3753         if (os_strcmp(cmd, "force_long_sd") == 0) {
3754                 wpa_s->force_long_sd = atoi(param);
3755                 return 0;
3756         }
3757
3758         if (os_strcmp(cmd, "peer_filter") == 0) {
3759                 u8 addr[ETH_ALEN];
3760                 if (hwaddr_aton(param, addr))
3761                         return -1;
3762                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
3763                 return 0;
3764         }
3765
3766         if (os_strcmp(cmd, "cross_connect") == 0)
3767                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
3768
3769         if (os_strcmp(cmd, "go_apsd") == 0) {
3770                 if (os_strcmp(param, "disable") == 0)
3771                         wpa_s->set_ap_uapsd = 0;
3772                 else {
3773                         wpa_s->set_ap_uapsd = 1;
3774                         wpa_s->ap_uapsd = atoi(param);
3775                 }
3776                 return 0;
3777         }
3778
3779         if (os_strcmp(cmd, "client_apsd") == 0) {
3780                 if (os_strcmp(param, "disable") == 0)
3781                         wpa_s->set_sta_uapsd = 0;
3782                 else {
3783                         int be, bk, vi, vo;
3784                         char *pos;
3785                         /* format: BE,BK,VI,VO;max SP Length */
3786                         be = atoi(param);
3787                         pos = os_strchr(param, ',');
3788                         if (pos == NULL)
3789                                 return -1;
3790                         pos++;
3791                         bk = atoi(pos);
3792                         pos = os_strchr(pos, ',');
3793                         if (pos == NULL)
3794                                 return -1;
3795                         pos++;
3796                         vi = atoi(pos);
3797                         pos = os_strchr(pos, ',');
3798                         if (pos == NULL)
3799                                 return -1;
3800                         pos++;
3801                         vo = atoi(pos);
3802                         /* ignore max SP Length for now */
3803
3804                         wpa_s->set_sta_uapsd = 1;
3805                         wpa_s->sta_uapsd = 0;
3806                         if (be)
3807                                 wpa_s->sta_uapsd |= BIT(0);
3808                         if (bk)
3809                                 wpa_s->sta_uapsd |= BIT(1);
3810                         if (vi)
3811                                 wpa_s->sta_uapsd |= BIT(2);
3812                         if (vo)
3813                                 wpa_s->sta_uapsd |= BIT(3);
3814                 }
3815                 return 0;
3816         }
3817
3818         if (os_strcmp(cmd, "disallow_freq") == 0)
3819                 return p2p_ctrl_disallow_freq(wpa_s, param);
3820
3821         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
3822                    cmd);
3823
3824         return -1;
3825 }
3826
3827
3828 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
3829 {
3830         char *pos, *pos2;
3831         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
3832
3833         if (cmd[0]) {
3834                 pos = os_strchr(cmd, ' ');
3835                 if (pos == NULL)
3836                         return -1;
3837                 *pos++ = '\0';
3838                 dur1 = atoi(cmd);
3839
3840                 pos2 = os_strchr(pos, ' ');
3841                 if (pos2)
3842                         *pos2++ = '\0';
3843                 int1 = atoi(pos);
3844         } else
3845                 pos2 = NULL;
3846
3847         if (pos2) {
3848                 pos = os_strchr(pos2, ' ');
3849                 if (pos == NULL)
3850                         return -1;
3851                 *pos++ = '\0';
3852                 dur2 = atoi(pos2);
3853                 int2 = atoi(pos);
3854         }
3855
3856         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
3857 }
3858
3859
3860 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
3861 {
3862         char *pos;
3863         unsigned int period = 0, interval = 0;
3864
3865         if (cmd[0]) {
3866                 pos = os_strchr(cmd, ' ');
3867                 if (pos == NULL)
3868                         return -1;
3869                 *pos++ = '\0';
3870                 period = atoi(cmd);
3871                 interval = atoi(pos);
3872         }
3873
3874         return wpas_p2p_ext_listen(wpa_s, period, interval);
3875 }
3876
3877 #endif /* CONFIG_P2P */
3878
3879
3880 #ifdef CONFIG_INTERWORKING
3881 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
3882 {
3883         u8 bssid[ETH_ALEN];
3884         struct wpa_bss *bss;
3885
3886         if (hwaddr_aton(dst, bssid)) {
3887                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
3888                 return -1;
3889         }
3890
3891         bss = wpa_bss_get_bssid(wpa_s, bssid);
3892         if (bss == NULL) {
3893                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
3894                            MAC2STR(bssid));
3895                 return -1;
3896         }
3897
3898         return interworking_connect(wpa_s, bss);
3899 }
3900
3901
3902 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
3903 {
3904         u8 dst_addr[ETH_ALEN];
3905         int used;
3906         char *pos;
3907 #define MAX_ANQP_INFO_ID 100
3908         u16 id[MAX_ANQP_INFO_ID];
3909         size_t num_id = 0;
3910
3911         used = hwaddr_aton2(dst, dst_addr);
3912         if (used < 0)
3913                 return -1;
3914         pos = dst + used;
3915         while (num_id < MAX_ANQP_INFO_ID) {
3916                 id[num_id] = atoi(pos);
3917                 if (id[num_id])
3918                         num_id++;
3919                 pos = os_strchr(pos + 1, ',');
3920                 if (pos == NULL)
3921                         break;
3922                 pos++;
3923         }
3924
3925         if (num_id == 0)
3926                 return -1;
3927
3928         return anqp_send_req(wpa_s, dst_addr, id, num_id);
3929 }
3930 #endif /* CONFIG_INTERWORKING */
3931
3932
3933 #ifdef CONFIG_HS20
3934
3935 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
3936 {
3937         u8 dst_addr[ETH_ALEN];
3938         int used;
3939         char *pos;
3940         u32 subtypes = 0;
3941
3942         used = hwaddr_aton2(dst, dst_addr);
3943         if (used < 0)
3944                 return -1;
3945         pos = dst + used;
3946         for (;;) {
3947                 int num = atoi(pos);
3948                 if (num <= 0 || num > 31)
3949                         return -1;
3950                 subtypes |= BIT(num);
3951                 pos = os_strchr(pos + 1, ',');
3952                 if (pos == NULL)
3953                         break;
3954                 pos++;
3955         }
3956
3957         if (subtypes == 0)
3958                 return -1;
3959
3960         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
3961 }
3962
3963
3964 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
3965                                     const u8 *addr, const char *realm)
3966 {
3967         u8 *buf;
3968         size_t rlen, len;
3969         int ret;
3970
3971         rlen = os_strlen(realm);
3972         len = 3 + rlen;
3973         buf = os_malloc(len);
3974         if (buf == NULL)
3975                 return -1;
3976         buf[0] = 1; /* NAI Home Realm Count */
3977         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
3978         buf[2] = rlen;
3979         os_memcpy(buf + 3, realm, rlen);
3980
3981         ret = hs20_anqp_send_req(wpa_s, addr,
3982                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
3983                                  buf, len);
3984
3985         os_free(buf);
3986
3987         return ret;
3988 }
3989
3990
3991 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
3992                                         char *dst)
3993 {
3994         struct wpa_cred *cred = wpa_s->conf->cred;
3995         u8 dst_addr[ETH_ALEN];
3996         int used;
3997         u8 *buf;
3998         size_t len;
3999         int ret;
4000
4001         used = hwaddr_aton2(dst, dst_addr);
4002         if (used < 0)
4003                 return -1;
4004
4005         while (dst[used] == ' ')
4006                 used++;
4007         if (os_strncmp(dst + used, "realm=", 6) == 0)
4008                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
4009                                                 dst + used + 6);
4010
4011         len = os_strlen(dst + used);
4012
4013         if (len == 0 && cred && cred->realm)
4014                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
4015
4016         if (len % 1)
4017                 return -1;
4018         len /= 2;
4019         buf = os_malloc(len);
4020         if (buf == NULL)
4021                 return -1;
4022         if (hexstr2bin(dst + used, buf, len) < 0) {
4023                 os_free(buf);
4024                 return -1;
4025         }
4026
4027         ret = hs20_anqp_send_req(wpa_s, dst_addr,
4028                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
4029                                  buf, len);
4030         os_free(buf);
4031
4032         return ret;
4033 }
4034
4035 #endif /* CONFIG_HS20 */
4036
4037
4038 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
4039         struct wpa_supplicant *wpa_s, char *cmd)
4040 {
4041         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
4042         return 0;
4043 }
4044
4045
4046 #ifdef CONFIG_AUTOSCAN
4047
4048 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
4049                                               char *cmd)
4050 {
4051         enum wpa_states state = wpa_s->wpa_state;
4052         char *new_params = NULL;
4053
4054         if (os_strlen(cmd) > 0) {
4055                 new_params = os_strdup(cmd);
4056                 if (new_params == NULL)
4057                         return -1;
4058         }
4059
4060         os_free(wpa_s->conf->autoscan);
4061         wpa_s->conf->autoscan = new_params;
4062
4063         if (wpa_s->conf->autoscan == NULL)
4064                 autoscan_deinit(wpa_s);
4065         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
4066                 autoscan_init(wpa_s, 1);
4067         else if (state == WPA_SCANNING)
4068                 wpa_supplicant_reinit_autoscan(wpa_s);
4069
4070         return 0;
4071 }
4072
4073 #endif /* CONFIG_AUTOSCAN */
4074
4075
4076 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
4077                                       size_t buflen)
4078 {
4079         struct wpa_signal_info si;
4080         int ret;
4081
4082         ret = wpa_drv_signal_poll(wpa_s, &si);
4083         if (ret)
4084                 return -1;
4085
4086         ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n"
4087                           "NOISE=%d\nFREQUENCY=%u\n",
4088                           si.current_signal, si.current_txrate / 1000,
4089                           si.current_noise, si.frequency);
4090         if (ret < 0 || (unsigned int) ret > buflen)
4091                 return -1;
4092         return ret;
4093 }
4094
4095
4096 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
4097                                          char *buf, size_t *resp_len)
4098 {
4099         char *reply;
4100         const int reply_size = 4096;
4101         int ctrl_rsp = 0;
4102         int reply_len;
4103
4104         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
4105             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
4106                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
4107                                       (const u8 *) buf, os_strlen(buf));
4108         } else {
4109                 int level = MSG_DEBUG;
4110                 if (os_strcmp(buf, "PING") == 0)
4111                         level = MSG_EXCESSIVE;
4112                 wpa_hexdump_ascii(level, "RX ctrl_iface",
4113                                   (const u8 *) buf, os_strlen(buf));
4114         }
4115
4116         reply = os_malloc(reply_size);
4117         if (reply == NULL) {
4118                 *resp_len = 1;
4119                 return NULL;
4120         }
4121
4122         os_memcpy(reply, "OK\n", 3);
4123         reply_len = 3;
4124
4125         if (os_strcmp(buf, "PING") == 0) {
4126                 os_memcpy(reply, "PONG\n", 5);
4127                 reply_len = 5;
4128         } else if (os_strcmp(buf, "IFNAME") == 0) {
4129                 reply_len = os_strlen(wpa_s->ifname);
4130                 os_memcpy(reply, wpa_s->ifname, reply_len);
4131         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
4132                 if (wpa_debug_reopen_file() < 0)
4133                         reply_len = -1;
4134         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
4135                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
4136         } else if (os_strcmp(buf, "MIB") == 0) {
4137                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
4138                 if (reply_len >= 0) {
4139                         int res;
4140                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
4141                                                reply_size - reply_len);
4142                         if (res < 0)
4143                                 reply_len = -1;
4144                         else
4145                                 reply_len += res;
4146                 }
4147         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
4148                 reply_len = wpa_supplicant_ctrl_iface_status(
4149                         wpa_s, buf + 6, reply, reply_size);
4150         } else if (os_strcmp(buf, "PMKSA") == 0) {
4151                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
4152                                                     reply_size);
4153         } else if (os_strncmp(buf, "SET ", 4) == 0) {
4154                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
4155                         reply_len = -1;
4156         } else if (os_strncmp(buf, "GET ", 4) == 0) {
4157                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
4158                                                           reply, reply_size);
4159         } else if (os_strcmp(buf, "LOGON") == 0) {
4160                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
4161         } else if (os_strcmp(buf, "LOGOFF") == 0) {
4162                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
4163         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
4164                 wpa_s->normal_scans = 0;
4165                 wpa_supplicant_reinit_autoscan(wpa_s);
4166                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
4167                         reply_len = -1;
4168                 else {
4169                         wpa_s->disconnected = 0;
4170                         wpa_s->reassociate = 1;
4171                         wpa_supplicant_req_scan(wpa_s, 0, 0);
4172                 }
4173         } else if (os_strcmp(buf, "RECONNECT") == 0) {
4174                 wpa_s->normal_scans = 0;
4175                 wpa_supplicant_reinit_autoscan(wpa_s);
4176                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
4177                         reply_len = -1;
4178                 else if (wpa_s->disconnected) {
4179                         wpa_s->disconnected = 0;
4180                         wpa_s->reassociate = 1;
4181                         wpa_supplicant_req_scan(wpa_s, 0, 0);
4182                 }
4183 #ifdef IEEE8021X_EAPOL
4184         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
4185                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
4186                         reply_len = -1;
4187 #endif /* IEEE8021X_EAPOL */
4188 #ifdef CONFIG_PEERKEY
4189         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
4190                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
4191                         reply_len = -1;
4192 #endif /* CONFIG_PEERKEY */
4193 #ifdef CONFIG_IEEE80211R
4194         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
4195                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
4196                         reply_len = -1;
4197 #endif /* CONFIG_IEEE80211R */
4198 #ifdef CONFIG_WPS
4199         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
4200                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
4201                 if (res == -2) {
4202                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
4203                         reply_len = 17;
4204                 } else if (res)
4205                         reply_len = -1;
4206         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
4207                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
4208                 if (res == -2) {
4209                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
4210                         reply_len = 17;
4211                 } else if (res)
4212                         reply_len = -1;
4213         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
4214                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
4215                                                               reply,
4216                                                               reply_size);
4217         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
4218                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
4219                         wpa_s, buf + 14, reply, reply_size);
4220         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
4221                 if (wpas_wps_cancel(wpa_s))
4222                         reply_len = -1;
4223 #ifdef CONFIG_WPS_OOB
4224         } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
4225                 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
4226                         reply_len = -1;
4227 #endif /* CONFIG_WPS_OOB */
4228 #ifdef CONFIG_WPS_NFC
4229         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
4230                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
4231                         reply_len = -1;
4232         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
4233                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
4234                         reply_len = -1;
4235         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
4236                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
4237                         wpa_s, buf + 14, reply, reply_size);
4238         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
4239                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
4240                                                                buf + 17))
4241                         reply_len = -1;
4242 #endif /* CONFIG_WPS_NFC */
4243         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
4244                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
4245                         reply_len = -1;
4246 #ifdef CONFIG_AP
4247         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
4248                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
4249                         wpa_s, buf + 11, reply, reply_size);
4250 #endif /* CONFIG_AP */
4251 #ifdef CONFIG_WPS_ER
4252         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
4253                 if (wpas_wps_er_start(wpa_s, NULL))
4254                         reply_len = -1;
4255         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
4256                 if (wpas_wps_er_start(wpa_s, buf + 13))
4257                         reply_len = -1;
4258         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
4259                 if (wpas_wps_er_stop(wpa_s))
4260                         reply_len = -1;
4261         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
4262                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
4263                         reply_len = -1;
4264         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
4265                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
4266                 if (ret == -2) {
4267                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
4268                         reply_len = 17;
4269                 } else if (ret == -3) {
4270                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
4271                         reply_len = 18;
4272                 } else if (ret == -4) {
4273                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
4274                         reply_len = 20;
4275                 } else if (ret)
4276                         reply_len = -1;
4277         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
4278                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
4279                         reply_len = -1;
4280         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
4281                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
4282                                                                 buf + 18))
4283                         reply_len = -1;
4284         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
4285                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
4286                         reply_len = -1;
4287 #ifdef CONFIG_WPS_NFC
4288         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
4289                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
4290                         wpa_s, buf + 24, reply, reply_size);
4291 #endif /* CONFIG_WPS_NFC */
4292 #endif /* CONFIG_WPS_ER */
4293 #endif /* CONFIG_WPS */
4294 #ifdef CONFIG_IBSS_RSN
4295         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
4296                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
4297                         reply_len = -1;
4298 #endif /* CONFIG_IBSS_RSN */
4299 #ifdef CONFIG_P2P
4300         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
4301                 if (p2p_ctrl_find(wpa_s, buf + 9))
4302                         reply_len = -1;
4303         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
4304                 if (p2p_ctrl_find(wpa_s, ""))
4305                         reply_len = -1;
4306         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
4307                 wpas_p2p_stop_find(wpa_s);
4308         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
4309                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
4310                                              reply_size);
4311         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
4312                 if (p2p_ctrl_listen(wpa_s, buf + 11))
4313                         reply_len = -1;
4314         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
4315                 if (p2p_ctrl_listen(wpa_s, ""))
4316                         reply_len = -1;
4317         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
4318                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
4319                         reply_len = -1;
4320         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
4321                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0))
4322                         reply_len = -1;
4323         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
4324                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
4325                         reply_len = -1;
4326         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
4327                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
4328                         reply_len = -1;
4329         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
4330                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
4331         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
4332                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
4333                                                    reply_size);
4334         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
4335                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
4336                         reply_len = -1;
4337         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
4338                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
4339                         reply_len = -1;
4340         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
4341                 wpas_p2p_sd_service_update(wpa_s);
4342         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
4343                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
4344                         reply_len = -1;
4345         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
4346                 wpas_p2p_service_flush(wpa_s);
4347         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
4348                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
4349                         reply_len = -1;
4350         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
4351                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
4352                         reply_len = -1;
4353         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
4354                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
4355                         reply_len = -1;
4356         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
4357                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
4358                         reply_len = -1;
4359         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
4360                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
4361                                               reply_size);
4362         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
4363                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
4364                         reply_len = -1;
4365         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
4366                 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4367                 wpa_s->force_long_sd = 0;
4368                 if (wpa_s->global->p2p)
4369                         p2p_flush(wpa_s->global->p2p);
4370         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
4371                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
4372                         reply_len = -1;
4373         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
4374                 if (wpas_p2p_cancel(wpa_s))
4375                         reply_len = -1;
4376         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
4377                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
4378                         reply_len = -1;
4379         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
4380                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
4381                         reply_len = -1;
4382         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
4383                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
4384                         reply_len = -1;
4385         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
4386                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
4387                         reply_len = -1;
4388 #endif /* CONFIG_P2P */
4389 #ifdef CONFIG_INTERWORKING
4390         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
4391                 if (interworking_fetch_anqp(wpa_s) < 0)
4392                         reply_len = -1;
4393         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
4394                 interworking_stop_fetch_anqp(wpa_s);
4395         } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
4396                 if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
4397                                         NULL) < 0)
4398                         reply_len = -1;
4399         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
4400                 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
4401                         reply_len = -1;
4402         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
4403                 if (get_anqp(wpa_s, buf + 9) < 0)
4404                         reply_len = -1;
4405 #endif /* CONFIG_INTERWORKING */
4406 #ifdef CONFIG_HS20
4407         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
4408                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
4409                         reply_len = -1;
4410         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
4411                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
4412                         reply_len = -1;
4413 #endif /* CONFIG_HS20 */
4414         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
4415         {
4416                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
4417                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
4418                         reply_len = -1;
4419                 else
4420                         ctrl_rsp = 1;
4421         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
4422                 if (wpa_supplicant_reload_configuration(wpa_s))
4423                         reply_len = -1;
4424         } else if (os_strcmp(buf, "TERMINATE") == 0) {
4425                 wpa_supplicant_terminate_proc(wpa_s->global);
4426         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
4427                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
4428                         reply_len = -1;
4429         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
4430                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
4431                         wpa_s, buf + 9, reply, reply_size);
4432         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
4433                 reply_len = wpa_supplicant_ctrl_iface_log_level(
4434                         wpa_s, buf + 9, reply, reply_size);
4435         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
4436                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
4437                         wpa_s, reply, reply_size);
4438         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
4439 #ifdef CONFIG_SME
4440                 wpa_s->sme.prev_bssid_set = 0;
4441 #endif /* CONFIG_SME */
4442                 wpa_s->reassociate = 0;
4443                 wpa_s->disconnected = 1;
4444                 wpa_supplicant_cancel_sched_scan(wpa_s);
4445                 wpa_supplicant_cancel_scan(wpa_s);
4446                 wpa_supplicant_deauthenticate(wpa_s,
4447                                               WLAN_REASON_DEAUTH_LEAVING);
4448         } else if (os_strcmp(buf, "SCAN") == 0) {
4449                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
4450                         reply_len = -1;
4451                 else {
4452                         if (!wpa_s->scanning &&
4453                             ((wpa_s->wpa_state <= WPA_SCANNING) ||
4454                              (wpa_s->wpa_state == WPA_COMPLETED))) {
4455                                 wpa_s->normal_scans = 0;
4456                                 wpa_s->scan_req = 2;
4457                                 wpa_supplicant_req_scan(wpa_s, 0, 0);
4458                         } else if (wpa_s->sched_scanning) {
4459                                 wpa_printf(MSG_DEBUG, "Stop ongoing "
4460                                            "sched_scan to allow requested "
4461                                            "full scan to proceed");
4462                                 wpa_supplicant_cancel_sched_scan(wpa_s);
4463                                 wpa_s->scan_req = 2;
4464                                 wpa_supplicant_req_scan(wpa_s, 0, 0);
4465                         } else {
4466                                 wpa_printf(MSG_DEBUG, "Ongoing scan action - "
4467                                            "reject new request");
4468                                 reply_len = os_snprintf(reply, reply_size,
4469                                                         "FAIL-BUSY\n");
4470                         }
4471                 }
4472         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
4473                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
4474                         wpa_s, reply, reply_size);
4475         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
4476                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
4477                         reply_len = -1;
4478         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
4479                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
4480                         reply_len = -1;
4481         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
4482                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
4483                         reply_len = -1;
4484         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
4485                 reply_len = wpa_supplicant_ctrl_iface_add_network(
4486                         wpa_s, reply, reply_size);
4487         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
4488                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
4489                         reply_len = -1;
4490         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
4491                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
4492                         reply_len = -1;
4493         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
4494                 reply_len = wpa_supplicant_ctrl_iface_get_network(
4495                         wpa_s, buf + 12, reply, reply_size);
4496         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
4497                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
4498                         wpa_s, reply, reply_size);
4499         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
4500                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
4501                         wpa_s, reply, reply_size);
4502         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
4503                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
4504                         reply_len = -1;
4505         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
4506                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
4507                         reply_len = -1;
4508 #ifndef CONFIG_NO_CONFIG_WRITE
4509         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
4510                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
4511                         reply_len = -1;
4512 #endif /* CONFIG_NO_CONFIG_WRITE */
4513         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
4514                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
4515                         wpa_s, buf + 15, reply, reply_size);
4516         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
4517                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
4518                         reply_len = -1;
4519         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
4520                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
4521                         reply_len = -1;
4522         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
4523                 reply_len = wpa_supplicant_global_iface_list(
4524                         wpa_s->global, reply, reply_size);
4525         } else if (os_strcmp(buf, "INTERFACES") == 0) {
4526                 reply_len = wpa_supplicant_global_iface_interfaces(
4527                         wpa_s->global, reply, reply_size);
4528         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
4529                 reply_len = wpa_supplicant_ctrl_iface_bss(
4530                         wpa_s, buf + 4, reply, reply_size);
4531 #ifdef CONFIG_AP
4532         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
4533                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
4534         } else if (os_strncmp(buf, "STA ", 4) == 0) {
4535                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
4536                                               reply_size);
4537         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
4538                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
4539                                                    reply_size);
4540         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
4541                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
4542                         reply_len = -1;
4543         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
4544                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
4545                         reply_len = -1;
4546 #endif /* CONFIG_AP */
4547         } else if (os_strcmp(buf, "SUSPEND") == 0) {
4548                 wpas_notify_suspend(wpa_s->global);
4549         } else if (os_strcmp(buf, "RESUME") == 0) {
4550                 wpas_notify_resume(wpa_s->global);
4551         } else if (os_strcmp(buf, "DROP_SA") == 0) {
4552                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
4553         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
4554                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
4555                         reply_len = -1;
4556         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
4557                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
4558                         reply_len = -1;
4559         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
4560                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
4561                         reply_len = -1;
4562         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
4563                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
4564                                                                buf + 17))
4565                         reply_len = -1;
4566 #ifdef CONFIG_TDLS
4567         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
4568                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
4569                         reply_len = -1;
4570         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
4571                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
4572                         reply_len = -1;
4573         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
4574                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
4575                         reply_len = -1;
4576 #endif /* CONFIG_TDLS */
4577         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
4578                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
4579                                                        reply_size);
4580 #ifdef CONFIG_AUTOSCAN
4581         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
4582                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
4583                         reply_len = -1;
4584 #endif /* CONFIG_AUTOSCAN */
4585         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
4586                 eapol_sm_request_reauth(wpa_s->eapol);
4587         } else {
4588                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
4589                 reply_len = 16;
4590         }
4591
4592         if (reply_len < 0) {
4593                 os_memcpy(reply, "FAIL\n", 5);
4594                 reply_len = 5;
4595         }
4596
4597         if (ctrl_rsp)
4598                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
4599
4600         *resp_len = reply_len;
4601         return reply;
4602 }
4603
4604
4605 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
4606                                            char *cmd)
4607 {
4608         struct wpa_interface iface;
4609         char *pos;
4610
4611         /*
4612          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
4613          * TAB<bridge_ifname>
4614          */
4615         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
4616
4617         os_memset(&iface, 0, sizeof(iface));
4618
4619         do {
4620                 iface.ifname = pos = cmd;
4621                 pos = os_strchr(pos, '\t');
4622                 if (pos)
4623                         *pos++ = '\0';
4624                 if (iface.ifname[0] == '\0')
4625                         return -1;
4626                 if (pos == NULL)
4627                         break;
4628
4629                 iface.confname = pos;
4630                 pos = os_strchr(pos, '\t');
4631                 if (pos)
4632                         *pos++ = '\0';
4633                 if (iface.confname[0] == '\0')
4634                         iface.confname = NULL;
4635                 if (pos == NULL)
4636                         break;
4637
4638                 iface.driver = pos;
4639                 pos = os_strchr(pos, '\t');
4640                 if (pos)
4641                         *pos++ = '\0';
4642                 if (iface.driver[0] == '\0')
4643                         iface.driver = NULL;
4644                 if (pos == NULL)
4645                         break;
4646
4647                 iface.ctrl_interface = pos;
4648                 pos = os_strchr(pos, '\t');
4649                 if (pos)
4650                         *pos++ = '\0';
4651                 if (iface.ctrl_interface[0] == '\0')
4652                         iface.ctrl_interface = NULL;
4653                 if (pos == NULL)
4654                         break;
4655
4656                 iface.driver_param = pos;
4657                 pos = os_strchr(pos, '\t');
4658                 if (pos)
4659                         *pos++ = '\0';
4660                 if (iface.driver_param[0] == '\0')
4661                         iface.driver_param = NULL;
4662                 if (pos == NULL)
4663                         break;
4664
4665                 iface.bridge_ifname = pos;
4666                 pos = os_strchr(pos, '\t');
4667                 if (pos)
4668                         *pos++ = '\0';
4669                 if (iface.bridge_ifname[0] == '\0')
4670                         iface.bridge_ifname = NULL;
4671                 if (pos == NULL)
4672                         break;
4673         } while (0);
4674
4675         if (wpa_supplicant_get_iface(global, iface.ifname))
4676                 return -1;
4677
4678         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
4679 }
4680
4681
4682 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
4683                                               char *cmd)
4684 {
4685         struct wpa_supplicant *wpa_s;
4686
4687         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
4688
4689         wpa_s = wpa_supplicant_get_iface(global, cmd);
4690         if (wpa_s == NULL)
4691                 return -1;
4692         return wpa_supplicant_remove_iface(global, wpa_s, 0);
4693 }
4694
4695
4696 static void wpa_free_iface_info(struct wpa_interface_info *iface)
4697 {
4698         struct wpa_interface_info *prev;
4699
4700         while (iface) {
4701                 prev = iface;
4702                 iface = iface->next;
4703
4704                 os_free(prev->ifname);
4705                 os_free(prev->desc);
4706                 os_free(prev);
4707         }
4708 }
4709
4710
4711 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
4712                                             char *buf, int len)
4713 {
4714         int i, res;
4715         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
4716         char *pos, *end;
4717
4718         for (i = 0; wpa_drivers[i]; i++) {
4719                 struct wpa_driver_ops *drv = wpa_drivers[i];
4720                 if (drv->get_interfaces == NULL)
4721                         continue;
4722                 tmp = drv->get_interfaces(global->drv_priv[i]);
4723                 if (tmp == NULL)
4724                         continue;
4725
4726                 if (last == NULL)
4727                         iface = last = tmp;
4728                 else
4729                         last->next = tmp;
4730                 while (last->next)
4731                         last = last->next;
4732         }
4733
4734         pos = buf;
4735         end = buf + len;
4736         for (tmp = iface; tmp; tmp = tmp->next) {
4737                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
4738                                   tmp->drv_name, tmp->ifname,
4739                                   tmp->desc ? tmp->desc : "");
4740                 if (res < 0 || res >= end - pos) {
4741                         *pos = '\0';
4742                         break;
4743                 }
4744                 pos += res;
4745         }
4746
4747         wpa_free_iface_info(iface);
4748
4749         return pos - buf;
4750 }
4751
4752
4753 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
4754                                                   char *buf, int len)
4755 {
4756         int res;
4757         char *pos, *end;
4758         struct wpa_supplicant *wpa_s;
4759
4760         wpa_s = global->ifaces;
4761         pos = buf;
4762         end = buf + len;
4763
4764         while (wpa_s) {
4765                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
4766                 if (res < 0 || res >= end - pos) {
4767                         *pos = '\0';
4768                         break;
4769                 }
4770                 pos += res;
4771                 wpa_s = wpa_s->next;
4772         }
4773         return pos - buf;
4774 }
4775
4776
4777 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
4778                                                 char *buf, size_t *resp_len)
4779 {
4780         char *reply;
4781         const int reply_size = 2048;
4782         int reply_len;
4783         int level = MSG_DEBUG;
4784
4785         if (os_strcmp(buf, "PING") == 0)
4786                 level = MSG_EXCESSIVE;
4787         wpa_hexdump_ascii(level, "RX global ctrl_iface",
4788                           (const u8 *) buf, os_strlen(buf));
4789
4790         reply = os_malloc(reply_size);
4791         if (reply == NULL) {
4792                 *resp_len = 1;
4793                 return NULL;
4794         }
4795
4796         os_memcpy(reply, "OK\n", 3);
4797         reply_len = 3;
4798
4799         if (os_strcmp(buf, "PING") == 0) {
4800                 os_memcpy(reply, "PONG\n", 5);
4801                 reply_len = 5;
4802         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
4803                 if (wpa_supplicant_global_iface_add(global, buf + 14))
4804                         reply_len = -1;
4805         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
4806                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
4807                         reply_len = -1;
4808         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
4809                 reply_len = wpa_supplicant_global_iface_list(
4810                         global, reply, reply_size);
4811         } else if (os_strcmp(buf, "INTERFACES") == 0) {
4812                 reply_len = wpa_supplicant_global_iface_interfaces(
4813                         global, reply, reply_size);
4814         } else if (os_strcmp(buf, "TERMINATE") == 0) {
4815                 wpa_supplicant_terminate_proc(global);
4816         } else if (os_strcmp(buf, "SUSPEND") == 0) {
4817                 wpas_notify_suspend(global);
4818         } else if (os_strcmp(buf, "RESUME") == 0) {
4819                 wpas_notify_resume(global);
4820         } else {
4821                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
4822                 reply_len = 16;
4823         }
4824
4825         if (reply_len < 0) {
4826                 os_memcpy(reply, "FAIL\n", 5);
4827                 reply_len = 5;
4828         }
4829
4830         *resp_len = reply_len;
4831         return reply;
4832 }