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