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