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