Move DROP_SA command to be within ifdef CONFIG_TESTING_OPTIONS
[mech_eap.git] / wpa_supplicant / ctrl_iface.c
1 /*
2  * WPA Supplicant / Control interface (shared code for all backends)
3  * Copyright (c) 2004-2014, 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 "utils/uuid.h"
14 #include "common/version.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/ieee802_11_common.h"
17 #include "common/wpa_ctrl.h"
18 #include "eap_peer/eap.h"
19 #include "eapol_supp/eapol_supp_sm.h"
20 #include "rsn_supp/wpa.h"
21 #include "rsn_supp/preauth.h"
22 #include "rsn_supp/pmksa_cache.h"
23 #include "l2_packet/l2_packet.h"
24 #include "wps/wps.h"
25 #include "config.h"
26 #include "wpa_supplicant_i.h"
27 #include "driver_i.h"
28 #include "wps_supplicant.h"
29 #include "ibss_rsn.h"
30 #include "ap.h"
31 #include "p2p_supplicant.h"
32 #include "p2p/p2p.h"
33 #include "hs20_supplicant.h"
34 #include "wifi_display.h"
35 #include "notify.h"
36 #include "bss.h"
37 #include "scan.h"
38 #include "ctrl_iface.h"
39 #include "interworking.h"
40 #include "blacklist.h"
41 #include "autoscan.h"
42 #include "wnm_sta.h"
43 #include "offchannel.h"
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 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
50                                         char *val);
51
52 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
53 {
54         char *pos;
55         u8 addr[ETH_ALEN], *filter = NULL, *n;
56         size_t count = 0;
57
58         pos = val;
59         while (pos) {
60                 if (*pos == '\0')
61                         break;
62                 if (hwaddr_aton(pos, addr)) {
63                         os_free(filter);
64                         return -1;
65                 }
66                 n = os_realloc_array(filter, count + 1, ETH_ALEN);
67                 if (n == NULL) {
68                         os_free(filter);
69                         return -1;
70                 }
71                 filter = n;
72                 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
73                 count++;
74
75                 pos = os_strchr(pos, ' ');
76                 if (pos)
77                         pos++;
78         }
79
80         wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
81         os_free(wpa_s->bssid_filter);
82         wpa_s->bssid_filter = filter;
83         wpa_s->bssid_filter_count = count;
84
85         return 0;
86 }
87
88
89 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
90 {
91         char *pos;
92         u8 addr[ETH_ALEN], *bssid = NULL, *n;
93         struct wpa_ssid_value *ssid = NULL, *ns;
94         size_t count = 0, ssid_count = 0;
95         struct wpa_ssid *c;
96
97         /*
98          * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | ""
99          * SSID_SPEC ::= ssid <SSID_HEX>
100          * BSSID_SPEC ::= bssid <BSSID_HEX>
101          */
102
103         pos = val;
104         while (pos) {
105                 if (*pos == '\0')
106                         break;
107                 if (os_strncmp(pos, "bssid ", 6) == 0) {
108                         int res;
109                         pos += 6;
110                         res = hwaddr_aton2(pos, addr);
111                         if (res < 0) {
112                                 os_free(ssid);
113                                 os_free(bssid);
114                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
115                                            "BSSID value '%s'", pos);
116                                 return -1;
117                         }
118                         pos += res;
119                         n = os_realloc_array(bssid, count + 1, ETH_ALEN);
120                         if (n == NULL) {
121                                 os_free(ssid);
122                                 os_free(bssid);
123                                 return -1;
124                         }
125                         bssid = n;
126                         os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
127                         count++;
128                 } else if (os_strncmp(pos, "ssid ", 5) == 0) {
129                         char *end;
130                         pos += 5;
131
132                         end = pos;
133                         while (*end) {
134                                 if (*end == '\0' || *end == ' ')
135                                         break;
136                                 end++;
137                         }
138
139                         ns = os_realloc_array(ssid, ssid_count + 1,
140                                               sizeof(struct wpa_ssid_value));
141                         if (ns == NULL) {
142                                 os_free(ssid);
143                                 os_free(bssid);
144                                 return -1;
145                         }
146                         ssid = ns;
147
148                         if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
149                             hexstr2bin(pos, ssid[ssid_count].ssid,
150                                        (end - pos) / 2) < 0) {
151                                 os_free(ssid);
152                                 os_free(bssid);
153                                 wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
154                                            "SSID value '%s'", pos);
155                                 return -1;
156                         }
157                         ssid[ssid_count].ssid_len = (end - pos) / 2;
158                         wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
159                                           ssid[ssid_count].ssid,
160                                           ssid[ssid_count].ssid_len);
161                         ssid_count++;
162                         pos = end;
163                 } else {
164                         wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
165                                    "'%s'", pos);
166                         os_free(ssid);
167                         os_free(bssid);
168                         return -1;
169                 }
170
171                 pos = os_strchr(pos, ' ');
172                 if (pos)
173                         pos++;
174         }
175
176         wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
177         os_free(wpa_s->disallow_aps_bssid);
178         wpa_s->disallow_aps_bssid = bssid;
179         wpa_s->disallow_aps_bssid_count = count;
180
181         wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
182         os_free(wpa_s->disallow_aps_ssid);
183         wpa_s->disallow_aps_ssid = ssid;
184         wpa_s->disallow_aps_ssid_count = ssid_count;
185
186         if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
187                 return 0;
188
189         c = wpa_s->current_ssid;
190         if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
191                 return 0;
192
193         if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
194             !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
195                 return 0;
196
197         wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
198                    "because current AP was marked disallowed");
199
200 #ifdef CONFIG_SME
201         wpa_s->sme.prev_bssid_set = 0;
202 #endif /* CONFIG_SME */
203         wpa_s->reassociate = 1;
204         wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
205         wpa_supplicant_req_scan(wpa_s, 0, 0);
206
207         return 0;
208 }
209
210
211 #ifndef CONFIG_NO_CONFIG_BLOBS
212 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos)
213 {
214         char *name = pos;
215         struct wpa_config_blob *blob;
216         size_t len;
217
218         pos = os_strchr(pos, ' ');
219         if (pos == NULL)
220                 return -1;
221         *pos++ = '\0';
222         len = os_strlen(pos);
223         if (len & 1)
224                 return -1;
225
226         wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name);
227         blob = os_zalloc(sizeof(*blob));
228         if (blob == NULL)
229                 return -1;
230         blob->name = os_strdup(name);
231         blob->data = os_malloc(len / 2);
232         if (blob->name == NULL || blob->data == NULL) {
233                 wpa_config_free_blob(blob);
234                 return -1;
235         }
236
237         if (hexstr2bin(pos, blob->data, len / 2) < 0) {
238                 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data");
239                 wpa_config_free_blob(blob);
240                 return -1;
241         }
242         blob->len = len / 2;
243
244         wpa_config_set_blob(wpa_s->conf, blob);
245
246         return 0;
247 }
248 #endif /* CONFIG_NO_CONFIG_BLOBS */
249
250
251 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
252 {
253         char *params;
254         char *pos;
255         int *freqs = NULL;
256         int ret;
257
258         if (atoi(cmd)) {
259                 params = os_strchr(cmd, ' ');
260                 os_free(wpa_s->manual_sched_scan_freqs);
261                 if (params) {
262                         params++;
263                         pos = os_strstr(params, "freq=");
264                         if (pos)
265                                 freqs = freq_range_to_channel_list(wpa_s,
266                                                                    pos + 5);
267                 }
268                 wpa_s->manual_sched_scan_freqs = freqs;
269                 ret = wpas_start_pno(wpa_s);
270         } else {
271                 ret = wpas_stop_pno(wpa_s);
272         }
273         return ret;
274 }
275
276
277 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
278                                          char *cmd)
279 {
280         char *value;
281         int ret = 0;
282
283         value = os_strchr(cmd, ' ');
284         if (value == NULL)
285                 return -1;
286         *value++ = '\0';
287
288         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
289         if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
290                 eapol_sm_configure(wpa_s->eapol,
291                                    atoi(value), -1, -1, -1);
292         } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
293                 eapol_sm_configure(wpa_s->eapol,
294                                    -1, atoi(value), -1, -1);
295         } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
296                 eapol_sm_configure(wpa_s->eapol,
297                                    -1, -1, atoi(value), -1);
298         } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
299                 eapol_sm_configure(wpa_s->eapol,
300                                    -1, -1, -1, atoi(value));
301         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
302                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
303                                      atoi(value)))
304                         ret = -1;
305         } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
306                    0) {
307                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
308                                      atoi(value)))
309                         ret = -1;
310         } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
311                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
312                         ret = -1;
313         } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
314                 wpa_s->wps_fragment_size = atoi(value);
315 #ifdef CONFIG_WPS_TESTING
316         } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
317                 long int val;
318                 val = strtol(value, NULL, 0);
319                 if (val < 0 || val > 0xff) {
320                         ret = -1;
321                         wpa_printf(MSG_DEBUG, "WPS: Invalid "
322                                    "wps_version_number %ld", val);
323                 } else {
324                         wps_version_number = val;
325                         wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
326                                    "version %u.%u",
327                                    (wps_version_number & 0xf0) >> 4,
328                                    wps_version_number & 0x0f);
329                 }
330         } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
331                 wps_testing_dummy_cred = atoi(value);
332                 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
333                            wps_testing_dummy_cred);
334         } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
335                 wps_corrupt_pkhash = atoi(value);
336                 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
337                            wps_corrupt_pkhash);
338 #endif /* CONFIG_WPS_TESTING */
339         } else if (os_strcasecmp(cmd, "ampdu") == 0) {
340                 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
341                         ret = -1;
342 #ifdef CONFIG_TDLS
343 #ifdef CONFIG_TDLS_TESTING
344         } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
345                 extern unsigned int tdls_testing;
346                 tdls_testing = strtol(value, NULL, 0);
347                 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
348 #endif /* CONFIG_TDLS_TESTING */
349         } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
350                 int disabled = atoi(value);
351                 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
352                 if (disabled) {
353                         if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
354                                 ret = -1;
355                 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
356                         ret = -1;
357                 wpa_tdls_enable(wpa_s->wpa, !disabled);
358 #endif /* CONFIG_TDLS */
359         } else if (os_strcasecmp(cmd, "pno") == 0) {
360                 ret = wpas_ctrl_pno(wpa_s, value);
361         } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
362                 int disabled = atoi(value);
363                 if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
364                         ret = -1;
365                 else if (disabled)
366                         wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
367         } else if (os_strcasecmp(cmd, "uapsd") == 0) {
368                 if (os_strcmp(value, "disable") == 0)
369                         wpa_s->set_sta_uapsd = 0;
370                 else {
371                         int be, bk, vi, vo;
372                         char *pos;
373                         /* format: BE,BK,VI,VO;max SP Length */
374                         be = atoi(value);
375                         pos = os_strchr(value, ',');
376                         if (pos == NULL)
377                                 return -1;
378                         pos++;
379                         bk = atoi(pos);
380                         pos = os_strchr(pos, ',');
381                         if (pos == NULL)
382                                 return -1;
383                         pos++;
384                         vi = atoi(pos);
385                         pos = os_strchr(pos, ',');
386                         if (pos == NULL)
387                                 return -1;
388                         pos++;
389                         vo = atoi(pos);
390                         /* ignore max SP Length for now */
391
392                         wpa_s->set_sta_uapsd = 1;
393                         wpa_s->sta_uapsd = 0;
394                         if (be)
395                                 wpa_s->sta_uapsd |= BIT(0);
396                         if (bk)
397                                 wpa_s->sta_uapsd |= BIT(1);
398                         if (vi)
399                                 wpa_s->sta_uapsd |= BIT(2);
400                         if (vo)
401                                 wpa_s->sta_uapsd |= BIT(3);
402                 }
403         } else if (os_strcasecmp(cmd, "ps") == 0) {
404                 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
405 #ifdef CONFIG_WIFI_DISPLAY
406         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
407                 int enabled = !!atoi(value);
408                 if (enabled && !wpa_s->global->p2p)
409                         ret = -1;
410                 else
411                         wifi_display_enable(wpa_s->global, enabled);
412 #endif /* CONFIG_WIFI_DISPLAY */
413         } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
414                 ret = set_bssid_filter(wpa_s, value);
415         } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
416                 ret = set_disallow_aps(wpa_s, value);
417         } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
418                 wpa_s->no_keep_alive = !!atoi(value);
419 #ifdef CONFIG_TESTING_OPTIONS
420         } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
421                 wpa_s->ext_mgmt_frame_handling = !!atoi(value);
422 #endif /* CONFIG_TESTING_OPTIONS */
423 #ifndef CONFIG_NO_CONFIG_BLOBS
424         } else if (os_strcmp(cmd, "blob") == 0) {
425                 ret = wpas_ctrl_set_blob(wpa_s, value);
426 #endif /* CONFIG_NO_CONFIG_BLOBS */
427         } else {
428                 value[-1] = '=';
429                 ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
430                 if (ret == 0)
431                         wpa_supplicant_update_config(wpa_s);
432         }
433
434         return ret;
435 }
436
437
438 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
439                                          char *cmd, char *buf, size_t buflen)
440 {
441         int res = -1;
442
443         wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
444
445         if (os_strcmp(cmd, "version") == 0) {
446                 res = os_snprintf(buf, buflen, "%s", VERSION_STR);
447         } else if (os_strcasecmp(cmd, "country") == 0) {
448                 if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
449                         res = os_snprintf(buf, buflen, "%c%c",
450                                           wpa_s->conf->country[0],
451                                           wpa_s->conf->country[1]);
452 #ifdef CONFIG_WIFI_DISPLAY
453         } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
454                 int enabled;
455                 if (wpa_s->global->p2p == NULL ||
456                     wpa_s->global->p2p_disabled)
457                         enabled = 0;
458                 else
459                         enabled = wpa_s->global->wifi_display;
460                 res = os_snprintf(buf, buflen, "%d", enabled);
461                 if (res < 0 || (unsigned int) res >= buflen)
462                         return -1;
463                 return res;
464 #endif /* CONFIG_WIFI_DISPLAY */
465 #ifdef CONFIG_TESTING_GET_GTK
466         } else if (os_strcmp(cmd, "gtk") == 0) {
467                 if (wpa_s->last_gtk_len == 0)
468                         return -1;
469                 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk,
470                                        wpa_s->last_gtk_len);
471                 return res;
472 #endif /* CONFIG_TESTING_GET_GTK */
473         }
474
475         if (res < 0 || (unsigned int) res >= buflen)
476                 return -1;
477         return res;
478 }
479
480
481 #ifdef IEEE8021X_EAPOL
482 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
483                                              char *addr)
484 {
485         u8 bssid[ETH_ALEN];
486         struct wpa_ssid *ssid = wpa_s->current_ssid;
487
488         if (hwaddr_aton(addr, bssid)) {
489                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
490                            "'%s'", addr);
491                 return -1;
492         }
493
494         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
495         rsn_preauth_deinit(wpa_s->wpa);
496         if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
497                 return -1;
498
499         return 0;
500 }
501 #endif /* IEEE8021X_EAPOL */
502
503
504 #ifdef CONFIG_PEERKEY
505 /* MLME-STKSTART.request(peer) */
506 static int wpa_supplicant_ctrl_iface_stkstart(
507         struct wpa_supplicant *wpa_s, char *addr)
508 {
509         u8 peer[ETH_ALEN];
510
511         if (hwaddr_aton(addr, peer)) {
512                 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
513                            "address '%s'", addr);
514                 return -1;
515         }
516
517         wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
518                    MAC2STR(peer));
519
520         return wpa_sm_stkstart(wpa_s->wpa, peer);
521 }
522 #endif /* CONFIG_PEERKEY */
523
524
525 #ifdef CONFIG_TDLS
526
527 static int wpa_supplicant_ctrl_iface_tdls_discover(
528         struct wpa_supplicant *wpa_s, char *addr)
529 {
530         u8 peer[ETH_ALEN];
531         int ret;
532
533         if (hwaddr_aton(addr, peer)) {
534                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
535                            "address '%s'", addr);
536                 return -1;
537         }
538
539         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
540                    MAC2STR(peer));
541
542         if (wpa_tdls_is_external_setup(wpa_s->wpa))
543                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
544         else
545                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
546
547         return ret;
548 }
549
550
551 static int wpa_supplicant_ctrl_iface_tdls_setup(
552         struct wpa_supplicant *wpa_s, char *addr)
553 {
554         u8 peer[ETH_ALEN];
555         int ret;
556
557         if (hwaddr_aton(addr, peer)) {
558                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
559                            "address '%s'", addr);
560                 return -1;
561         }
562
563         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
564                    MAC2STR(peer));
565
566         if ((wpa_s->conf->tdls_external_control) &&
567             wpa_tdls_is_external_setup(wpa_s->wpa))
568                 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
569
570         wpa_tdls_remove(wpa_s->wpa, peer);
571
572         if (wpa_tdls_is_external_setup(wpa_s->wpa))
573                 ret = wpa_tdls_start(wpa_s->wpa, peer);
574         else
575                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
576
577         return ret;
578 }
579
580
581 static int wpa_supplicant_ctrl_iface_tdls_teardown(
582         struct wpa_supplicant *wpa_s, char *addr)
583 {
584         u8 peer[ETH_ALEN];
585         int ret;
586
587         if (hwaddr_aton(addr, peer)) {
588                 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
589                            "address '%s'", addr);
590                 return -1;
591         }
592
593         wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
594                    MAC2STR(peer));
595
596         if ((wpa_s->conf->tdls_external_control) &&
597             wpa_tdls_is_external_setup(wpa_s->wpa))
598                 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
599
600         if (wpa_tdls_is_external_setup(wpa_s->wpa))
601                 ret = wpa_tdls_teardown_link(
602                         wpa_s->wpa, peer,
603                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
604         else
605                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
606
607         return ret;
608 }
609
610
611 static int ctrl_iface_get_capability_tdls(
612         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
613 {
614         int ret;
615
616         ret = os_snprintf(buf, buflen, "%s\n",
617                           wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ?
618                           (wpa_s->drv_flags &
619                            WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ?
620                            "EXTERNAL" : "INTERNAL") : "UNSUPPORTED");
621         if (ret < 0 || (size_t) ret > buflen)
622                 return -1;
623         return ret;
624 }
625
626 #endif /* CONFIG_TDLS */
627
628
629 #ifdef CONFIG_IEEE80211R
630 static int wpa_supplicant_ctrl_iface_ft_ds(
631         struct wpa_supplicant *wpa_s, char *addr)
632 {
633         u8 target_ap[ETH_ALEN];
634         struct wpa_bss *bss;
635         const u8 *mdie;
636
637         if (hwaddr_aton(addr, target_ap)) {
638                 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
639                            "address '%s'", addr);
640                 return -1;
641         }
642
643         wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
644
645         bss = wpa_bss_get_bssid(wpa_s, target_ap);
646         if (bss)
647                 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
648         else
649                 mdie = NULL;
650
651         return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
652 }
653 #endif /* CONFIG_IEEE80211R */
654
655
656 #ifdef CONFIG_WPS
657 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
658                                              char *cmd)
659 {
660         u8 bssid[ETH_ALEN], *_bssid = bssid;
661 #ifdef CONFIG_P2P
662         u8 p2p_dev_addr[ETH_ALEN];
663 #endif /* CONFIG_P2P */
664 #ifdef CONFIG_AP
665         u8 *_p2p_dev_addr = NULL;
666 #endif /* CONFIG_AP */
667
668         if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
669                 _bssid = NULL;
670 #ifdef CONFIG_P2P
671         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
672                 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
673                         wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
674                                    "P2P Device Address '%s'",
675                                    cmd + 13);
676                         return -1;
677                 }
678                 _p2p_dev_addr = p2p_dev_addr;
679 #endif /* CONFIG_P2P */
680         } else if (hwaddr_aton(cmd, bssid)) {
681                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
682                            cmd);
683                 return -1;
684         }
685
686 #ifdef CONFIG_AP
687         if (wpa_s->ap_iface)
688                 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
689 #endif /* CONFIG_AP */
690
691         return wpas_wps_start_pbc(wpa_s, _bssid, 0);
692 }
693
694
695 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
696                                              char *cmd, char *buf,
697                                              size_t buflen)
698 {
699         u8 bssid[ETH_ALEN], *_bssid = bssid;
700         char *pin;
701         int ret;
702
703         pin = os_strchr(cmd, ' ');
704         if (pin)
705                 *pin++ = '\0';
706
707         if (os_strcmp(cmd, "any") == 0)
708                 _bssid = NULL;
709         else if (os_strcmp(cmd, "get") == 0) {
710                 ret = wps_generate_pin();
711                 goto done;
712         } else if (hwaddr_aton(cmd, bssid)) {
713                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
714                            cmd);
715                 return -1;
716         }
717
718 #ifdef CONFIG_AP
719         if (wpa_s->ap_iface) {
720                 int timeout = 0;
721                 char *pos;
722
723                 if (pin) {
724                         pos = os_strchr(pin, ' ');
725                         if (pos) {
726                                 *pos++ = '\0';
727                                 timeout = atoi(pos);
728                         }
729                 }
730
731                 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
732                                                  buf, buflen, timeout);
733         }
734 #endif /* CONFIG_AP */
735
736         if (pin) {
737                 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
738                                          DEV_PW_DEFAULT);
739                 if (ret < 0)
740                         return -1;
741                 ret = os_snprintf(buf, buflen, "%s", pin);
742                 if (ret < 0 || (size_t) ret >= buflen)
743                         return -1;
744                 return ret;
745         }
746
747         ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
748         if (ret < 0)
749                 return -1;
750
751 done:
752         /* Return the generated PIN */
753         ret = os_snprintf(buf, buflen, "%08d", ret);
754         if (ret < 0 || (size_t) ret >= buflen)
755                 return -1;
756         return ret;
757 }
758
759
760 static int wpa_supplicant_ctrl_iface_wps_check_pin(
761         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
762 {
763         char pin[9];
764         size_t len;
765         char *pos;
766         int ret;
767
768         wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
769                               (u8 *) cmd, os_strlen(cmd));
770         for (pos = cmd, len = 0; *pos != '\0'; pos++) {
771                 if (*pos < '0' || *pos > '9')
772                         continue;
773                 pin[len++] = *pos;
774                 if (len == 9) {
775                         wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
776                         return -1;
777                 }
778         }
779         if (len != 4 && len != 8) {
780                 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
781                 return -1;
782         }
783         pin[len] = '\0';
784
785         if (len == 8) {
786                 unsigned int pin_val;
787                 pin_val = atoi(pin);
788                 if (!wps_pin_valid(pin_val)) {
789                         wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
790                         ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
791                         if (ret < 0 || (size_t) ret >= buflen)
792                                 return -1;
793                         return ret;
794                 }
795         }
796
797         ret = os_snprintf(buf, buflen, "%s", pin);
798         if (ret < 0 || (size_t) ret >= buflen)
799                 return -1;
800
801         return ret;
802 }
803
804
805 #ifdef CONFIG_WPS_NFC
806
807 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
808                                              char *cmd)
809 {
810         u8 bssid[ETH_ALEN], *_bssid = bssid;
811
812         if (cmd == NULL || cmd[0] == '\0')
813                 _bssid = NULL;
814         else if (hwaddr_aton(cmd, bssid))
815                 return -1;
816
817         return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL,
818                                   0, 0);
819 }
820
821
822 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token(
823         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
824 {
825         int ndef;
826         struct wpabuf *buf;
827         int res;
828         char *pos;
829
830         pos = os_strchr(cmd, ' ');
831         if (pos)
832                 *pos++ = '\0';
833         if (os_strcmp(cmd, "WPS") == 0)
834                 ndef = 0;
835         else if (os_strcmp(cmd, "NDEF") == 0)
836                 ndef = 1;
837         else
838                 return -1;
839
840         buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos);
841         if (buf == NULL)
842                 return -1;
843
844         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
845                                          wpabuf_len(buf));
846         reply[res++] = '\n';
847         reply[res] = '\0';
848
849         wpabuf_free(buf);
850
851         return res;
852 }
853
854
855 static int wpa_supplicant_ctrl_iface_wps_nfc_token(
856         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
857 {
858         int ndef;
859         struct wpabuf *buf;
860         int res;
861
862         if (os_strcmp(cmd, "WPS") == 0)
863                 ndef = 0;
864         else if (os_strcmp(cmd, "NDEF") == 0)
865                 ndef = 1;
866         else
867                 return -1;
868
869         buf = wpas_wps_nfc_token(wpa_s, ndef);
870         if (buf == NULL)
871                 return -1;
872
873         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
874                                          wpabuf_len(buf));
875         reply[res++] = '\n';
876         reply[res] = '\0';
877
878         wpabuf_free(buf);
879
880         return res;
881 }
882
883
884 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
885         struct wpa_supplicant *wpa_s, char *pos)
886 {
887         size_t len;
888         struct wpabuf *buf;
889         int ret;
890         char *freq;
891         int forced_freq = 0;
892
893         freq = strstr(pos, " freq=");
894         if (freq) {
895                 *freq = '\0';
896                 freq += 6;
897                 forced_freq = atoi(freq);
898         }
899
900         len = os_strlen(pos);
901         if (len & 0x01)
902                 return -1;
903         len /= 2;
904
905         buf = wpabuf_alloc(len);
906         if (buf == NULL)
907                 return -1;
908         if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
909                 wpabuf_free(buf);
910                 return -1;
911         }
912
913         ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq);
914         wpabuf_free(buf);
915
916         return ret;
917 }
918
919
920 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
921                                               char *reply, size_t max_len,
922                                               int ndef)
923 {
924         struct wpabuf *buf;
925         int res;
926
927         buf = wpas_wps_nfc_handover_req(wpa_s, ndef);
928         if (buf == NULL)
929                 return -1;
930
931         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
932                                          wpabuf_len(buf));
933         reply[res++] = '\n';
934         reply[res] = '\0';
935
936         wpabuf_free(buf);
937
938         return res;
939 }
940
941
942 #ifdef CONFIG_P2P
943 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
944                                               char *reply, size_t max_len,
945                                               int ndef)
946 {
947         struct wpabuf *buf;
948         int res;
949
950         buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
951         if (buf == NULL) {
952                 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
953                 return -1;
954         }
955
956         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
957                                          wpabuf_len(buf));
958         reply[res++] = '\n';
959         reply[res] = '\0';
960
961         wpabuf_free(buf);
962
963         return res;
964 }
965 #endif /* CONFIG_P2P */
966
967
968 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
969                                           char *cmd, char *reply,
970                                           size_t max_len)
971 {
972         char *pos;
973         int ndef;
974
975         pos = os_strchr(cmd, ' ');
976         if (pos == NULL)
977                 return -1;
978         *pos++ = '\0';
979
980         if (os_strcmp(cmd, "WPS") == 0)
981                 ndef = 0;
982         else if (os_strcmp(cmd, "NDEF") == 0)
983                 ndef = 1;
984         else
985                 return -1;
986
987         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
988                 if (!ndef)
989                         return -1;
990                 return wpas_ctrl_nfc_get_handover_req_wps(
991                         wpa_s, reply, max_len, ndef);
992         }
993
994 #ifdef CONFIG_P2P
995         if (os_strcmp(pos, "P2P-CR") == 0) {
996                 return wpas_ctrl_nfc_get_handover_req_p2p(
997                         wpa_s, reply, max_len, ndef);
998         }
999 #endif /* CONFIG_P2P */
1000
1001         return -1;
1002 }
1003
1004
1005 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
1006                                               char *reply, size_t max_len,
1007                                               int ndef, int cr, char *uuid)
1008 {
1009         struct wpabuf *buf;
1010         int res;
1011
1012         buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
1013         if (buf == NULL)
1014                 return -1;
1015
1016         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1017                                          wpabuf_len(buf));
1018         reply[res++] = '\n';
1019         reply[res] = '\0';
1020
1021         wpabuf_free(buf);
1022
1023         return res;
1024 }
1025
1026
1027 #ifdef CONFIG_P2P
1028 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
1029                                               char *reply, size_t max_len,
1030                                               int ndef, int tag)
1031 {
1032         struct wpabuf *buf;
1033         int res;
1034
1035         buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
1036         if (buf == NULL)
1037                 return -1;
1038
1039         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1040                                          wpabuf_len(buf));
1041         reply[res++] = '\n';
1042         reply[res] = '\0';
1043
1044         wpabuf_free(buf);
1045
1046         return res;
1047 }
1048 #endif /* CONFIG_P2P */
1049
1050
1051 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
1052                                           char *cmd, char *reply,
1053                                           size_t max_len)
1054 {
1055         char *pos, *pos2;
1056         int ndef;
1057
1058         pos = os_strchr(cmd, ' ');
1059         if (pos == NULL)
1060                 return -1;
1061         *pos++ = '\0';
1062
1063         if (os_strcmp(cmd, "WPS") == 0)
1064                 ndef = 0;
1065         else if (os_strcmp(cmd, "NDEF") == 0)
1066                 ndef = 1;
1067         else
1068                 return -1;
1069
1070         pos2 = os_strchr(pos, ' ');
1071         if (pos2)
1072                 *pos2++ = '\0';
1073         if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
1074                 if (!ndef)
1075                         return -1;
1076                 return wpas_ctrl_nfc_get_handover_sel_wps(
1077                         wpa_s, reply, max_len, ndef,
1078                         os_strcmp(pos, "WPS-CR") == 0, pos2);
1079         }
1080
1081 #ifdef CONFIG_P2P
1082         if (os_strcmp(pos, "P2P-CR") == 0) {
1083                 return wpas_ctrl_nfc_get_handover_sel_p2p(
1084                         wpa_s, reply, max_len, ndef, 0);
1085         }
1086
1087         if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
1088                 return wpas_ctrl_nfc_get_handover_sel_p2p(
1089                         wpa_s, reply, max_len, ndef, 1);
1090         }
1091 #endif /* CONFIG_P2P */
1092
1093         return -1;
1094 }
1095
1096
1097 static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
1098                                          char *cmd)
1099 {
1100         size_t len;
1101         struct wpabuf *buf;
1102         int ret;
1103
1104         len = os_strlen(cmd);
1105         if (len & 0x01)
1106                 return -1;
1107         len /= 2;
1108
1109         buf = wpabuf_alloc(len);
1110         if (buf == NULL)
1111                 return -1;
1112         if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
1113                 wpabuf_free(buf);
1114                 return -1;
1115         }
1116
1117         ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf);
1118         wpabuf_free(buf);
1119
1120         return ret;
1121 }
1122
1123
1124 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
1125                                          char *cmd)
1126 {
1127         size_t len;
1128         struct wpabuf *req, *sel;
1129         int ret;
1130         char *pos, *role, *type, *pos2;
1131 #ifdef CONFIG_P2P
1132         char *freq;
1133         int forced_freq = 0;
1134
1135         freq = strstr(cmd, " freq=");
1136         if (freq) {
1137                 *freq = '\0';
1138                 freq += 6;
1139                 forced_freq = atoi(freq);
1140         }
1141 #endif /* CONFIG_P2P */
1142
1143         role = cmd;
1144         pos = os_strchr(role, ' ');
1145         if (pos == NULL) {
1146                 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report");
1147                 return -1;
1148         }
1149         *pos++ = '\0';
1150
1151         type = pos;
1152         pos = os_strchr(type, ' ');
1153         if (pos == NULL) {
1154                 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report");
1155                 return -1;
1156         }
1157         *pos++ = '\0';
1158
1159         pos2 = os_strchr(pos, ' ');
1160         if (pos2 == NULL) {
1161                 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report");
1162                 return -1;
1163         }
1164         *pos2++ = '\0';
1165
1166         len = os_strlen(pos);
1167         if (len & 0x01) {
1168                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report");
1169                 return -1;
1170         }
1171         len /= 2;
1172
1173         req = wpabuf_alloc(len);
1174         if (req == NULL) {
1175                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message");
1176                 return -1;
1177         }
1178         if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
1179                 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report");
1180                 wpabuf_free(req);
1181                 return -1;
1182         }
1183
1184         len = os_strlen(pos2);
1185         if (len & 0x01) {
1186                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report");
1187                 wpabuf_free(req);
1188                 return -1;
1189         }
1190         len /= 2;
1191
1192         sel = wpabuf_alloc(len);
1193         if (sel == NULL) {
1194                 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message");
1195                 wpabuf_free(req);
1196                 return -1;
1197         }
1198         if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
1199                 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report");
1200                 wpabuf_free(req);
1201                 wpabuf_free(sel);
1202                 return -1;
1203         }
1204
1205         wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d",
1206                    role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel));
1207
1208         if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) {
1209                 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel);
1210 #ifdef CONFIG_AP
1211         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
1212         {
1213                 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
1214                 if (ret < 0)
1215                         ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
1216 #endif /* CONFIG_AP */
1217 #ifdef CONFIG_P2P
1218         } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
1219         {
1220                 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0);
1221         } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
1222         {
1223                 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel,
1224                                                    forced_freq);
1225 #endif /* CONFIG_P2P */
1226         } else {
1227                 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
1228                            "reported: role=%s type=%s", role, type);
1229                 ret = -1;
1230         }
1231         wpabuf_free(req);
1232         wpabuf_free(sel);
1233
1234         if (ret)
1235                 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages");
1236
1237         return ret;
1238 }
1239
1240 #endif /* CONFIG_WPS_NFC */
1241
1242
1243 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
1244                                              char *cmd)
1245 {
1246         u8 bssid[ETH_ALEN];
1247         char *pin;
1248         char *new_ssid;
1249         char *new_auth;
1250         char *new_encr;
1251         char *new_key;
1252         struct wps_new_ap_settings ap;
1253
1254         pin = os_strchr(cmd, ' ');
1255         if (pin == NULL)
1256                 return -1;
1257         *pin++ = '\0';
1258
1259         if (hwaddr_aton(cmd, bssid)) {
1260                 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
1261                            cmd);
1262                 return -1;
1263         }
1264
1265         new_ssid = os_strchr(pin, ' ');
1266         if (new_ssid == NULL)
1267                 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
1268         *new_ssid++ = '\0';
1269
1270         new_auth = os_strchr(new_ssid, ' ');
1271         if (new_auth == NULL)
1272                 return -1;
1273         *new_auth++ = '\0';
1274
1275         new_encr = os_strchr(new_auth, ' ');
1276         if (new_encr == NULL)
1277                 return -1;
1278         *new_encr++ = '\0';
1279
1280         new_key = os_strchr(new_encr, ' ');
1281         if (new_key == NULL)
1282                 return -1;
1283         *new_key++ = '\0';
1284
1285         os_memset(&ap, 0, sizeof(ap));
1286         ap.ssid_hex = new_ssid;
1287         ap.auth = new_auth;
1288         ap.encr = new_encr;
1289         ap.key_hex = new_key;
1290         return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
1291 }
1292
1293
1294 #ifdef CONFIG_AP
1295 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
1296                                                 char *cmd, char *buf,
1297                                                 size_t buflen)
1298 {
1299         int timeout = 300;
1300         char *pos;
1301         const char *pin_txt;
1302
1303         if (!wpa_s->ap_iface)
1304                 return -1;
1305
1306         pos = os_strchr(cmd, ' ');
1307         if (pos)
1308                 *pos++ = '\0';
1309
1310         if (os_strcmp(cmd, "disable") == 0) {
1311                 wpas_wps_ap_pin_disable(wpa_s);
1312                 return os_snprintf(buf, buflen, "OK\n");
1313         }
1314
1315         if (os_strcmp(cmd, "random") == 0) {
1316                 if (pos)
1317                         timeout = atoi(pos);
1318                 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
1319                 if (pin_txt == NULL)
1320                         return -1;
1321                 return os_snprintf(buf, buflen, "%s", pin_txt);
1322         }
1323
1324         if (os_strcmp(cmd, "get") == 0) {
1325                 pin_txt = wpas_wps_ap_pin_get(wpa_s);
1326                 if (pin_txt == NULL)
1327                         return -1;
1328                 return os_snprintf(buf, buflen, "%s", pin_txt);
1329         }
1330
1331         if (os_strcmp(cmd, "set") == 0) {
1332                 char *pin;
1333                 if (pos == NULL)
1334                         return -1;
1335                 pin = pos;
1336                 pos = os_strchr(pos, ' ');
1337                 if (pos) {
1338                         *pos++ = '\0';
1339                         timeout = atoi(pos);
1340                 }
1341                 if (os_strlen(pin) > buflen)
1342                         return -1;
1343                 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
1344                         return -1;
1345                 return os_snprintf(buf, buflen, "%s", pin);
1346         }
1347
1348         return -1;
1349 }
1350 #endif /* CONFIG_AP */
1351
1352
1353 #ifdef CONFIG_WPS_ER
1354 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
1355                                                 char *cmd)
1356 {
1357         char *uuid = cmd, *pin, *pos;
1358         u8 addr_buf[ETH_ALEN], *addr = NULL;
1359         pin = os_strchr(uuid, ' ');
1360         if (pin == NULL)
1361                 return -1;
1362         *pin++ = '\0';
1363         pos = os_strchr(pin, ' ');
1364         if (pos) {
1365                 *pos++ = '\0';
1366                 if (hwaddr_aton(pos, addr_buf) == 0)
1367                         addr = addr_buf;
1368         }
1369         return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
1370 }
1371
1372
1373 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
1374                                                   char *cmd)
1375 {
1376         char *uuid = cmd, *pin;
1377         pin = os_strchr(uuid, ' ');
1378         if (pin == NULL)
1379                 return -1;
1380         *pin++ = '\0';
1381         return wpas_wps_er_learn(wpa_s, uuid, pin);
1382 }
1383
1384
1385 static int wpa_supplicant_ctrl_iface_wps_er_set_config(
1386         struct wpa_supplicant *wpa_s, char *cmd)
1387 {
1388         char *uuid = cmd, *id;
1389         id = os_strchr(uuid, ' ');
1390         if (id == NULL)
1391                 return -1;
1392         *id++ = '\0';
1393         return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
1394 }
1395
1396
1397 static int wpa_supplicant_ctrl_iface_wps_er_config(
1398         struct wpa_supplicant *wpa_s, char *cmd)
1399 {
1400         char *pin;
1401         char *new_ssid;
1402         char *new_auth;
1403         char *new_encr;
1404         char *new_key;
1405         struct wps_new_ap_settings ap;
1406
1407         pin = os_strchr(cmd, ' ');
1408         if (pin == NULL)
1409                 return -1;
1410         *pin++ = '\0';
1411
1412         new_ssid = os_strchr(pin, ' ');
1413         if (new_ssid == NULL)
1414                 return -1;
1415         *new_ssid++ = '\0';
1416
1417         new_auth = os_strchr(new_ssid, ' ');
1418         if (new_auth == NULL)
1419                 return -1;
1420         *new_auth++ = '\0';
1421
1422         new_encr = os_strchr(new_auth, ' ');
1423         if (new_encr == NULL)
1424                 return -1;
1425         *new_encr++ = '\0';
1426
1427         new_key = os_strchr(new_encr, ' ');
1428         if (new_key == NULL)
1429                 return -1;
1430         *new_key++ = '\0';
1431
1432         os_memset(&ap, 0, sizeof(ap));
1433         ap.ssid_hex = new_ssid;
1434         ap.auth = new_auth;
1435         ap.encr = new_encr;
1436         ap.key_hex = new_key;
1437         return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
1438 }
1439
1440
1441 #ifdef CONFIG_WPS_NFC
1442 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
1443         struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
1444 {
1445         int ndef;
1446         struct wpabuf *buf;
1447         int res;
1448         char *uuid;
1449
1450         uuid = os_strchr(cmd, ' ');
1451         if (uuid == NULL)
1452                 return -1;
1453         *uuid++ = '\0';
1454
1455         if (os_strcmp(cmd, "WPS") == 0)
1456                 ndef = 0;
1457         else if (os_strcmp(cmd, "NDEF") == 0)
1458                 ndef = 1;
1459         else
1460                 return -1;
1461
1462         buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
1463         if (buf == NULL)
1464                 return -1;
1465
1466         res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
1467                                          wpabuf_len(buf));
1468         reply[res++] = '\n';
1469         reply[res] = '\0';
1470
1471         wpabuf_free(buf);
1472
1473         return res;
1474 }
1475 #endif /* CONFIG_WPS_NFC */
1476 #endif /* CONFIG_WPS_ER */
1477
1478 #endif /* CONFIG_WPS */
1479
1480
1481 #ifdef CONFIG_IBSS_RSN
1482 static int wpa_supplicant_ctrl_iface_ibss_rsn(
1483         struct wpa_supplicant *wpa_s, char *addr)
1484 {
1485         u8 peer[ETH_ALEN];
1486
1487         if (hwaddr_aton(addr, peer)) {
1488                 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
1489                            "address '%s'", addr);
1490                 return -1;
1491         }
1492
1493         wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
1494                    MAC2STR(peer));
1495
1496         return ibss_rsn_start(wpa_s->ibss_rsn, peer);
1497 }
1498 #endif /* CONFIG_IBSS_RSN */
1499
1500
1501 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
1502                                               char *rsp)
1503 {
1504 #ifdef IEEE8021X_EAPOL
1505         char *pos, *id_pos;
1506         int id;
1507         struct wpa_ssid *ssid;
1508
1509         pos = os_strchr(rsp, '-');
1510         if (pos == NULL)
1511                 return -1;
1512         *pos++ = '\0';
1513         id_pos = pos;
1514         pos = os_strchr(pos, ':');
1515         if (pos == NULL)
1516                 return -1;
1517         *pos++ = '\0';
1518         id = atoi(id_pos);
1519         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
1520         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
1521                               (u8 *) pos, os_strlen(pos));
1522
1523         ssid = wpa_config_get_network(wpa_s->conf, id);
1524         if (ssid == NULL) {
1525                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1526                            "to update", id);
1527                 return -1;
1528         }
1529
1530         return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
1531                                                          pos);
1532 #else /* IEEE8021X_EAPOL */
1533         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1534         return -1;
1535 #endif /* IEEE8021X_EAPOL */
1536 }
1537
1538
1539 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
1540                                             const char *params,
1541                                             char *buf, size_t buflen)
1542 {
1543         char *pos, *end, tmp[30];
1544         int res, verbose, wps, ret;
1545 #ifdef CONFIG_HS20
1546         const u8 *hs20;
1547 #endif /* CONFIG_HS20 */
1548
1549         if (os_strcmp(params, "-DRIVER") == 0)
1550                 return wpa_drv_status(wpa_s, buf, buflen);
1551         verbose = os_strcmp(params, "-VERBOSE") == 0;
1552         wps = os_strcmp(params, "-WPS") == 0;
1553         pos = buf;
1554         end = buf + buflen;
1555         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
1556                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1557                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
1558                                   MAC2STR(wpa_s->bssid));
1559                 if (ret < 0 || ret >= end - pos)
1560                         return pos - buf;
1561                 pos += ret;
1562                 if (ssid) {
1563                         u8 *_ssid = ssid->ssid;
1564                         size_t ssid_len = ssid->ssid_len;
1565                         u8 ssid_buf[MAX_SSID_LEN];
1566                         if (ssid_len == 0) {
1567                                 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
1568                                 if (_res < 0)
1569                                         ssid_len = 0;
1570                                 else
1571                                         ssid_len = _res;
1572                                 _ssid = ssid_buf;
1573                         }
1574                         ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
1575                                           wpa_ssid_txt(_ssid, ssid_len),
1576                                           ssid->id);
1577                         if (ret < 0 || ret >= end - pos)
1578                                 return pos - buf;
1579                         pos += ret;
1580
1581                         if (wps && ssid->passphrase &&
1582                             wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
1583                             (ssid->mode == WPAS_MODE_AP ||
1584                              ssid->mode == WPAS_MODE_P2P_GO)) {
1585                                 ret = os_snprintf(pos, end - pos,
1586                                                   "passphrase=%s\n",
1587                                                   ssid->passphrase);
1588                                 if (ret < 0 || ret >= end - pos)
1589                                         return pos - buf;
1590                                 pos += ret;
1591                         }
1592                         if (ssid->id_str) {
1593                                 ret = os_snprintf(pos, end - pos,
1594                                                   "id_str=%s\n",
1595                                                   ssid->id_str);
1596                                 if (ret < 0 || ret >= end - pos)
1597                                         return pos - buf;
1598                                 pos += ret;
1599                         }
1600
1601                         switch (ssid->mode) {
1602                         case WPAS_MODE_INFRA:
1603                                 ret = os_snprintf(pos, end - pos,
1604                                                   "mode=station\n");
1605                                 break;
1606                         case WPAS_MODE_IBSS:
1607                                 ret = os_snprintf(pos, end - pos,
1608                                                   "mode=IBSS\n");
1609                                 break;
1610                         case WPAS_MODE_AP:
1611                                 ret = os_snprintf(pos, end - pos,
1612                                                   "mode=AP\n");
1613                                 break;
1614                         case WPAS_MODE_P2P_GO:
1615                                 ret = os_snprintf(pos, end - pos,
1616                                                   "mode=P2P GO\n");
1617                                 break;
1618                         case WPAS_MODE_P2P_GROUP_FORMATION:
1619                                 ret = os_snprintf(pos, end - pos,
1620                                                   "mode=P2P GO - group "
1621                                                   "formation\n");
1622                                 break;
1623                         default:
1624                                 ret = 0;
1625                                 break;
1626                         }
1627                         if (ret < 0 || ret >= end - pos)
1628                                 return pos - buf;
1629                         pos += ret;
1630                 }
1631
1632 #ifdef CONFIG_AP
1633                 if (wpa_s->ap_iface) {
1634                         pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
1635                                                             end - pos,
1636                                                             verbose);
1637                 } else
1638 #endif /* CONFIG_AP */
1639                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
1640         }
1641 #ifdef CONFIG_SAE
1642         if (wpa_s->wpa_state >= WPA_ASSOCIATED &&
1643 #ifdef CONFIG_AP
1644             !wpa_s->ap_iface &&
1645 #endif /* CONFIG_AP */
1646             wpa_s->sme.sae.state == SAE_ACCEPTED) {
1647                 ret = os_snprintf(pos, end - pos, "sae_group=%d\n",
1648                                   wpa_s->sme.sae.group);
1649                 if (ret < 0 || ret >= end - pos)
1650                         return pos - buf;
1651                 pos += ret;
1652         }
1653 #endif /* CONFIG_SAE */
1654         ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
1655                           wpa_supplicant_state_txt(wpa_s->wpa_state));
1656         if (ret < 0 || ret >= end - pos)
1657                 return pos - buf;
1658         pos += ret;
1659
1660         if (wpa_s->l2 &&
1661             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
1662                 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
1663                 if (ret < 0 || ret >= end - pos)
1664                         return pos - buf;
1665                 pos += ret;
1666         }
1667
1668 #ifdef CONFIG_P2P
1669         if (wpa_s->global->p2p) {
1670                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
1671                                   "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
1672                 if (ret < 0 || ret >= end - pos)
1673                         return pos - buf;
1674                 pos += ret;
1675         }
1676 #endif /* CONFIG_P2P */
1677
1678         ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
1679                           MAC2STR(wpa_s->own_addr));
1680         if (ret < 0 || ret >= end - pos)
1681                 return pos - buf;
1682         pos += ret;
1683
1684 #ifdef CONFIG_HS20
1685         if (wpa_s->current_bss &&
1686             (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss,
1687                                           HS20_IE_VENDOR_TYPE)) &&
1688             wpa_s->wpa_proto == WPA_PROTO_RSN &&
1689             wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1690                 int release = 1;
1691                 if (hs20[1] >= 5) {
1692                         u8 rel_num = (hs20[6] & 0xf0) >> 4;
1693                         release = rel_num + 1;
1694                 }
1695                 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release);
1696                 if (ret < 0 || ret >= end - pos)
1697                         return pos - buf;
1698                 pos += ret;
1699         }
1700
1701         if (wpa_s->current_ssid) {
1702                 struct wpa_cred *cred;
1703                 char *type;
1704
1705                 for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1706                         size_t i;
1707
1708                         if (wpa_s->current_ssid->parent_cred != cred)
1709                                 continue;
1710
1711                         if (cred->provisioning_sp) {
1712                                 ret = os_snprintf(pos, end - pos,
1713                                                   "provisioning_sp=%s\n",
1714                                                   cred->provisioning_sp);
1715                                 if (ret < 0 || ret >= end - pos)
1716                                         return pos - buf;
1717                                 pos += ret;
1718                         }
1719
1720                         if (!cred->domain)
1721                                 goto no_domain;
1722
1723                         i = 0;
1724                         if (wpa_s->current_bss && wpa_s->current_bss->anqp) {
1725                                 struct wpabuf *names =
1726                                         wpa_s->current_bss->anqp->domain_name;
1727                                 for (i = 0; names && i < cred->num_domain; i++)
1728                                 {
1729                                         if (domain_name_list_contains(
1730                                                     names, cred->domain[i], 1))
1731                                                 break;
1732                                 }
1733                                 if (i == cred->num_domain)
1734                                         i = 0; /* show first entry by default */
1735                         }
1736                         ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
1737                                           cred->domain[i]);
1738                         if (ret < 0 || ret >= end - pos)
1739                                 return pos - buf;
1740                         pos += ret;
1741
1742                 no_domain:
1743                         if (wpa_s->current_bss == NULL ||
1744                             wpa_s->current_bss->anqp == NULL)
1745                                 res = -1;
1746                         else
1747                                 res = interworking_home_sp_cred(
1748                                         wpa_s, cred,
1749                                         wpa_s->current_bss->anqp->domain_name);
1750                         if (res > 0)
1751                                 type = "home";
1752                         else if (res == 0)
1753                                 type = "roaming";
1754                         else
1755                                 type = "unknown";
1756
1757                         ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
1758                         if (ret < 0 || ret >= end - pos)
1759                                 return pos - buf;
1760                         pos += ret;
1761
1762                         break;
1763                 }
1764         }
1765 #endif /* CONFIG_HS20 */
1766
1767         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
1768             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1769                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
1770                                           verbose);
1771                 if (res >= 0)
1772                         pos += res;
1773         }
1774
1775         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
1776         if (res >= 0)
1777                 pos += res;
1778
1779 #ifdef CONFIG_WPS
1780         {
1781                 char uuid_str[100];
1782                 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
1783                 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
1784                 if (ret < 0 || ret >= end - pos)
1785                         return pos - buf;
1786                 pos += ret;
1787         }
1788 #endif /* CONFIG_WPS */
1789
1790 #ifdef ANDROID
1791         wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
1792                      "id=%d state=%d BSSID=" MACSTR " SSID=%s",
1793                      wpa_s->current_ssid ? wpa_s->current_ssid->id : -1,
1794                      wpa_s->wpa_state,
1795                      MAC2STR(wpa_s->bssid),
1796                      wpa_s->current_ssid && wpa_s->current_ssid->ssid ?
1797                      wpa_ssid_txt(wpa_s->current_ssid->ssid,
1798                                   wpa_s->current_ssid->ssid_len) : "");
1799         if (wpa_s->wpa_state == WPA_COMPLETED) {
1800                 struct wpa_ssid *ssid = wpa_s->current_ssid;
1801                 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED
1802                              "- connection to " MACSTR
1803                              " completed %s [id=%d id_str=%s]",
1804                              MAC2STR(wpa_s->bssid), "(auth)",
1805                              ssid ? ssid->id : -1,
1806                              ssid && ssid->id_str ? ssid->id_str : "");
1807         }
1808 #endif /* ANDROID */
1809
1810         return pos - buf;
1811 }
1812
1813
1814 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
1815                                            char *cmd)
1816 {
1817         char *pos;
1818         int id;
1819         struct wpa_ssid *ssid;
1820         u8 bssid[ETH_ALEN];
1821
1822         /* cmd: "<network id> <BSSID>" */
1823         pos = os_strchr(cmd, ' ');
1824         if (pos == NULL)
1825                 return -1;
1826         *pos++ = '\0';
1827         id = atoi(cmd);
1828         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
1829         if (hwaddr_aton(pos, bssid)) {
1830                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
1831                 return -1;
1832         }
1833
1834         ssid = wpa_config_get_network(wpa_s->conf, id);
1835         if (ssid == NULL) {
1836                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
1837                            "to update", id);
1838                 return -1;
1839         }
1840
1841         os_memcpy(ssid->bssid, bssid, ETH_ALEN);
1842         ssid->bssid_set = !is_zero_ether_addr(bssid);
1843
1844         return 0;
1845 }
1846
1847
1848 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
1849                                                char *cmd, char *buf,
1850                                                size_t buflen)
1851 {
1852         u8 bssid[ETH_ALEN];
1853         struct wpa_blacklist *e;
1854         char *pos, *end;
1855         int ret;
1856
1857         /* cmd: "BLACKLIST [<BSSID>]" */
1858         if (*cmd == '\0') {
1859                 pos = buf;
1860                 end = buf + buflen;
1861                 e = wpa_s->blacklist;
1862                 while (e) {
1863                         ret = os_snprintf(pos, end - pos, MACSTR "\n",
1864                                           MAC2STR(e->bssid));
1865                         if (ret < 0 || ret >= end - pos)
1866                                 return pos - buf;
1867                         pos += ret;
1868                         e = e->next;
1869                 }
1870                 return pos - buf;
1871         }
1872
1873         cmd++;
1874         if (os_strncmp(cmd, "clear", 5) == 0) {
1875                 wpa_blacklist_clear(wpa_s);
1876                 os_memcpy(buf, "OK\n", 3);
1877                 return 3;
1878         }
1879
1880         wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
1881         if (hwaddr_aton(cmd, bssid)) {
1882                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
1883                 return -1;
1884         }
1885
1886         /*
1887          * Add the BSSID twice, so its count will be 2, causing it to be
1888          * skipped when processing scan results.
1889          */
1890         ret = wpa_blacklist_add(wpa_s, bssid);
1891         if (ret != 0)
1892                 return -1;
1893         ret = wpa_blacklist_add(wpa_s, bssid);
1894         if (ret != 0)
1895                 return -1;
1896         os_memcpy(buf, "OK\n", 3);
1897         return 3;
1898 }
1899
1900
1901 static const char * debug_level_str(int level)
1902 {
1903         switch (level) {
1904         case MSG_EXCESSIVE:
1905                 return "EXCESSIVE";
1906         case MSG_MSGDUMP:
1907                 return "MSGDUMP";
1908         case MSG_DEBUG:
1909                 return "DEBUG";
1910         case MSG_INFO:
1911                 return "INFO";
1912         case MSG_WARNING:
1913                 return "WARNING";
1914         case MSG_ERROR:
1915                 return "ERROR";
1916         default:
1917                 return "?";
1918         }
1919 }
1920
1921
1922 static int str_to_debug_level(const char *s)
1923 {
1924         if (os_strcasecmp(s, "EXCESSIVE") == 0)
1925                 return MSG_EXCESSIVE;
1926         if (os_strcasecmp(s, "MSGDUMP") == 0)
1927                 return MSG_MSGDUMP;
1928         if (os_strcasecmp(s, "DEBUG") == 0)
1929                 return MSG_DEBUG;
1930         if (os_strcasecmp(s, "INFO") == 0)
1931                 return MSG_INFO;
1932         if (os_strcasecmp(s, "WARNING") == 0)
1933                 return MSG_WARNING;
1934         if (os_strcasecmp(s, "ERROR") == 0)
1935                 return MSG_ERROR;
1936         return -1;
1937 }
1938
1939
1940 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
1941                                                char *cmd, char *buf,
1942                                                size_t buflen)
1943 {
1944         char *pos, *end, *stamp;
1945         int ret;
1946
1947         if (cmd == NULL) {
1948                 return -1;
1949         }
1950
1951         /* cmd: "LOG_LEVEL [<level>]" */
1952         if (*cmd == '\0') {
1953                 pos = buf;
1954                 end = buf + buflen;
1955                 ret = os_snprintf(pos, end - pos, "Current level: %s\n"
1956                                   "Timestamp: %d\n",
1957                                   debug_level_str(wpa_debug_level),
1958                                   wpa_debug_timestamp);
1959                 if (ret < 0 || ret >= end - pos)
1960                         ret = 0;
1961
1962                 return ret;
1963         }
1964
1965         while (*cmd == ' ')
1966                 cmd++;
1967
1968         stamp = os_strchr(cmd, ' ');
1969         if (stamp) {
1970                 *stamp++ = '\0';
1971                 while (*stamp == ' ') {
1972                         stamp++;
1973                 }
1974         }
1975
1976         if (cmd && os_strlen(cmd)) {
1977                 int level = str_to_debug_level(cmd);
1978                 if (level < 0)
1979                         return -1;
1980                 wpa_debug_level = level;
1981         }
1982
1983         if (stamp && os_strlen(stamp))
1984                 wpa_debug_timestamp = atoi(stamp);
1985
1986         os_memcpy(buf, "OK\n", 3);
1987         return 3;
1988 }
1989
1990
1991 static int wpa_supplicant_ctrl_iface_list_networks(
1992         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
1993 {
1994         char *pos, *end;
1995         struct wpa_ssid *ssid;
1996         int ret;
1997
1998         pos = buf;
1999         end = buf + buflen;
2000         ret = os_snprintf(pos, end - pos,
2001                           "network id / ssid / bssid / flags\n");
2002         if (ret < 0 || ret >= end - pos)
2003                 return pos - buf;
2004         pos += ret;
2005
2006         ssid = wpa_s->conf->ssid;
2007         while (ssid) {
2008                 ret = os_snprintf(pos, end - pos, "%d\t%s",
2009                                   ssid->id,
2010                                   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2011                 if (ret < 0 || ret >= end - pos)
2012                         return pos - buf;
2013                 pos += ret;
2014                 if (ssid->bssid_set) {
2015                         ret = os_snprintf(pos, end - pos, "\t" MACSTR,
2016                                           MAC2STR(ssid->bssid));
2017                 } else {
2018                         ret = os_snprintf(pos, end - pos, "\tany");
2019                 }
2020                 if (ret < 0 || ret >= end - pos)
2021                         return pos - buf;
2022                 pos += ret;
2023                 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
2024                                   ssid == wpa_s->current_ssid ?
2025                                   "[CURRENT]" : "",
2026                                   ssid->disabled ? "[DISABLED]" : "",
2027                                   ssid->disabled_until.sec ?
2028                                   "[TEMP-DISABLED]" : "",
2029                                   ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
2030                                   "");
2031                 if (ret < 0 || ret >= end - pos)
2032                         return pos - buf;
2033                 pos += ret;
2034                 ret = os_snprintf(pos, end - pos, "\n");
2035                 if (ret < 0 || ret >= end - pos)
2036                         return pos - buf;
2037                 pos += ret;
2038
2039                 ssid = ssid->next;
2040         }
2041
2042         return pos - buf;
2043 }
2044
2045
2046 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
2047 {
2048         int ret;
2049         ret = os_snprintf(pos, end - pos, "-");
2050         if (ret < 0 || ret >= end - pos)
2051                 return pos;
2052         pos += ret;
2053         ret = wpa_write_ciphers(pos, end, cipher, "+");
2054         if (ret < 0)
2055                 return pos;
2056         pos += ret;
2057         return pos;
2058 }
2059
2060
2061 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
2062                                     const u8 *ie, size_t ie_len)
2063 {
2064         struct wpa_ie_data data;
2065         char *start;
2066         int ret;
2067
2068         ret = os_snprintf(pos, end - pos, "[%s-", proto);
2069         if (ret < 0 || ret >= end - pos)
2070                 return pos;
2071         pos += ret;
2072
2073         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
2074                 ret = os_snprintf(pos, end - pos, "?]");
2075                 if (ret < 0 || ret >= end - pos)
2076                         return pos;
2077                 pos += ret;
2078                 return pos;
2079         }
2080
2081         start = pos;
2082         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
2083                 ret = os_snprintf(pos, end - pos, "%sEAP",
2084                                   pos == start ? "" : "+");
2085                 if (ret < 0 || ret >= end - pos)
2086                         return pos;
2087                 pos += ret;
2088         }
2089         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
2090                 ret = os_snprintf(pos, end - pos, "%sPSK",
2091                                   pos == start ? "" : "+");
2092                 if (ret < 0 || ret >= end - pos)
2093                         return pos;
2094                 pos += ret;
2095         }
2096         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
2097                 ret = os_snprintf(pos, end - pos, "%sNone",
2098                                   pos == start ? "" : "+");
2099                 if (ret < 0 || ret >= end - pos)
2100                         return pos;
2101                 pos += ret;
2102         }
2103 #ifdef CONFIG_IEEE80211R
2104         if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
2105                 ret = os_snprintf(pos, end - pos, "%sFT/EAP",
2106                                   pos == start ? "" : "+");
2107                 if (ret < 0 || ret >= end - pos)
2108                         return pos;
2109                 pos += ret;
2110         }
2111         if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
2112                 ret = os_snprintf(pos, end - pos, "%sFT/PSK",
2113                                   pos == start ? "" : "+");
2114                 if (ret < 0 || ret >= end - pos)
2115                         return pos;
2116                 pos += ret;
2117         }
2118 #endif /* CONFIG_IEEE80211R */
2119 #ifdef CONFIG_IEEE80211W
2120         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
2121                 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
2122                                   pos == start ? "" : "+");
2123                 if (ret < 0 || ret >= end - pos)
2124                         return pos;
2125                 pos += ret;
2126         }
2127         if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
2128                 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
2129                                   pos == start ? "" : "+");
2130                 if (ret < 0 || ret >= end - pos)
2131                         return pos;
2132                 pos += ret;
2133         }
2134 #endif /* CONFIG_IEEE80211W */
2135
2136         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
2137
2138         if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
2139                 ret = os_snprintf(pos, end - pos, "-preauth");
2140                 if (ret < 0 || ret >= end - pos)
2141                         return pos;
2142                 pos += ret;
2143         }
2144
2145         ret = os_snprintf(pos, end - pos, "]");
2146         if (ret < 0 || ret >= end - pos)
2147                 return pos;
2148         pos += ret;
2149
2150         return pos;
2151 }
2152
2153
2154 #ifdef CONFIG_WPS
2155 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
2156                                             char *pos, char *end,
2157                                             struct wpabuf *wps_ie)
2158 {
2159         int ret;
2160         const char *txt;
2161
2162         if (wps_ie == NULL)
2163                 return pos;
2164         if (wps_is_selected_pbc_registrar(wps_ie))
2165                 txt = "[WPS-PBC]";
2166         else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
2167                 txt = "[WPS-AUTH]";
2168         else if (wps_is_selected_pin_registrar(wps_ie))
2169                 txt = "[WPS-PIN]";
2170         else
2171                 txt = "[WPS]";
2172
2173         ret = os_snprintf(pos, end - pos, "%s", txt);
2174         if (ret >= 0 && ret < end - pos)
2175                 pos += ret;
2176         wpabuf_free(wps_ie);
2177         return pos;
2178 }
2179 #endif /* CONFIG_WPS */
2180
2181
2182 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
2183                                         char *pos, char *end,
2184                                         const struct wpa_bss *bss)
2185 {
2186 #ifdef CONFIG_WPS
2187         struct wpabuf *wps_ie;
2188         wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
2189         return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
2190 #else /* CONFIG_WPS */
2191         return pos;
2192 #endif /* CONFIG_WPS */
2193 }
2194
2195
2196 /* Format one result on one text line into a buffer. */
2197 static int wpa_supplicant_ctrl_iface_scan_result(
2198         struct wpa_supplicant *wpa_s,
2199         const struct wpa_bss *bss, char *buf, size_t buflen)
2200 {
2201         char *pos, *end;
2202         int ret;
2203         const u8 *ie, *ie2, *p2p;
2204
2205         p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
2206         if (!p2p)
2207                 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE);
2208         if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
2209             os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
2210             0)
2211                 return 0; /* Do not show P2P listen discovery results here */
2212
2213         pos = buf;
2214         end = buf + buflen;
2215
2216         ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
2217                           MAC2STR(bss->bssid), bss->freq, bss->level);
2218         if (ret < 0 || ret >= end - pos)
2219                 return -1;
2220         pos += ret;
2221         ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
2222         if (ie)
2223                 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
2224         ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2225         if (ie2)
2226                 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
2227         pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
2228         if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
2229                 ret = os_snprintf(pos, end - pos, "[WEP]");
2230                 if (ret < 0 || ret >= end - pos)
2231                         return -1;
2232                 pos += ret;
2233         }
2234         if (bss->caps & IEEE80211_CAP_IBSS) {
2235                 ret = os_snprintf(pos, end - pos, "[IBSS]");
2236                 if (ret < 0 || ret >= end - pos)
2237                         return -1;
2238                 pos += ret;
2239         }
2240         if (bss->caps & IEEE80211_CAP_ESS) {
2241                 ret = os_snprintf(pos, end - pos, "[ESS]");
2242                 if (ret < 0 || ret >= end - pos)
2243                         return -1;
2244                 pos += ret;
2245         }
2246         if (p2p) {
2247                 ret = os_snprintf(pos, end - pos, "[P2P]");
2248                 if (ret < 0 || ret >= end - pos)
2249                         return -1;
2250                 pos += ret;
2251         }
2252 #ifdef CONFIG_HS20
2253         if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
2254                 ret = os_snprintf(pos, end - pos, "[HS20]");
2255                 if (ret < 0 || ret >= end - pos)
2256                         return -1;
2257                 pos += ret;
2258         }
2259 #endif /* CONFIG_HS20 */
2260
2261         ret = os_snprintf(pos, end - pos, "\t%s",
2262                           wpa_ssid_txt(bss->ssid, bss->ssid_len));
2263         if (ret < 0 || ret >= end - pos)
2264                 return -1;
2265         pos += ret;
2266
2267         ret = os_snprintf(pos, end - pos, "\n");
2268         if (ret < 0 || ret >= end - pos)
2269                 return -1;
2270         pos += ret;
2271
2272         return pos - buf;
2273 }
2274
2275
2276 static int wpa_supplicant_ctrl_iface_scan_results(
2277         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2278 {
2279         char *pos, *end;
2280         struct wpa_bss *bss;
2281         int ret;
2282
2283         pos = buf;
2284         end = buf + buflen;
2285         ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
2286                           "flags / ssid\n");
2287         if (ret < 0 || ret >= end - pos)
2288                 return pos - buf;
2289         pos += ret;
2290
2291         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2292                 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
2293                                                             end - pos);
2294                 if (ret < 0 || ret >= end - pos)
2295                         return pos - buf;
2296                 pos += ret;
2297         }
2298
2299         return pos - buf;
2300 }
2301
2302
2303 static int wpa_supplicant_ctrl_iface_select_network(
2304         struct wpa_supplicant *wpa_s, char *cmd)
2305 {
2306         int id;
2307         struct wpa_ssid *ssid;
2308         char *pos;
2309
2310         /* cmd: "<network id>" or "any" */
2311         if (os_strncmp(cmd, "any", 3) == 0) {
2312                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
2313                 ssid = NULL;
2314         } else {
2315                 id = atoi(cmd);
2316                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
2317
2318                 ssid = wpa_config_get_network(wpa_s->conf, id);
2319                 if (ssid == NULL) {
2320                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2321                                    "network id=%d", id);
2322                         return -1;
2323                 }
2324                 if (ssid->disabled == 2) {
2325                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2326                                    "SELECT_NETWORK with persistent P2P group");
2327                         return -1;
2328                 }
2329         }
2330
2331         pos = os_strstr(cmd, " freq=");
2332         if (pos) {
2333                 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
2334                 if (freqs) {
2335                         wpa_s->scan_req = MANUAL_SCAN_REQ;
2336                         os_free(wpa_s->manual_scan_freqs);
2337                         wpa_s->manual_scan_freqs = freqs;
2338                 }
2339         }
2340
2341         wpa_supplicant_select_network(wpa_s, ssid);
2342
2343         return 0;
2344 }
2345
2346
2347 static int wpa_supplicant_ctrl_iface_enable_network(
2348         struct wpa_supplicant *wpa_s, char *cmd)
2349 {
2350         int id;
2351         struct wpa_ssid *ssid;
2352
2353         /* cmd: "<network id>" or "all" */
2354         if (os_strcmp(cmd, "all") == 0) {
2355                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
2356                 ssid = NULL;
2357         } else {
2358                 id = atoi(cmd);
2359                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
2360
2361                 ssid = wpa_config_get_network(wpa_s->conf, id);
2362                 if (ssid == NULL) {
2363                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2364                                    "network id=%d", id);
2365                         return -1;
2366                 }
2367                 if (ssid->disabled == 2) {
2368                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2369                                    "ENABLE_NETWORK with persistent P2P group");
2370                         return -1;
2371                 }
2372
2373                 if (os_strstr(cmd, " no-connect")) {
2374                         ssid->disabled = 0;
2375                         return 0;
2376                 }
2377         }
2378         wpa_supplicant_enable_network(wpa_s, ssid);
2379
2380         return 0;
2381 }
2382
2383
2384 static int wpa_supplicant_ctrl_iface_disable_network(
2385         struct wpa_supplicant *wpa_s, char *cmd)
2386 {
2387         int id;
2388         struct wpa_ssid *ssid;
2389
2390         /* cmd: "<network id>" or "all" */
2391         if (os_strcmp(cmd, "all") == 0) {
2392                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
2393                 ssid = NULL;
2394         } else {
2395                 id = atoi(cmd);
2396                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
2397
2398                 ssid = wpa_config_get_network(wpa_s->conf, id);
2399                 if (ssid == NULL) {
2400                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
2401                                    "network id=%d", id);
2402                         return -1;
2403                 }
2404                 if (ssid->disabled == 2) {
2405                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
2406                                    "DISABLE_NETWORK with persistent P2P "
2407                                    "group");
2408                         return -1;
2409                 }
2410         }
2411         wpa_supplicant_disable_network(wpa_s, ssid);
2412
2413         return 0;
2414 }
2415
2416
2417 static int wpa_supplicant_ctrl_iface_add_network(
2418         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
2419 {
2420         struct wpa_ssid *ssid;
2421         int ret;
2422
2423         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
2424
2425         ssid = wpa_config_add_network(wpa_s->conf);
2426         if (ssid == NULL)
2427                 return -1;
2428
2429         wpas_notify_network_added(wpa_s, ssid);
2430
2431         ssid->disabled = 1;
2432         wpa_config_set_network_defaults(ssid);
2433
2434         ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
2435         if (ret < 0 || (size_t) ret >= buflen)
2436                 return -1;
2437         return ret;
2438 }
2439
2440
2441 static int wpa_supplicant_ctrl_iface_remove_network(
2442         struct wpa_supplicant *wpa_s, char *cmd)
2443 {
2444         int id;
2445         struct wpa_ssid *ssid;
2446         int was_disabled;
2447
2448         /* cmd: "<network id>" or "all" */
2449         if (os_strcmp(cmd, "all") == 0) {
2450                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
2451                 if (wpa_s->sched_scanning)
2452                         wpa_supplicant_cancel_sched_scan(wpa_s);
2453
2454                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2455                 if (wpa_s->current_ssid) {
2456 #ifdef CONFIG_SME
2457                         wpa_s->sme.prev_bssid_set = 0;
2458 #endif /* CONFIG_SME */
2459                         wpa_sm_set_config(wpa_s->wpa, NULL);
2460                         eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2461                         wpa_supplicant_deauthenticate(
2462                                 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2463                 }
2464                 ssid = wpa_s->conf->ssid;
2465                 while (ssid) {
2466                         struct wpa_ssid *remove_ssid = ssid;
2467                         id = ssid->id;
2468                         ssid = ssid->next;
2469                         wpas_notify_network_removed(wpa_s, remove_ssid);
2470                         wpa_config_remove_network(wpa_s->conf, id);
2471                 }
2472                 return 0;
2473         }
2474
2475         id = atoi(cmd);
2476         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
2477
2478         ssid = wpa_config_get_network(wpa_s->conf, id);
2479         if (ssid)
2480                 wpas_notify_network_removed(wpa_s, ssid);
2481         if (ssid == NULL) {
2482                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2483                            "id=%d", id);
2484                 return -1;
2485         }
2486
2487         if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2488 #ifdef CONFIG_SME
2489                 wpa_s->sme.prev_bssid_set = 0;
2490 #endif /* CONFIG_SME */
2491                 /*
2492                  * Invalidate the EAP session cache if the current or
2493                  * previously used network is removed.
2494                  */
2495                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2496         }
2497
2498         if (ssid == wpa_s->current_ssid) {
2499                 wpa_sm_set_config(wpa_s->wpa, NULL);
2500                 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2501
2502                 wpa_supplicant_deauthenticate(wpa_s,
2503                                               WLAN_REASON_DEAUTH_LEAVING);
2504         }
2505
2506         was_disabled = ssid->disabled;
2507
2508         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2509                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
2510                            "network id=%d", id);
2511                 return -1;
2512         }
2513
2514         if (!was_disabled && wpa_s->sched_scanning) {
2515                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2516                            "network from filters");
2517                 wpa_supplicant_cancel_sched_scan(wpa_s);
2518                 wpa_supplicant_req_scan(wpa_s, 0, 0);
2519         }
2520
2521         return 0;
2522 }
2523
2524
2525 static int wpa_supplicant_ctrl_iface_set_network(
2526         struct wpa_supplicant *wpa_s, char *cmd)
2527 {
2528         int id;
2529         struct wpa_ssid *ssid;
2530         char *name, *value;
2531
2532         /* cmd: "<network id> <variable name> <value>" */
2533         name = os_strchr(cmd, ' ');
2534         if (name == NULL)
2535                 return -1;
2536         *name++ = '\0';
2537
2538         value = os_strchr(name, ' ');
2539         if (value == NULL)
2540                 return -1;
2541         *value++ = '\0';
2542
2543         id = atoi(cmd);
2544         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
2545                    id, name);
2546         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2547                               (u8 *) value, os_strlen(value));
2548
2549         ssid = wpa_config_get_network(wpa_s->conf, id);
2550         if (ssid == NULL) {
2551                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2552                            "id=%d", id);
2553                 return -1;
2554         }
2555
2556         if (wpa_config_set(ssid, name, value, 0) < 0) {
2557                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
2558                            "variable '%s'", name);
2559                 return -1;
2560         }
2561
2562         if (os_strcmp(name, "bssid") != 0 &&
2563             os_strcmp(name, "priority") != 0)
2564                 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
2565
2566         if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
2567                 /*
2568                  * Invalidate the EAP session cache if anything in the current
2569                  * or previously used configuration changes.
2570                  */
2571                 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2572         }
2573
2574         if ((os_strcmp(name, "psk") == 0 &&
2575              value[0] == '"' && ssid->ssid_len) ||
2576             (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
2577                 wpa_config_update_psk(ssid);
2578         else if (os_strcmp(name, "priority") == 0)
2579                 wpa_config_update_prio_list(wpa_s->conf);
2580
2581         return 0;
2582 }
2583
2584
2585 static int wpa_supplicant_ctrl_iface_get_network(
2586         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
2587 {
2588         int id;
2589         size_t res;
2590         struct wpa_ssid *ssid;
2591         char *name, *value;
2592
2593         /* cmd: "<network id> <variable name>" */
2594         name = os_strchr(cmd, ' ');
2595         if (name == NULL || buflen == 0)
2596                 return -1;
2597         *name++ = '\0';
2598
2599         id = atoi(cmd);
2600         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
2601                    id, name);
2602
2603         ssid = wpa_config_get_network(wpa_s->conf, id);
2604         if (ssid == NULL) {
2605                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
2606                            "id=%d", id);
2607                 return -1;
2608         }
2609
2610         value = wpa_config_get_no_key(ssid, name);
2611         if (value == NULL) {
2612                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
2613                            "variable '%s'", name);
2614                 return -1;
2615         }
2616
2617         res = os_strlcpy(buf, value, buflen);
2618         if (res >= buflen) {
2619                 os_free(value);
2620                 return -1;
2621         }
2622
2623         os_free(value);
2624
2625         return res;
2626 }
2627
2628
2629 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
2630                                                 char *buf, size_t buflen)
2631 {
2632         char *pos, *end;
2633         struct wpa_cred *cred;
2634         int ret;
2635
2636         pos = buf;
2637         end = buf + buflen;
2638         ret = os_snprintf(pos, end - pos,
2639                           "cred id / realm / username / domain / imsi\n");
2640         if (ret < 0 || ret >= end - pos)
2641                 return pos - buf;
2642         pos += ret;
2643
2644         cred = wpa_s->conf->cred;
2645         while (cred) {
2646                 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
2647                                   cred->id, cred->realm ? cred->realm : "",
2648                                   cred->username ? cred->username : "",
2649                                   cred->domain ? cred->domain[0] : "",
2650                                   cred->imsi ? cred->imsi : "");
2651                 if (ret < 0 || ret >= end - pos)
2652                         return pos - buf;
2653                 pos += ret;
2654
2655                 cred = cred->next;
2656         }
2657
2658         return pos - buf;
2659 }
2660
2661
2662 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
2663                                               char *buf, size_t buflen)
2664 {
2665         struct wpa_cred *cred;
2666         int ret;
2667
2668         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
2669
2670         cred = wpa_config_add_cred(wpa_s->conf);
2671         if (cred == NULL)
2672                 return -1;
2673
2674         wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
2675
2676         ret = os_snprintf(buf, buflen, "%d\n", cred->id);
2677         if (ret < 0 || (size_t) ret >= buflen)
2678                 return -1;
2679         return ret;
2680 }
2681
2682
2683 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
2684                                  struct wpa_cred *cred)
2685 {
2686         struct wpa_ssid *ssid;
2687         char str[20];
2688         int id;
2689
2690         if (cred == NULL) {
2691                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
2692                 return -1;
2693         }
2694
2695         id = cred->id;
2696         if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
2697                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
2698                 return -1;
2699         }
2700
2701         wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
2702
2703         /* Remove any network entry created based on the removed credential */
2704         ssid = wpa_s->conf->ssid;
2705         while (ssid) {
2706                 if (ssid->parent_cred == cred) {
2707                         wpa_printf(MSG_DEBUG, "Remove network id %d since it "
2708                                    "used the removed credential", ssid->id);
2709                         os_snprintf(str, sizeof(str), "%d", ssid->id);
2710                         ssid = ssid->next;
2711                         wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
2712                 } else
2713                         ssid = ssid->next;
2714         }
2715
2716         return 0;
2717 }
2718
2719
2720 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
2721                                                  char *cmd)
2722 {
2723         int id;
2724         struct wpa_cred *cred, *prev;
2725
2726         /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or
2727          * "provisioning_sp=<FQDN> */
2728         if (os_strcmp(cmd, "all") == 0) {
2729                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
2730                 cred = wpa_s->conf->cred;
2731                 while (cred) {
2732                         prev = cred;
2733                         cred = cred->next;
2734                         wpas_ctrl_remove_cred(wpa_s, prev);
2735                 }
2736                 return 0;
2737         }
2738
2739         if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
2740                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'",
2741                            cmd + 8);
2742                 cred = wpa_s->conf->cred;
2743                 while (cred) {
2744                         prev = cred;
2745                         cred = cred->next;
2746                         if (prev->domain) {
2747                                 size_t i;
2748                                 for (i = 0; i < prev->num_domain; i++) {
2749                                         if (os_strcmp(prev->domain[i], cmd + 8)
2750                                             != 0)
2751                                                 continue;
2752                                         wpas_ctrl_remove_cred(wpa_s, prev);
2753                                         break;
2754                                 }
2755                         }
2756                 }
2757                 return 0;
2758         }
2759
2760         if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) {
2761                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'",
2762                            cmd + 16);
2763                 cred = wpa_s->conf->cred;
2764                 while (cred) {
2765                         prev = cred;
2766                         cred = cred->next;
2767                         if (prev->provisioning_sp &&
2768                             os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
2769                                 wpas_ctrl_remove_cred(wpa_s, prev);
2770                 }
2771                 return 0;
2772         }
2773
2774         id = atoi(cmd);
2775         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
2776
2777         cred = wpa_config_get_cred(wpa_s->conf, id);
2778         return wpas_ctrl_remove_cred(wpa_s, cred);
2779 }
2780
2781
2782 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
2783                                               char *cmd)
2784 {
2785         int id;
2786         struct wpa_cred *cred;
2787         char *name, *value;
2788
2789         /* cmd: "<cred id> <variable name> <value>" */
2790         name = os_strchr(cmd, ' ');
2791         if (name == NULL)
2792                 return -1;
2793         *name++ = '\0';
2794
2795         value = os_strchr(name, ' ');
2796         if (value == NULL)
2797                 return -1;
2798         *value++ = '\0';
2799
2800         id = atoi(cmd);
2801         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
2802                    id, name);
2803         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
2804                               (u8 *) value, os_strlen(value));
2805
2806         cred = wpa_config_get_cred(wpa_s->conf, id);
2807         if (cred == NULL) {
2808                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2809                            id);
2810                 return -1;
2811         }
2812
2813         if (wpa_config_set_cred(cred, name, value, 0) < 0) {
2814                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
2815                            "variable '%s'", name);
2816                 return -1;
2817         }
2818
2819         wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
2820
2821         return 0;
2822 }
2823
2824
2825 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
2826                                               char *cmd, char *buf,
2827                                               size_t buflen)
2828 {
2829         int id;
2830         size_t res;
2831         struct wpa_cred *cred;
2832         char *name, *value;
2833
2834         /* cmd: "<cred id> <variable name>" */
2835         name = os_strchr(cmd, ' ');
2836         if (name == NULL)
2837                 return -1;
2838         *name++ = '\0';
2839
2840         id = atoi(cmd);
2841         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
2842                    id, name);
2843
2844         cred = wpa_config_get_cred(wpa_s->conf, id);
2845         if (cred == NULL) {
2846                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
2847                            id);
2848                 return -1;
2849         }
2850
2851         value = wpa_config_get_cred_no_key(cred, name);
2852         if (value == NULL) {
2853                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
2854                            name);
2855                 return -1;
2856         }
2857
2858         res = os_strlcpy(buf, value, buflen);
2859         if (res >= buflen) {
2860                 os_free(value);
2861                 return -1;
2862         }
2863
2864         os_free(value);
2865
2866         return res;
2867 }
2868
2869
2870 #ifndef CONFIG_NO_CONFIG_WRITE
2871 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
2872 {
2873         int ret;
2874
2875         if (!wpa_s->conf->update_config) {
2876                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
2877                            "to update configuration (update_config=0)");
2878                 return -1;
2879         }
2880
2881         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
2882         if (ret) {
2883                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
2884                            "update configuration");
2885         } else {
2886                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
2887                            " updated");
2888         }
2889
2890         return ret;
2891 }
2892 #endif /* CONFIG_NO_CONFIG_WRITE */
2893
2894
2895 struct cipher_info {
2896         unsigned int capa;
2897         const char *name;
2898         int group_only;
2899 };
2900
2901 static const struct cipher_info ciphers[] = {
2902         { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
2903         { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
2904         { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
2905         { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
2906         { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
2907         { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
2908         { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
2909         { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
2910 };
2911
2912
2913 static int ctrl_iface_get_capability_pairwise(int res, char *strict,
2914                                               struct wpa_driver_capa *capa,
2915                                               char *buf, size_t buflen)
2916 {
2917         int ret;
2918         char *pos, *end;
2919         size_t len;
2920         unsigned int i;
2921
2922         pos = buf;
2923         end = pos + buflen;
2924
2925         if (res < 0) {
2926                 if (strict)
2927                         return 0;
2928                 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
2929                 if (len >= buflen)
2930                         return -1;
2931                 return len;
2932         }
2933
2934         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
2935                 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
2936                         ret = os_snprintf(pos, end - pos, "%s%s",
2937                                           pos == buf ? "" : " ",
2938                                           ciphers[i].name);
2939                         if (ret < 0 || ret >= end - pos)
2940                                 return pos - buf;
2941                         pos += ret;
2942                 }
2943         }
2944
2945         return pos - buf;
2946 }
2947
2948
2949 static int ctrl_iface_get_capability_group(int res, char *strict,
2950                                            struct wpa_driver_capa *capa,
2951                                            char *buf, size_t buflen)
2952 {
2953         int ret;
2954         char *pos, *end;
2955         size_t len;
2956         unsigned int i;
2957
2958         pos = buf;
2959         end = pos + buflen;
2960
2961         if (res < 0) {
2962                 if (strict)
2963                         return 0;
2964                 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
2965                 if (len >= buflen)
2966                         return -1;
2967                 return len;
2968         }
2969
2970         for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
2971                 if (capa->enc & ciphers[i].capa) {
2972                         ret = os_snprintf(pos, end - pos, "%s%s",
2973                                           pos == buf ? "" : " ",
2974                                           ciphers[i].name);
2975                         if (ret < 0 || ret >= end - pos)
2976                                 return pos - buf;
2977                         pos += ret;
2978                 }
2979         }
2980
2981         return pos - buf;
2982 }
2983
2984
2985 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
2986                                               struct wpa_driver_capa *capa,
2987                                               char *buf, size_t buflen)
2988 {
2989         int ret;
2990         char *pos, *end;
2991         size_t len;
2992
2993         pos = buf;
2994         end = pos + buflen;
2995
2996         if (res < 0) {
2997                 if (strict)
2998                         return 0;
2999                 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
3000                                  "NONE", buflen);
3001                 if (len >= buflen)
3002                         return -1;
3003                 return len;
3004         }
3005
3006         ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
3007         if (ret < 0 || ret >= end - pos)
3008                 return pos - buf;
3009         pos += ret;
3010
3011         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3012                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
3013                 ret = os_snprintf(pos, end - pos, " WPA-EAP");
3014                 if (ret < 0 || ret >= end - pos)
3015                         return pos - buf;
3016                 pos += ret;
3017         }
3018
3019         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3020                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3021                 ret = os_snprintf(pos, end - pos, " WPA-PSK");
3022                 if (ret < 0 || ret >= end - pos)
3023                         return pos - buf;
3024                 pos += ret;
3025         }
3026
3027         if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
3028                 ret = os_snprintf(pos, end - pos, " WPA-NONE");
3029                 if (ret < 0 || ret >= end - pos)
3030                         return pos - buf;
3031                 pos += ret;
3032         }
3033
3034         return pos - buf;
3035 }
3036
3037
3038 static int ctrl_iface_get_capability_proto(int res, char *strict,
3039                                            struct wpa_driver_capa *capa,
3040                                            char *buf, size_t buflen)
3041 {
3042         int ret;
3043         char *pos, *end;
3044         size_t len;
3045
3046         pos = buf;
3047         end = pos + buflen;
3048
3049         if (res < 0) {
3050                 if (strict)
3051                         return 0;
3052                 len = os_strlcpy(buf, "RSN WPA", buflen);
3053                 if (len >= buflen)
3054                         return -1;
3055                 return len;
3056         }
3057
3058         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
3059                               WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
3060                 ret = os_snprintf(pos, end - pos, "%sRSN",
3061                                   pos == buf ? "" : " ");
3062                 if (ret < 0 || ret >= end - pos)
3063                         return pos - buf;
3064                 pos += ret;
3065         }
3066
3067         if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3068                               WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
3069                 ret = os_snprintf(pos, end - pos, "%sWPA",
3070                                   pos == buf ? "" : " ");
3071                 if (ret < 0 || ret >= end - pos)
3072                         return pos - buf;
3073                 pos += ret;
3074         }
3075
3076         return pos - buf;
3077 }
3078
3079
3080 static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
3081                                               struct wpa_driver_capa *capa,
3082                                               char *buf, size_t buflen)
3083 {
3084         int ret;
3085         char *pos, *end;
3086         size_t len;
3087
3088         pos = buf;
3089         end = pos + buflen;
3090
3091         if (res < 0) {
3092                 if (strict)
3093                         return 0;
3094                 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
3095                 if (len >= buflen)
3096                         return -1;
3097                 return len;
3098         }
3099
3100         if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
3101                 ret = os_snprintf(pos, end - pos, "%sOPEN",
3102                                   pos == buf ? "" : " ");
3103                 if (ret < 0 || ret >= end - pos)
3104                         return pos - buf;
3105                 pos += ret;
3106         }
3107
3108         if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
3109                 ret = os_snprintf(pos, end - pos, "%sSHARED",
3110                                   pos == buf ? "" : " ");
3111                 if (ret < 0 || ret >= end - pos)
3112                         return pos - buf;
3113                 pos += ret;
3114         }
3115
3116         if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
3117                 ret = os_snprintf(pos, end - pos, "%sLEAP",
3118                                   pos == buf ? "" : " ");
3119                 if (ret < 0 || ret >= end - pos)
3120                         return pos - buf;
3121                 pos += ret;
3122         }
3123
3124         return pos - buf;
3125 }
3126
3127
3128 static int ctrl_iface_get_capability_modes(int res, char *strict,
3129                                            struct wpa_driver_capa *capa,
3130                                            char *buf, size_t buflen)
3131 {
3132         int ret;
3133         char *pos, *end;
3134         size_t len;
3135
3136         pos = buf;
3137         end = pos + buflen;
3138
3139         if (res < 0) {
3140                 if (strict)
3141                         return 0;
3142                 len = os_strlcpy(buf, "IBSS AP", buflen);
3143                 if (len >= buflen)
3144                         return -1;
3145                 return len;
3146         }
3147
3148         if (capa->flags & WPA_DRIVER_FLAGS_IBSS) {
3149                 ret = os_snprintf(pos, end - pos, "%sIBSS",
3150                                   pos == buf ? "" : " ");
3151                 if (ret < 0 || ret >= end - pos)
3152                         return pos - buf;
3153                 pos += ret;
3154         }
3155
3156         if (capa->flags & WPA_DRIVER_FLAGS_AP) {
3157                 ret = os_snprintf(pos, end - pos, "%sAP",
3158                                   pos == buf ? "" : " ");
3159                 if (ret < 0 || ret >= end - pos)
3160                         return pos - buf;
3161                 pos += ret;
3162         }
3163
3164         return pos - buf;
3165 }
3166
3167
3168 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s,
3169                                               char *buf, size_t buflen)
3170 {
3171         struct hostapd_channel_data *chnl;
3172         int ret, i, j;
3173         char *pos, *end, *hmode;
3174
3175         pos = buf;
3176         end = pos + buflen;
3177
3178         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3179                 switch (wpa_s->hw.modes[j].mode) {
3180                 case HOSTAPD_MODE_IEEE80211B:
3181                         hmode = "B";
3182                         break;
3183                 case HOSTAPD_MODE_IEEE80211G:
3184                         hmode = "G";
3185                         break;
3186                 case HOSTAPD_MODE_IEEE80211A:
3187                         hmode = "A";
3188                         break;
3189                 case HOSTAPD_MODE_IEEE80211AD:
3190                         hmode = "AD";
3191                         break;
3192                 default:
3193                         continue;
3194                 }
3195                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode);
3196                 if (ret < 0 || ret >= end - pos)
3197                         return pos - buf;
3198                 pos += ret;
3199                 chnl = wpa_s->hw.modes[j].channels;
3200                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3201                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3202                                 continue;
3203                         ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan);
3204                         if (ret < 0 || ret >= end - pos)
3205                                 return pos - buf;
3206                         pos += ret;
3207                 }
3208                 ret = os_snprintf(pos, end - pos, "\n");
3209                 if (ret < 0 || ret >= end - pos)
3210                         return pos - buf;
3211                 pos += ret;
3212         }
3213
3214         return pos - buf;
3215 }
3216
3217
3218 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s,
3219                                           char *buf, size_t buflen)
3220 {
3221         struct hostapd_channel_data *chnl;
3222         int ret, i, j;
3223         char *pos, *end, *hmode;
3224
3225         pos = buf;
3226         end = pos + buflen;
3227
3228         for (j = 0; j < wpa_s->hw.num_modes; j++) {
3229                 switch (wpa_s->hw.modes[j].mode) {
3230                 case HOSTAPD_MODE_IEEE80211B:
3231                         hmode = "B";
3232                         break;
3233                 case HOSTAPD_MODE_IEEE80211G:
3234                         hmode = "G";
3235                         break;
3236                 case HOSTAPD_MODE_IEEE80211A:
3237                         hmode = "A";
3238                         break;
3239                 case HOSTAPD_MODE_IEEE80211AD:
3240                         hmode = "AD";
3241                         break;
3242                 default:
3243                         continue;
3244                 }
3245                 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n",
3246                                   hmode);
3247                 if (ret < 0 || ret >= end - pos)
3248                         return pos - buf;
3249                 pos += ret;
3250                 chnl = wpa_s->hw.modes[j].channels;
3251                 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) {
3252                         if (chnl[i].flag & HOSTAPD_CHAN_DISABLED)
3253                                 continue;
3254                         ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n",
3255                                           chnl[i].chan, chnl[i].freq,
3256                                           chnl[i].flag & HOSTAPD_CHAN_NO_IBSS ?
3257                                           " (NO_IBSS)" : "",
3258                                           chnl[i].flag & HOSTAPD_CHAN_RADAR ?
3259                                           " (DFS)" : "");
3260
3261                         if (ret < 0 || ret >= end - pos)
3262                                 return pos - buf;
3263                         pos += ret;
3264                 }
3265                 ret = os_snprintf(pos, end - pos, "\n");
3266                 if (ret < 0 || ret >= end - pos)
3267                         return pos - buf;
3268                 pos += ret;
3269         }
3270
3271         return pos - buf;
3272 }
3273
3274
3275 static int wpa_supplicant_ctrl_iface_get_capability(
3276         struct wpa_supplicant *wpa_s, const char *_field, char *buf,
3277         size_t buflen)
3278 {
3279         struct wpa_driver_capa capa;
3280         int res;
3281         char *strict;
3282         char field[30];
3283         size_t len;
3284
3285         /* Determine whether or not strict checking was requested */
3286         len = os_strlcpy(field, _field, sizeof(field));
3287         if (len >= sizeof(field))
3288                 return -1;
3289         strict = os_strchr(field, ' ');
3290         if (strict != NULL) {
3291                 *strict++ = '\0';
3292                 if (os_strcmp(strict, "strict") != 0)
3293                         return -1;
3294         }
3295
3296         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
3297                 field, strict ? strict : "");
3298
3299         if (os_strcmp(field, "eap") == 0) {
3300                 return eap_get_names(buf, buflen);
3301         }
3302
3303         res = wpa_drv_get_capa(wpa_s, &capa);
3304
3305         if (os_strcmp(field, "pairwise") == 0)
3306                 return ctrl_iface_get_capability_pairwise(res, strict, &capa,
3307                                                           buf, buflen);
3308
3309         if (os_strcmp(field, "group") == 0)
3310                 return ctrl_iface_get_capability_group(res, strict, &capa,
3311                                                        buf, buflen);
3312
3313         if (os_strcmp(field, "key_mgmt") == 0)
3314                 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
3315                                                           buf, buflen);
3316
3317         if (os_strcmp(field, "proto") == 0)
3318                 return ctrl_iface_get_capability_proto(res, strict, &capa,
3319                                                        buf, buflen);
3320
3321         if (os_strcmp(field, "auth_alg") == 0)
3322                 return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
3323                                                           buf, buflen);
3324
3325         if (os_strcmp(field, "modes") == 0)
3326                 return ctrl_iface_get_capability_modes(res, strict, &capa,
3327                                                        buf, buflen);
3328
3329         if (os_strcmp(field, "channels") == 0)
3330                 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen);
3331
3332         if (os_strcmp(field, "freq") == 0)
3333                 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen);
3334
3335 #ifdef CONFIG_TDLS
3336         if (os_strcmp(field, "tdls") == 0)
3337                 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen);
3338 #endif /* CONFIG_TDLS */
3339
3340         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
3341                    field);
3342
3343         return -1;
3344 }
3345
3346
3347 #ifdef CONFIG_INTERWORKING
3348 static char * anqp_add_hex(char *pos, char *end, const char *title,
3349                            struct wpabuf *data)
3350 {
3351         char *start = pos;
3352         size_t i;
3353         int ret;
3354         const u8 *d;
3355
3356         if (data == NULL)
3357                 return start;
3358
3359         ret = os_snprintf(pos, end - pos, "%s=", title);
3360         if (ret < 0 || ret >= end - pos)
3361                 return start;
3362         pos += ret;
3363
3364         d = wpabuf_head_u8(data);
3365         for (i = 0; i < wpabuf_len(data); i++) {
3366                 ret = os_snprintf(pos, end - pos, "%02x", *d++);
3367                 if (ret < 0 || ret >= end - pos)
3368                         return start;
3369                 pos += ret;
3370         }
3371
3372         ret = os_snprintf(pos, end - pos, "\n");
3373         if (ret < 0 || ret >= end - pos)
3374                 return start;
3375         pos += ret;
3376
3377         return pos;
3378 }
3379 #endif /* CONFIG_INTERWORKING */
3380
3381
3382 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
3383                           unsigned long mask, char *buf, size_t buflen)
3384 {
3385         size_t i;
3386         int ret;
3387         char *pos, *end;
3388         const u8 *ie, *ie2;
3389
3390         pos = buf;
3391         end = buf + buflen;
3392
3393         if (mask & WPA_BSS_MASK_ID) {
3394                 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id);
3395                 if (ret < 0 || ret >= end - pos)
3396                         return 0;
3397                 pos += ret;
3398         }
3399
3400         if (mask & WPA_BSS_MASK_BSSID) {
3401                 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
3402                                   MAC2STR(bss->bssid));
3403                 if (ret < 0 || ret >= end - pos)
3404                         return 0;
3405                 pos += ret;
3406         }
3407
3408         if (mask & WPA_BSS_MASK_FREQ) {
3409                 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq);
3410                 if (ret < 0 || ret >= end - pos)
3411                         return 0;
3412                 pos += ret;
3413         }
3414
3415         if (mask & WPA_BSS_MASK_BEACON_INT) {
3416                 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n",
3417                                   bss->beacon_int);
3418                 if (ret < 0 || ret >= end - pos)
3419                         return 0;
3420                 pos += ret;
3421         }
3422
3423         if (mask & WPA_BSS_MASK_CAPABILITIES) {
3424                 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n",
3425                                   bss->caps);
3426                 if (ret < 0 || ret >= end - pos)
3427                         return 0;
3428                 pos += ret;
3429         }
3430
3431         if (mask & WPA_BSS_MASK_QUAL) {
3432                 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual);
3433                 if (ret < 0 || ret >= end - pos)
3434                         return 0;
3435                 pos += ret;
3436         }
3437
3438         if (mask & WPA_BSS_MASK_NOISE) {
3439                 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise);
3440                 if (ret < 0 || ret >= end - pos)
3441                         return 0;
3442                 pos += ret;
3443         }
3444
3445         if (mask & WPA_BSS_MASK_LEVEL) {
3446                 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level);
3447                 if (ret < 0 || ret >= end - pos)
3448                         return 0;
3449                 pos += ret;
3450         }
3451
3452         if (mask & WPA_BSS_MASK_TSF) {
3453                 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n",
3454                                   (unsigned long long) bss->tsf);
3455                 if (ret < 0 || ret >= end - pos)
3456                         return 0;
3457                 pos += ret;
3458         }
3459
3460         if (mask & WPA_BSS_MASK_AGE) {
3461                 struct os_reltime now;
3462
3463                 os_get_reltime(&now);
3464                 ret = os_snprintf(pos, end - pos, "age=%d\n",
3465                                   (int) (now.sec - bss->last_update.sec));
3466                 if (ret < 0 || ret >= end - pos)
3467                         return 0;
3468                 pos += ret;
3469         }
3470
3471         if (mask & WPA_BSS_MASK_IE) {
3472                 ret = os_snprintf(pos, end - pos, "ie=");
3473                 if (ret < 0 || ret >= end - pos)
3474                         return 0;
3475                 pos += ret;
3476
3477                 ie = (const u8 *) (bss + 1);
3478                 for (i = 0; i < bss->ie_len; i++) {
3479                         ret = os_snprintf(pos, end - pos, "%02x", *ie++);
3480                         if (ret < 0 || ret >= end - pos)
3481                                 return 0;
3482                         pos += ret;
3483                 }
3484
3485                 ret = os_snprintf(pos, end - pos, "\n");
3486                 if (ret < 0 || ret >= end - pos)
3487                         return 0;
3488                 pos += ret;
3489         }
3490
3491         if (mask & WPA_BSS_MASK_FLAGS) {
3492                 ret = os_snprintf(pos, end - pos, "flags=");
3493                 if (ret < 0 || ret >= end - pos)
3494                         return 0;
3495                 pos += ret;
3496
3497                 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
3498                 if (ie)
3499                         pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
3500                                                     2 + ie[1]);
3501                 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3502                 if (ie2)
3503                         pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
3504                                                     2 + ie2[1]);
3505                 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
3506                 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
3507                         ret = os_snprintf(pos, end - pos, "[WEP]");
3508                         if (ret < 0 || ret >= end - pos)
3509                                 return 0;
3510                         pos += ret;
3511                 }
3512                 if (bss->caps & IEEE80211_CAP_IBSS) {
3513                         ret = os_snprintf(pos, end - pos, "[IBSS]");
3514                         if (ret < 0 || ret >= end - pos)
3515                                 return 0;
3516                         pos += ret;
3517                 }
3518                 if (bss->caps & IEEE80211_CAP_ESS) {
3519                         ret = os_snprintf(pos, end - pos, "[ESS]");
3520                         if (ret < 0 || ret >= end - pos)
3521                                 return 0;
3522                         pos += ret;
3523                 }
3524                 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
3525                     wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
3526                         ret = os_snprintf(pos, end - pos, "[P2P]");
3527                         if (ret < 0 || ret >= end - pos)
3528                                 return 0;
3529                         pos += ret;
3530                 }
3531 #ifdef CONFIG_HS20
3532                 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
3533                         ret = os_snprintf(pos, end - pos, "[HS20]");
3534                         if (ret < 0 || ret >= end - pos)
3535                                 return 0;
3536                         pos += ret;
3537                 }
3538 #endif /* CONFIG_HS20 */
3539
3540                 ret = os_snprintf(pos, end - pos, "\n");
3541                 if (ret < 0 || ret >= end - pos)
3542                         return 0;
3543                 pos += ret;
3544         }
3545
3546         if (mask & WPA_BSS_MASK_SSID) {
3547                 ret = os_snprintf(pos, end - pos, "ssid=%s\n",
3548                                   wpa_ssid_txt(bss->ssid, bss->ssid_len));
3549                 if (ret < 0 || ret >= end - pos)
3550                         return 0;
3551                 pos += ret;
3552         }
3553
3554 #ifdef CONFIG_WPS
3555         if (mask & WPA_BSS_MASK_WPS_SCAN) {
3556                 ie = (const u8 *) (bss + 1);
3557                 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
3558                 if (ret < 0 || ret >= end - pos)
3559                         return 0;
3560                 pos += ret;
3561         }
3562 #endif /* CONFIG_WPS */
3563
3564 #ifdef CONFIG_P2P
3565         if (mask & WPA_BSS_MASK_P2P_SCAN) {
3566                 ie = (const u8 *) (bss + 1);
3567                 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
3568                 if (ret < 0 || ret >= end - pos)
3569                         return 0;
3570                 pos += ret;
3571         }
3572 #endif /* CONFIG_P2P */
3573
3574 #ifdef CONFIG_WIFI_DISPLAY
3575         if (mask & WPA_BSS_MASK_WIFI_DISPLAY) {
3576                 struct wpabuf *wfd;
3577                 ie = (const u8 *) (bss + 1);
3578                 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len,
3579                                                   WFD_IE_VENDOR_TYPE);
3580                 if (wfd) {
3581                         ret = os_snprintf(pos, end - pos, "wfd_subelems=");
3582                         if (ret < 0 || ret >= end - pos) {
3583                                 wpabuf_free(wfd);
3584                                 return 0;
3585                         }
3586                         pos += ret;
3587
3588                         pos += wpa_snprintf_hex(pos, end - pos,
3589                                                 wpabuf_head(wfd),
3590                                                 wpabuf_len(wfd));
3591                         wpabuf_free(wfd);
3592
3593                         ret = os_snprintf(pos, end - pos, "\n");
3594                         if (ret < 0 || ret >= end - pos)
3595                                 return 0;
3596                         pos += ret;
3597                 }
3598         }
3599 #endif /* CONFIG_WIFI_DISPLAY */
3600
3601 #ifdef CONFIG_INTERWORKING
3602         if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
3603                 struct wpa_bss_anqp *anqp = bss->anqp;
3604                 pos = anqp_add_hex(pos, end, "anqp_venue_name",
3605                                    anqp->venue_name);
3606                 pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
3607                                    anqp->network_auth_type);
3608                 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
3609                                    anqp->roaming_consortium);
3610                 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
3611                                    anqp->ip_addr_type_availability);
3612                 pos = anqp_add_hex(pos, end, "anqp_nai_realm",
3613                                    anqp->nai_realm);
3614                 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp);
3615                 pos = anqp_add_hex(pos, end, "anqp_domain_name",
3616                                    anqp->domain_name);
3617 #ifdef CONFIG_HS20
3618                 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name",
3619                                    anqp->hs20_operator_friendly_name);
3620                 pos = anqp_add_hex(pos, end, "hs20_wan_metrics",
3621                                    anqp->hs20_wan_metrics);
3622                 pos = anqp_add_hex(pos, end, "hs20_connection_capability",
3623                                    anqp->hs20_connection_capability);
3624                 pos = anqp_add_hex(pos, end, "hs20_operating_class",
3625                                    anqp->hs20_operating_class);
3626                 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
3627                                    anqp->hs20_osu_providers_list);
3628 #endif /* CONFIG_HS20 */
3629         }
3630 #endif /* CONFIG_INTERWORKING */
3631
3632         if (mask & WPA_BSS_MASK_DELIM) {
3633                 ret = os_snprintf(pos, end - pos, "====\n");
3634                 if (ret < 0 || ret >= end - pos)
3635                         return 0;
3636                 pos += ret;
3637         }
3638
3639         return pos - buf;
3640 }
3641
3642
3643 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
3644                                          const char *cmd, char *buf,
3645                                          size_t buflen)
3646 {
3647         u8 bssid[ETH_ALEN];
3648         size_t i;
3649         struct wpa_bss *bss;
3650         struct wpa_bss *bsslast = NULL;
3651         struct dl_list *next;
3652         int ret = 0;
3653         int len;
3654         char *ctmp;
3655         unsigned long mask = WPA_BSS_MASK_ALL;
3656
3657         if (os_strncmp(cmd, "RANGE=", 6) == 0) {
3658                 if (os_strncmp(cmd + 6, "ALL", 3) == 0) {
3659                         bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss,
3660                                             list_id);
3661                         bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss,
3662                                                list_id);
3663                 } else { /* N1-N2 */
3664                         unsigned int id1, id2;
3665
3666                         if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) {
3667                                 wpa_printf(MSG_INFO, "Wrong BSS range "
3668                                            "format");
3669                                 return 0;
3670                         }
3671
3672                         if (*(cmd + 6) == '-')
3673                                 id1 = 0;
3674                         else
3675                                 id1 = atoi(cmd + 6);
3676                         ctmp++;
3677                         if (*ctmp >= '0' && *ctmp <= '9')
3678                                 id2 = atoi(ctmp);
3679                         else
3680                                 id2 = (unsigned int) -1;
3681                         bss = wpa_bss_get_id_range(wpa_s, id1, id2);
3682                         if (id2 == (unsigned int) -1)
3683                                 bsslast = dl_list_last(&wpa_s->bss_id,
3684                                                        struct wpa_bss,
3685                                                        list_id);
3686                         else {
3687                                 bsslast = wpa_bss_get_id(wpa_s, id2);
3688                                 if (bsslast == NULL && bss && id2 > id1) {
3689                                         struct wpa_bss *tmp = bss;
3690                                         for (;;) {
3691                                                 next = tmp->list_id.next;
3692                                                 if (next == &wpa_s->bss_id)
3693                                                         break;
3694                                                 tmp = dl_list_entry(
3695                                                         next, struct wpa_bss,
3696                                                         list_id);
3697                                                 if (tmp->id > id2)
3698                                                         break;
3699                                                 bsslast = tmp;
3700                                         }
3701                                 }
3702                         }
3703                 }
3704         } else if (os_strncmp(cmd, "FIRST", 5) == 0)
3705                 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id);
3706         else if (os_strncmp(cmd, "LAST", 4) == 0)
3707                 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id);
3708         else if (os_strncmp(cmd, "ID-", 3) == 0) {
3709                 i = atoi(cmd + 3);
3710                 bss = wpa_bss_get_id(wpa_s, i);
3711         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
3712                 i = atoi(cmd + 5);
3713                 bss = wpa_bss_get_id(wpa_s, i);
3714                 if (bss) {
3715                         next = bss->list_id.next;
3716                         if (next == &wpa_s->bss_id)
3717                                 bss = NULL;
3718                         else
3719                                 bss = dl_list_entry(next, struct wpa_bss,
3720                                                     list_id);
3721                 }
3722 #ifdef CONFIG_P2P
3723         } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
3724                 if (hwaddr_aton(cmd + 13, bssid) == 0)
3725                         bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid);
3726                 else
3727                         bss = NULL;
3728 #endif /* CONFIG_P2P */
3729         } else if (hwaddr_aton(cmd, bssid) == 0)
3730                 bss = wpa_bss_get_bssid(wpa_s, bssid);
3731         else {
3732                 struct wpa_bss *tmp;
3733                 i = atoi(cmd);
3734                 bss = NULL;
3735                 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
3736                 {
3737                         if (i-- == 0) {
3738                                 bss = tmp;
3739                                 break;
3740                         }
3741                 }
3742         }
3743
3744         if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) {
3745                 mask = strtoul(ctmp + 5, NULL, 0x10);
3746                 if (mask == 0)
3747                         mask = WPA_BSS_MASK_ALL;
3748         }
3749
3750         if (bss == NULL)
3751                 return 0;
3752
3753         if (bsslast == NULL)
3754                 bsslast = bss;
3755         do {
3756                 len = print_bss_info(wpa_s, bss, mask, buf, buflen);
3757                 ret += len;
3758                 buf += len;
3759                 buflen -= len;
3760                 if (bss == bsslast) {
3761                         if ((mask & WPA_BSS_MASK_DELIM) && len &&
3762                             (bss == dl_list_last(&wpa_s->bss_id,
3763                                                  struct wpa_bss, list_id)))
3764                                 os_snprintf(buf - 5, 5, "####\n");
3765                         break;
3766                 }
3767                 next = bss->list_id.next;
3768                 if (next == &wpa_s->bss_id)
3769                         break;
3770                 bss = dl_list_entry(next, struct wpa_bss, list_id);
3771         } while (bss && len);
3772
3773         return ret;
3774 }
3775
3776
3777 static int wpa_supplicant_ctrl_iface_ap_scan(
3778         struct wpa_supplicant *wpa_s, char *cmd)
3779 {
3780         int ap_scan = atoi(cmd);
3781         return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
3782 }
3783
3784
3785 static int wpa_supplicant_ctrl_iface_scan_interval(
3786         struct wpa_supplicant *wpa_s, char *cmd)
3787 {
3788         int scan_int = atoi(cmd);
3789         return wpa_supplicant_set_scan_interval(wpa_s, scan_int);
3790 }
3791
3792
3793 static int wpa_supplicant_ctrl_iface_bss_expire_age(
3794         struct wpa_supplicant *wpa_s, char *cmd)
3795 {
3796         int expire_age = atoi(cmd);
3797         return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age);
3798 }
3799
3800
3801 static int wpa_supplicant_ctrl_iface_bss_expire_count(
3802         struct wpa_supplicant *wpa_s, char *cmd)
3803 {
3804         int expire_count = atoi(cmd);
3805         return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count);
3806 }
3807
3808
3809 static int wpa_supplicant_ctrl_iface_bss_flush(
3810         struct wpa_supplicant *wpa_s, char *cmd)
3811 {
3812         int flush_age = atoi(cmd);
3813
3814         if (flush_age == 0)
3815                 wpa_bss_flush(wpa_s);
3816         else
3817                 wpa_bss_flush_by_age(wpa_s, flush_age);
3818         return 0;
3819 }
3820
3821
3822 #ifdef CONFIG_TESTING_OPTIONS
3823 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
3824 {
3825         wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
3826         /* MLME-DELETEKEYS.request */
3827         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
3828         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
3829         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
3830         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
3831 #ifdef CONFIG_IEEE80211W
3832         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
3833         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
3834 #endif /* CONFIG_IEEE80211W */
3835
3836         wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
3837                         0);
3838         /* MLME-SETPROTECTION.request(None) */
3839         wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
3840                                    MLME_SETPROTECTION_PROTECT_TYPE_NONE,
3841                                    MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
3842         wpa_sm_drop_sa(wpa_s->wpa);
3843 }
3844 #endif /* CONFIG_TESTING_OPTIONS */
3845
3846
3847 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
3848                                           char *addr)
3849 {
3850 #ifdef CONFIG_NO_SCAN_PROCESSING
3851         return -1;
3852 #else /* CONFIG_NO_SCAN_PROCESSING */
3853         u8 bssid[ETH_ALEN];
3854         struct wpa_bss *bss;
3855         struct wpa_ssid *ssid = wpa_s->current_ssid;
3856
3857         if (hwaddr_aton(addr, bssid)) {
3858                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
3859                            "address '%s'", addr);
3860                 return -1;
3861         }
3862
3863         wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
3864
3865         if (!ssid) {
3866                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
3867                            "configuration known for the target AP");
3868                 return -1;
3869         }
3870
3871         bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
3872         if (!bss) {
3873                 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
3874                            "from BSS table");
3875                 return -1;
3876         }
3877
3878         /*
3879          * TODO: Find best network configuration block from configuration to
3880          * allow roaming to other networks
3881          */
3882
3883         wpa_s->reassociate = 1;
3884         wpa_supplicant_connect(wpa_s, bss, ssid);
3885
3886         return 0;
3887 #endif /* CONFIG_NO_SCAN_PROCESSING */
3888 }
3889
3890
3891 #ifdef CONFIG_P2P
3892 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
3893 {
3894         unsigned int timeout = atoi(cmd);
3895         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
3896         u8 dev_id[ETH_ALEN], *_dev_id = NULL;
3897         u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
3898         char *pos;
3899         unsigned int search_delay;
3900
3901         if (os_strstr(cmd, "type=social"))
3902                 type = P2P_FIND_ONLY_SOCIAL;
3903         else if (os_strstr(cmd, "type=progressive"))
3904                 type = P2P_FIND_PROGRESSIVE;
3905
3906         pos = os_strstr(cmd, "dev_id=");
3907         if (pos) {
3908                 pos += 7;
3909                 if (hwaddr_aton(pos, dev_id))
3910                         return -1;
3911                 _dev_id = dev_id;
3912         }
3913
3914         pos = os_strstr(cmd, "dev_type=");
3915         if (pos) {
3916                 pos += 9;
3917                 if (wps_dev_type_str2bin(pos, dev_type) < 0)
3918                         return -1;
3919                 _dev_type = dev_type;
3920         }
3921
3922         pos = os_strstr(cmd, "delay=");
3923         if (pos) {
3924                 pos += 6;
3925                 search_delay = atoi(pos);
3926         } else
3927                 search_delay = wpas_p2p_search_delay(wpa_s);
3928
3929         return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
3930                              _dev_id, search_delay);
3931 }
3932
3933
3934 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
3935                             char *buf, size_t buflen)
3936 {
3937         u8 addr[ETH_ALEN];
3938         char *pos, *pos2;
3939         char *pin = NULL;
3940         enum p2p_wps_method wps_method;
3941         int new_pin;
3942         int ret;
3943         int persistent_group, persistent_id = -1;
3944         int join;
3945         int auth;
3946         int automatic;
3947         int go_intent = -1;
3948         int freq = 0;
3949         int pd;
3950         int ht40, vht;
3951
3952         /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
3953          * [persistent|persistent=<network id>]
3954          * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
3955          * [ht40] [vht] */
3956
3957         if (hwaddr_aton(cmd, addr))
3958                 return -1;
3959
3960         pos = cmd + 17;
3961         if (*pos != ' ')
3962                 return -1;
3963         pos++;
3964
3965         persistent_group = os_strstr(pos, " persistent") != NULL;
3966         pos2 = os_strstr(pos, " persistent=");
3967         if (pos2) {
3968                 struct wpa_ssid *ssid;
3969                 persistent_id = atoi(pos2 + 12);
3970                 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
3971                 if (ssid == NULL || ssid->disabled != 2 ||
3972                     ssid->mode != WPAS_MODE_P2P_GO) {
3973                         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
3974                                    "SSID id=%d for persistent P2P group (GO)",
3975                                    persistent_id);
3976                         return -1;
3977                 }
3978         }
3979         join = os_strstr(pos, " join") != NULL;
3980         auth = os_strstr(pos, " auth") != NULL;
3981         automatic = os_strstr(pos, " auto") != NULL;
3982         pd = os_strstr(pos, " provdisc") != NULL;
3983         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
3984         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
3985                 vht;
3986
3987         pos2 = os_strstr(pos, " go_intent=");
3988         if (pos2) {
3989                 pos2 += 11;
3990                 go_intent = atoi(pos2);
3991                 if (go_intent < 0 || go_intent > 15)
3992                         return -1;
3993         }
3994
3995         pos2 = os_strstr(pos, " freq=");
3996         if (pos2) {
3997                 pos2 += 6;
3998                 freq = atoi(pos2);
3999                 if (freq <= 0)
4000                         return -1;
4001         }
4002
4003         if (os_strncmp(pos, "pin", 3) == 0) {
4004                 /* Request random PIN (to be displayed) and enable the PIN */
4005                 wps_method = WPS_PIN_DISPLAY;
4006         } else if (os_strncmp(pos, "pbc", 3) == 0) {
4007                 wps_method = WPS_PBC;
4008         } else {
4009                 pin = pos;
4010                 pos = os_strchr(pin, ' ');
4011                 wps_method = WPS_PIN_KEYPAD;
4012                 if (pos) {
4013                         *pos++ = '\0';
4014                         if (os_strncmp(pos, "display", 7) == 0)
4015                                 wps_method = WPS_PIN_DISPLAY;
4016                 }
4017                 if (!wps_pin_str_valid(pin)) {
4018                         os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
4019                         return 17;
4020                 }
4021         }
4022
4023         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
4024                                    persistent_group, automatic, join,
4025                                    auth, go_intent, freq, persistent_id, pd,
4026                                    ht40, vht);
4027         if (new_pin == -2) {
4028                 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
4029                 return 25;
4030         }
4031         if (new_pin == -3) {
4032                 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
4033                 return 25;
4034         }
4035         if (new_pin < 0)
4036                 return -1;
4037         if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
4038                 ret = os_snprintf(buf, buflen, "%08d", new_pin);
4039                 if (ret < 0 || (size_t) ret >= buflen)
4040                         return -1;
4041                 return ret;
4042         }
4043
4044         os_memcpy(buf, "OK\n", 3);
4045         return 3;
4046 }
4047
4048
4049 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd)
4050 {
4051         unsigned int timeout = atoi(cmd);
4052         return wpas_p2p_listen(wpa_s, timeout);
4053 }
4054
4055
4056 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
4057 {
4058         u8 addr[ETH_ALEN];
4059         char *pos;
4060         enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
4061
4062         /* <addr> <config method> [join|auto] */
4063
4064         if (hwaddr_aton(cmd, addr))
4065                 return -1;
4066
4067         pos = cmd + 17;
4068         if (*pos != ' ')
4069                 return -1;
4070         pos++;
4071
4072         if (os_strstr(pos, " join") != NULL)
4073                 use = WPAS_P2P_PD_FOR_JOIN;
4074         else if (os_strstr(pos, " auto") != NULL)
4075                 use = WPAS_P2P_PD_AUTO;
4076
4077         return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
4078 }
4079
4080
4081 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
4082                               size_t buflen)
4083 {
4084         struct wpa_ssid *ssid = wpa_s->current_ssid;
4085
4086         if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
4087             ssid->passphrase == NULL)
4088                 return -1;
4089
4090         os_strlcpy(buf, ssid->passphrase, buflen);
4091         return os_strlen(buf);
4092 }
4093
4094
4095 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
4096                                   char *buf, size_t buflen)
4097 {
4098         u64 ref;
4099         int res;
4100         u8 dst_buf[ETH_ALEN], *dst;
4101         struct wpabuf *tlvs;
4102         char *pos;
4103         size_t len;
4104
4105         if (hwaddr_aton(cmd, dst_buf))
4106                 return -1;
4107         dst = dst_buf;
4108         if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
4109             dst[3] == 0 && dst[4] == 0 && dst[5] == 0)
4110                 dst = NULL;
4111         pos = cmd + 17;
4112         if (*pos != ' ')
4113                 return -1;
4114         pos++;
4115
4116         if (os_strncmp(pos, "upnp ", 5) == 0) {
4117                 u8 version;
4118                 pos += 5;
4119                 if (hexstr2bin(pos, &version, 1) < 0)
4120                         return -1;
4121                 pos += 2;
4122                 if (*pos != ' ')
4123                         return -1;
4124                 pos++;
4125                 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
4126 #ifdef CONFIG_WIFI_DISPLAY
4127         } else if (os_strncmp(pos, "wifi-display ", 13) == 0) {
4128                 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13);
4129 #endif /* CONFIG_WIFI_DISPLAY */
4130         } else {
4131                 len = os_strlen(pos);
4132                 if (len & 1)
4133                         return -1;
4134                 len /= 2;
4135                 tlvs = wpabuf_alloc(len);
4136                 if (tlvs == NULL)
4137                         return -1;
4138                 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) {
4139                         wpabuf_free(tlvs);
4140                         return -1;
4141                 }
4142
4143                 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
4144                 wpabuf_free(tlvs);
4145         }
4146         if (ref == 0)
4147                 return -1;
4148         res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
4149         if (res < 0 || (unsigned) res >= buflen)
4150                 return -1;
4151         return res;
4152 }
4153
4154
4155 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s,
4156                                          char *cmd)
4157 {
4158         long long unsigned val;
4159         u64 req;
4160         if (sscanf(cmd, "%llx", &val) != 1)
4161                 return -1;
4162         req = val;
4163         return wpas_p2p_sd_cancel_request(wpa_s, req);
4164 }
4165
4166
4167 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd)
4168 {
4169         int freq;
4170         u8 dst[ETH_ALEN];
4171         u8 dialog_token;
4172         struct wpabuf *resp_tlvs;
4173         char *pos, *pos2;
4174         size_t len;
4175
4176         pos = os_strchr(cmd, ' ');
4177         if (pos == NULL)
4178                 return -1;
4179         *pos++ = '\0';
4180         freq = atoi(cmd);
4181         if (freq == 0)
4182                 return -1;
4183
4184         if (hwaddr_aton(pos, dst))
4185                 return -1;
4186         pos += 17;
4187         if (*pos != ' ')
4188                 return -1;
4189         pos++;
4190
4191         pos2 = os_strchr(pos, ' ');
4192         if (pos2 == NULL)
4193                 return -1;
4194         *pos2++ = '\0';
4195         dialog_token = atoi(pos);
4196
4197         len = os_strlen(pos2);
4198         if (len & 1)
4199                 return -1;
4200         len /= 2;
4201         resp_tlvs = wpabuf_alloc(len);
4202         if (resp_tlvs == NULL)
4203                 return -1;
4204         if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) {
4205                 wpabuf_free(resp_tlvs);
4206                 return -1;
4207         }
4208
4209         wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs);
4210         wpabuf_free(resp_tlvs);
4211         return 0;
4212 }
4213
4214
4215 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s,
4216                                        char *cmd)
4217 {
4218         if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1"))
4219                 return -1;
4220         wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd);
4221         return 0;
4222 }
4223
4224
4225 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s,
4226                                         char *cmd)
4227 {
4228         char *pos;
4229         size_t len;
4230         struct wpabuf *query, *resp;
4231
4232         pos = os_strchr(cmd, ' ');
4233         if (pos == NULL)
4234                 return -1;
4235         *pos++ = '\0';
4236
4237         len = os_strlen(cmd);
4238         if (len & 1)
4239                 return -1;
4240         len /= 2;
4241         query = wpabuf_alloc(len);
4242         if (query == NULL)
4243                 return -1;
4244         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4245                 wpabuf_free(query);
4246                 return -1;
4247         }
4248
4249         len = os_strlen(pos);
4250         if (len & 1) {
4251                 wpabuf_free(query);
4252                 return -1;
4253         }
4254         len /= 2;
4255         resp = wpabuf_alloc(len);
4256         if (resp == NULL) {
4257                 wpabuf_free(query);
4258                 return -1;
4259         }
4260         if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) {
4261                 wpabuf_free(query);
4262                 wpabuf_free(resp);
4263                 return -1;
4264         }
4265
4266         if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
4267                 wpabuf_free(query);
4268                 wpabuf_free(resp);
4269                 return -1;
4270         }
4271         return 0;
4272 }
4273
4274
4275 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4276 {
4277         char *pos;
4278         u8 version;
4279
4280         pos = os_strchr(cmd, ' ');
4281         if (pos == NULL)
4282                 return -1;
4283         *pos++ = '\0';
4284
4285         if (hexstr2bin(cmd, &version, 1) < 0)
4286                 return -1;
4287
4288         return wpas_p2p_service_add_upnp(wpa_s, version, pos);
4289 }
4290
4291
4292 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
4293 {
4294         char *pos;
4295
4296         pos = os_strchr(cmd, ' ');
4297         if (pos == NULL)
4298                 return -1;
4299         *pos++ = '\0';
4300
4301         if (os_strcmp(cmd, "bonjour") == 0)
4302                 return p2p_ctrl_service_add_bonjour(wpa_s, pos);
4303         if (os_strcmp(cmd, "upnp") == 0)
4304                 return p2p_ctrl_service_add_upnp(wpa_s, pos);
4305         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4306         return -1;
4307 }
4308
4309
4310 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s,
4311                                         char *cmd)
4312 {
4313         size_t len;
4314         struct wpabuf *query;
4315         int ret;
4316
4317         len = os_strlen(cmd);
4318         if (len & 1)
4319                 return -1;
4320         len /= 2;
4321         query = wpabuf_alloc(len);
4322         if (query == NULL)
4323                 return -1;
4324         if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) {
4325                 wpabuf_free(query);
4326                 return -1;
4327         }
4328
4329         ret = wpas_p2p_service_del_bonjour(wpa_s, query);
4330         wpabuf_free(query);
4331         return ret;
4332 }
4333
4334
4335 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
4336 {
4337         char *pos;
4338         u8 version;
4339
4340         pos = os_strchr(cmd, ' ');
4341         if (pos == NULL)
4342                 return -1;
4343         *pos++ = '\0';
4344
4345         if (hexstr2bin(cmd, &version, 1) < 0)
4346                 return -1;
4347
4348         return wpas_p2p_service_del_upnp(wpa_s, version, pos);
4349 }
4350
4351
4352 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
4353 {
4354         char *pos;
4355
4356         pos = os_strchr(cmd, ' ');
4357         if (pos == NULL)
4358                 return -1;
4359         *pos++ = '\0';
4360
4361         if (os_strcmp(cmd, "bonjour") == 0)
4362                 return p2p_ctrl_service_del_bonjour(wpa_s, pos);
4363         if (os_strcmp(cmd, "upnp") == 0)
4364                 return p2p_ctrl_service_del_upnp(wpa_s, pos);
4365         wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
4366         return -1;
4367 }
4368
4369
4370 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd)
4371 {
4372         u8 addr[ETH_ALEN];
4373
4374         /* <addr> */
4375
4376         if (hwaddr_aton(cmd, addr))
4377                 return -1;
4378
4379         return wpas_p2p_reject(wpa_s, addr);
4380 }
4381
4382
4383 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
4384 {
4385         char *pos;
4386         int id;
4387         struct wpa_ssid *ssid;
4388         u8 *_peer = NULL, peer[ETH_ALEN];
4389         int freq = 0, pref_freq = 0;
4390         int ht40, vht;
4391
4392         id = atoi(cmd);
4393         pos = os_strstr(cmd, " peer=");
4394         if (pos) {
4395                 pos += 6;
4396                 if (hwaddr_aton(pos, peer))
4397                         return -1;
4398                 _peer = peer;
4399         }
4400         ssid = wpa_config_get_network(wpa_s->conf, id);
4401         if (ssid == NULL || ssid->disabled != 2) {
4402                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4403                            "for persistent P2P group",
4404                            id);
4405                 return -1;
4406         }
4407
4408         pos = os_strstr(cmd, " freq=");
4409         if (pos) {
4410                 pos += 6;
4411                 freq = atoi(pos);
4412                 if (freq <= 0)
4413                         return -1;
4414         }
4415
4416         pos = os_strstr(cmd, " pref=");
4417         if (pos) {
4418                 pos += 6;
4419                 pref_freq = atoi(pos);
4420                 if (pref_freq <= 0)
4421                         return -1;
4422         }
4423
4424         vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht;
4425         ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4426                 vht;
4427
4428         return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
4429                                pref_freq);
4430 }
4431
4432
4433 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd)
4434 {
4435         char *pos;
4436         u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
4437
4438         pos = os_strstr(cmd, " peer=");
4439         if (!pos)
4440                 return -1;
4441
4442         *pos = '\0';
4443         pos += 6;
4444         if (hwaddr_aton(pos, peer)) {
4445                 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos);
4446                 return -1;
4447         }
4448
4449         pos = os_strstr(pos, " go_dev_addr=");
4450         if (pos) {
4451                 pos += 13;
4452                 if (hwaddr_aton(pos, go_dev_addr)) {
4453                         wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'",
4454                                    pos);
4455                         return -1;
4456                 }
4457                 go_dev = go_dev_addr;
4458         }
4459
4460         return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
4461 }
4462
4463
4464 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
4465 {
4466         if (os_strncmp(cmd, "persistent=", 11) == 0)
4467                 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11);
4468         if (os_strncmp(cmd, "group=", 6) == 0)
4469                 return p2p_ctrl_invite_group(wpa_s, cmd + 6);
4470
4471         return -1;
4472 }
4473
4474
4475 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
4476                                          char *cmd, int freq, int ht40,
4477                                          int vht)
4478 {
4479         int id;
4480         struct wpa_ssid *ssid;
4481
4482         id = atoi(cmd);
4483         ssid = wpa_config_get_network(wpa_s->conf, id);
4484         if (ssid == NULL || ssid->disabled != 2) {
4485                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
4486                            "for persistent P2P group",
4487                            id);
4488                 return -1;
4489         }
4490
4491         return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
4492                                              NULL, 0);
4493 }
4494
4495
4496 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
4497 {
4498         int freq = 0, ht40, vht;
4499         char *pos;
4500
4501         pos = os_strstr(cmd, "freq=");
4502         if (pos)
4503                 freq = atoi(pos + 5);
4504
4505         vht = (os_strstr(cmd, "vht") != NULL) || wpa_s->conf->p2p_go_vht;
4506         ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
4507                 vht;
4508
4509         if (os_strncmp(cmd, "persistent=", 11) == 0)
4510                 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq,
4511                                                      ht40, vht);
4512         if (os_strcmp(cmd, "persistent") == 0 ||
4513             os_strncmp(cmd, "persistent ", 11) == 0)
4514                 return wpas_p2p_group_add(wpa_s, 1, freq, ht40, vht);
4515         if (os_strncmp(cmd, "freq=", 5) == 0)
4516                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
4517         if (ht40)
4518                 return wpas_p2p_group_add(wpa_s, 0, freq, ht40, vht);
4519
4520         wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'",
4521                    cmd);
4522         return -1;
4523 }
4524
4525
4526 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
4527                          char *buf, size_t buflen)
4528 {
4529         u8 addr[ETH_ALEN], *addr_ptr;
4530         int next, res;
4531         const struct p2p_peer_info *info;
4532         char *pos, *end;
4533         char devtype[WPS_DEV_TYPE_BUFSIZE];
4534         struct wpa_ssid *ssid;
4535         size_t i;
4536
4537         if (!wpa_s->global->p2p)
4538                 return -1;
4539
4540         if (os_strcmp(cmd, "FIRST") == 0) {
4541                 addr_ptr = NULL;
4542                 next = 0;
4543         } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
4544                 if (hwaddr_aton(cmd + 5, addr) < 0)
4545                         return -1;
4546                 addr_ptr = addr;
4547                 next = 1;
4548         } else {
4549                 if (hwaddr_aton(cmd, addr) < 0)
4550                         return -1;
4551                 addr_ptr = addr;
4552                 next = 0;
4553         }
4554
4555         info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next);
4556         if (info == NULL)
4557                 return -1;
4558
4559         pos = buf;
4560         end = buf + buflen;
4561
4562         res = os_snprintf(pos, end - pos, MACSTR "\n"
4563                           "pri_dev_type=%s\n"
4564                           "device_name=%s\n"
4565                           "manufacturer=%s\n"
4566                           "model_name=%s\n"
4567                           "model_number=%s\n"
4568                           "serial_number=%s\n"
4569                           "config_methods=0x%x\n"
4570                           "dev_capab=0x%x\n"
4571                           "group_capab=0x%x\n"
4572                           "level=%d\n",
4573                           MAC2STR(info->p2p_device_addr),
4574                           wps_dev_type_bin2str(info->pri_dev_type,
4575                                                devtype, sizeof(devtype)),
4576                           info->device_name,
4577                           info->manufacturer,
4578                           info->model_name,
4579                           info->model_number,
4580                           info->serial_number,
4581                           info->config_methods,
4582                           info->dev_capab,
4583                           info->group_capab,
4584                           info->level);
4585         if (res < 0 || res >= end - pos)
4586                 return pos - buf;
4587         pos += res;
4588
4589         for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++)
4590         {
4591                 const u8 *t;
4592                 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN];
4593                 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n",
4594                                   wps_dev_type_bin2str(t, devtype,
4595                                                        sizeof(devtype)));
4596                 if (res < 0 || res >= end - pos)
4597                         return pos - buf;
4598                 pos += res;
4599         }
4600
4601         ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0);
4602         if (ssid) {
4603                 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id);
4604                 if (res < 0 || res >= end - pos)
4605                         return pos - buf;
4606                 pos += res;
4607         }
4608
4609         res = p2p_get_peer_info_txt(info, pos, end - pos);
4610         if (res < 0)
4611                 return pos - buf;
4612         pos += res;
4613
4614         return pos - buf;
4615 }
4616
4617
4618 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s,
4619                                   const char *param)
4620 {
4621         unsigned int i;
4622
4623         if (wpa_s->global->p2p == NULL)
4624                 return -1;
4625
4626         if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0)
4627                 return -1;
4628
4629         for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) {
4630                 struct wpa_freq_range *freq;
4631                 freq = &wpa_s->global->p2p_disallow_freq.range[i];
4632                 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u",
4633                            freq->min, freq->max);
4634         }
4635
4636         wpas_p2p_update_channel_list(wpa_s);
4637         return 0;
4638 }
4639
4640
4641 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
4642 {
4643         char *param;
4644
4645         if (wpa_s->global->p2p == NULL)
4646                 return -1;
4647
4648         param = os_strchr(cmd, ' ');
4649         if (param == NULL)
4650                 return -1;
4651         *param++ = '\0';
4652
4653         if (os_strcmp(cmd, "discoverability") == 0) {
4654                 p2p_set_client_discoverability(wpa_s->global->p2p,
4655                                                atoi(param));
4656                 return 0;
4657         }
4658
4659         if (os_strcmp(cmd, "managed") == 0) {
4660                 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param));
4661                 return 0;
4662         }
4663
4664         if (os_strcmp(cmd, "listen_channel") == 0) {
4665                 return p2p_set_listen_channel(wpa_s->global->p2p, 81,
4666                                               atoi(param));
4667         }
4668
4669         if (os_strcmp(cmd, "ssid_postfix") == 0) {
4670                 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param,
4671                                             os_strlen(param));
4672         }
4673
4674         if (os_strcmp(cmd, "noa") == 0) {
4675                 char *pos;
4676                 int count, start, duration;
4677                 /* GO NoA parameters: count,start_offset(ms),duration(ms) */
4678                 count = atoi(param);
4679                 pos = os_strchr(param, ',');
4680                 if (pos == NULL)
4681                         return -1;
4682                 pos++;
4683                 start = atoi(pos);
4684                 pos = os_strchr(pos, ',');
4685                 if (pos == NULL)
4686                         return -1;
4687                 pos++;
4688                 duration = atoi(pos);
4689                 if (count < 0 || count > 255 || start < 0 || duration < 0)
4690                         return -1;
4691                 if (count == 0 && duration > 0)
4692                         return -1;
4693                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
4694                            "start=%d duration=%d", count, start, duration);
4695                 return wpas_p2p_set_noa(wpa_s, count, start, duration);
4696         }
4697
4698         if (os_strcmp(cmd, "ps") == 0)
4699                 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1);
4700
4701         if (os_strcmp(cmd, "oppps") == 0)
4702                 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1);
4703
4704         if (os_strcmp(cmd, "ctwindow") == 0)
4705                 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param));
4706
4707         if (os_strcmp(cmd, "disabled") == 0) {
4708                 wpa_s->global->p2p_disabled = atoi(param);
4709                 wpa_printf(MSG_DEBUG, "P2P functionality %s",
4710                            wpa_s->global->p2p_disabled ?
4711                            "disabled" : "enabled");
4712                 if (wpa_s->global->p2p_disabled) {
4713                         wpas_p2p_stop_find(wpa_s);
4714                         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4715                         p2p_flush(wpa_s->global->p2p);
4716                 }
4717                 return 0;
4718         }
4719
4720         if (os_strcmp(cmd, "conc_pref") == 0) {
4721                 if (os_strcmp(param, "sta") == 0)
4722                         wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
4723                 else if (os_strcmp(param, "p2p") == 0)
4724                         wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
4725                 else {
4726                         wpa_printf(MSG_INFO, "Invalid conc_pref value");
4727                         return -1;
4728                 }
4729                 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
4730                            "%s", param);
4731                 return 0;
4732         }
4733
4734         if (os_strcmp(cmd, "force_long_sd") == 0) {
4735                 wpa_s->force_long_sd = atoi(param);
4736                 return 0;
4737         }
4738
4739         if (os_strcmp(cmd, "peer_filter") == 0) {
4740                 u8 addr[ETH_ALEN];
4741                 if (hwaddr_aton(param, addr))
4742                         return -1;
4743                 p2p_set_peer_filter(wpa_s->global->p2p, addr);
4744                 return 0;
4745         }
4746
4747         if (os_strcmp(cmd, "cross_connect") == 0)
4748                 return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
4749
4750         if (os_strcmp(cmd, "go_apsd") == 0) {
4751                 if (os_strcmp(param, "disable") == 0)
4752                         wpa_s->set_ap_uapsd = 0;
4753                 else {
4754                         wpa_s->set_ap_uapsd = 1;
4755                         wpa_s->ap_uapsd = atoi(param);
4756                 }
4757                 return 0;
4758         }
4759
4760         if (os_strcmp(cmd, "client_apsd") == 0) {
4761                 if (os_strcmp(param, "disable") == 0)
4762                         wpa_s->set_sta_uapsd = 0;
4763                 else {
4764                         int be, bk, vi, vo;
4765                         char *pos;
4766                         /* format: BE,BK,VI,VO;max SP Length */
4767                         be = atoi(param);
4768                         pos = os_strchr(param, ',');
4769                         if (pos == NULL)
4770                                 return -1;
4771                         pos++;
4772                         bk = atoi(pos);
4773                         pos = os_strchr(pos, ',');
4774                         if (pos == NULL)
4775                                 return -1;
4776                         pos++;
4777                         vi = atoi(pos);
4778                         pos = os_strchr(pos, ',');
4779                         if (pos == NULL)
4780                                 return -1;
4781                         pos++;
4782                         vo = atoi(pos);
4783                         /* ignore max SP Length for now */
4784
4785                         wpa_s->set_sta_uapsd = 1;
4786                         wpa_s->sta_uapsd = 0;
4787                         if (be)
4788                                 wpa_s->sta_uapsd |= BIT(0);
4789                         if (bk)
4790                                 wpa_s->sta_uapsd |= BIT(1);
4791                         if (vi)
4792                                 wpa_s->sta_uapsd |= BIT(2);
4793                         if (vo)
4794                                 wpa_s->sta_uapsd |= BIT(3);
4795                 }
4796                 return 0;
4797         }
4798
4799         if (os_strcmp(cmd, "disallow_freq") == 0)
4800                 return p2p_ctrl_disallow_freq(wpa_s, param);
4801
4802         if (os_strcmp(cmd, "disc_int") == 0) {
4803                 int min_disc_int, max_disc_int, max_disc_tu;
4804                 char *pos;
4805
4806                 pos = param;
4807
4808                 min_disc_int = atoi(pos);
4809                 pos = os_strchr(pos, ' ');
4810                 if (pos == NULL)
4811                         return -1;
4812                 *pos++ = '\0';
4813
4814                 max_disc_int = atoi(pos);
4815                 pos = os_strchr(pos, ' ');
4816                 if (pos == NULL)
4817                         return -1;
4818                 *pos++ = '\0';
4819
4820                 max_disc_tu = atoi(pos);
4821
4822                 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
4823                                         max_disc_int, max_disc_tu);
4824         }
4825
4826         if (os_strcmp(cmd, "per_sta_psk") == 0) {
4827                 wpa_s->global->p2p_per_sta_psk = !!atoi(param);
4828                 return 0;
4829         }
4830
4831 #ifdef CONFIG_WPS_NFC
4832         if (os_strcmp(cmd, "nfc_tag") == 0)
4833                 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param));
4834 #endif /* CONFIG_WPS_NFC */
4835
4836         if (os_strcmp(cmd, "disable_ip_addr_req") == 0) {
4837                 wpa_s->p2p_disable_ip_addr_req = !!atoi(param);
4838                 return 0;
4839         }
4840
4841         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
4842                    cmd);
4843
4844         return -1;
4845 }
4846
4847
4848 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s)
4849 {
4850         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
4851         wpa_s->force_long_sd = 0;
4852         if (wpa_s->global->p2p)
4853                 p2p_flush(wpa_s->global->p2p);
4854 }
4855
4856
4857 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd)
4858 {
4859         char *pos, *pos2;
4860         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
4861
4862         if (cmd[0]) {
4863                 pos = os_strchr(cmd, ' ');
4864                 if (pos == NULL)
4865                         return -1;
4866                 *pos++ = '\0';
4867                 dur1 = atoi(cmd);
4868
4869                 pos2 = os_strchr(pos, ' ');
4870                 if (pos2)
4871                         *pos2++ = '\0';
4872                 int1 = atoi(pos);
4873         } else
4874                 pos2 = NULL;
4875
4876         if (pos2) {
4877                 pos = os_strchr(pos2, ' ');
4878                 if (pos == NULL)
4879                         return -1;
4880                 *pos++ = '\0';
4881                 dur2 = atoi(pos2);
4882                 int2 = atoi(pos);
4883         }
4884
4885         return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2);
4886 }
4887
4888
4889 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd)
4890 {
4891         char *pos;
4892         unsigned int period = 0, interval = 0;
4893
4894         if (cmd[0]) {
4895                 pos = os_strchr(cmd, ' ');
4896                 if (pos == NULL)
4897                         return -1;
4898                 *pos++ = '\0';
4899                 period = atoi(cmd);
4900                 interval = atoi(pos);
4901         }
4902
4903         return wpas_p2p_ext_listen(wpa_s, period, interval);
4904 }
4905
4906
4907 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd)
4908 {
4909         const char *pos;
4910         u8 peer[ETH_ALEN];
4911         int iface_addr = 0;
4912
4913         pos = cmd;
4914         if (os_strncmp(pos, "iface=", 6) == 0) {
4915                 iface_addr = 1;
4916                 pos += 6;
4917         }
4918         if (hwaddr_aton(pos, peer))
4919                 return -1;
4920
4921         wpas_p2p_remove_client(wpa_s, peer, iface_addr);
4922         return 0;
4923 }
4924
4925 #endif /* CONFIG_P2P */
4926
4927
4928 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
4929 {
4930         struct wpa_freq_range_list ranges;
4931         int *freqs = NULL;
4932         struct hostapd_hw_modes *mode;
4933         u16 i;
4934
4935         if (wpa_s->hw.modes == NULL)
4936                 return NULL;
4937
4938         os_memset(&ranges, 0, sizeof(ranges));
4939         if (freq_range_list_parse(&ranges, val) < 0)
4940                 return NULL;
4941
4942         for (i = 0; i < wpa_s->hw.num_modes; i++) {
4943                 int j;
4944
4945                 mode = &wpa_s->hw.modes[i];
4946                 for (j = 0; j < mode->num_channels; j++) {
4947                         unsigned int freq;
4948
4949                         if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
4950                                 continue;
4951
4952                         freq = mode->channels[j].freq;
4953                         if (!freq_range_list_includes(&ranges, freq))
4954                                 continue;
4955
4956                         int_array_add_unique(&freqs, freq);
4957                 }
4958         }
4959
4960         os_free(ranges.range);
4961         return freqs;
4962 }
4963
4964
4965 #ifdef CONFIG_INTERWORKING
4966
4967 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
4968 {
4969         int auto_sel = 0;
4970         int *freqs = NULL;
4971
4972         if (param) {
4973                 char *pos;
4974
4975                 auto_sel = os_strstr(param, "auto") != NULL;
4976
4977                 pos = os_strstr(param, "freq=");
4978                 if (pos) {
4979                         freqs = freq_range_to_channel_list(wpa_s, pos + 5);
4980                         if (freqs == NULL)
4981                                 return -1;
4982                 }
4983
4984         }
4985
4986         return interworking_select(wpa_s, auto_sel, freqs);
4987 }
4988
4989
4990 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
4991 {
4992         u8 bssid[ETH_ALEN];
4993         struct wpa_bss *bss;
4994
4995         if (hwaddr_aton(dst, bssid)) {
4996                 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
4997                 return -1;
4998         }
4999
5000         bss = wpa_bss_get_bssid(wpa_s, bssid);
5001         if (bss == NULL) {
5002                 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
5003                            MAC2STR(bssid));
5004                 return -1;
5005         }
5006
5007         return interworking_connect(wpa_s, bss);
5008 }
5009
5010
5011 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
5012 {
5013         u8 dst_addr[ETH_ALEN];
5014         int used;
5015         char *pos;
5016 #define MAX_ANQP_INFO_ID 100
5017         u16 id[MAX_ANQP_INFO_ID];
5018         size_t num_id = 0;
5019         u32 subtypes = 0;
5020
5021         used = hwaddr_aton2(dst, dst_addr);
5022         if (used < 0)
5023                 return -1;
5024         pos = dst + used;
5025         while (num_id < MAX_ANQP_INFO_ID) {
5026                 if (os_strncmp(pos, "hs20:", 5) == 0) {
5027 #ifdef CONFIG_HS20
5028                         int num = atoi(pos + 5);
5029                         if (num <= 0 || num > 31)
5030                                 return -1;
5031                         subtypes |= BIT(num);
5032 #else /* CONFIG_HS20 */
5033                         return -1;
5034 #endif /* CONFIG_HS20 */
5035                 } else {
5036                         id[num_id] = atoi(pos);
5037                         if (id[num_id])
5038                                 num_id++;
5039                 }
5040                 pos = os_strchr(pos + 1, ',');
5041                 if (pos == NULL)
5042                         break;
5043                 pos++;
5044         }
5045
5046         if (num_id == 0)
5047                 return -1;
5048
5049         return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
5050 }
5051
5052
5053 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd)
5054 {
5055         u8 dst_addr[ETH_ALEN];
5056         struct wpabuf *advproto, *query = NULL;
5057         int used, ret = -1;
5058         char *pos, *end;
5059         size_t len;
5060
5061         used = hwaddr_aton2(cmd, dst_addr);
5062         if (used < 0)
5063                 return -1;
5064
5065         pos = cmd + used;
5066         while (*pos == ' ')
5067                 pos++;
5068
5069         /* Advertisement Protocol ID */
5070         end = os_strchr(pos, ' ');
5071         if (end)
5072                 len = end - pos;
5073         else
5074                 len = os_strlen(pos);
5075         if (len & 0x01)
5076                 return -1;
5077         len /= 2;
5078         if (len == 0)
5079                 return -1;
5080         advproto = wpabuf_alloc(len);
5081         if (advproto == NULL)
5082                 return -1;
5083         if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0)
5084                 goto fail;
5085
5086         if (end) {
5087                 /* Optional Query Request */
5088                 pos = end + 1;
5089                 while (*pos == ' ')
5090                         pos++;
5091
5092                 len = os_strlen(pos);
5093                 if (len) {
5094                         if (len & 0x01)
5095                                 goto fail;
5096                         len /= 2;
5097                         if (len == 0)
5098                                 goto fail;
5099                         query = wpabuf_alloc(len);
5100                         if (query == NULL)
5101                                 goto fail;
5102                         if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0)
5103                                 goto fail;
5104                 }
5105         }
5106
5107         ret = gas_send_request(wpa_s, dst_addr, advproto, query);
5108
5109 fail:
5110         wpabuf_free(advproto);
5111         wpabuf_free(query);
5112
5113         return ret;
5114 }
5115
5116
5117 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf,
5118                             size_t buflen)
5119 {
5120         u8 addr[ETH_ALEN];
5121         int dialog_token;
5122         int used;
5123         char *pos;
5124         size_t resp_len, start, requested_len;
5125         struct wpabuf *resp;
5126         int ret;
5127
5128         used = hwaddr_aton2(cmd, addr);
5129         if (used < 0)
5130                 return -1;
5131
5132         pos = cmd + used;
5133         while (*pos == ' ')
5134                 pos++;
5135         dialog_token = atoi(pos);
5136
5137         if (wpa_s->last_gas_resp &&
5138             os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
5139             dialog_token == wpa_s->last_gas_dialog_token)
5140                 resp = wpa_s->last_gas_resp;
5141         else if (wpa_s->prev_gas_resp &&
5142                  os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
5143                  dialog_token == wpa_s->prev_gas_dialog_token)
5144                 resp = wpa_s->prev_gas_resp;
5145         else
5146                 return -1;
5147
5148         resp_len = wpabuf_len(resp);
5149         start = 0;
5150         requested_len = resp_len;
5151
5152         pos = os_strchr(pos, ' ');
5153         if (pos) {
5154                 start = atoi(pos);
5155                 if (start > resp_len)
5156                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
5157                 pos = os_strchr(pos, ',');
5158                 if (pos == NULL)
5159                         return -1;
5160                 pos++;
5161                 requested_len = atoi(pos);
5162                 if (start + requested_len > resp_len)
5163                         return os_snprintf(buf, buflen, "FAIL-Invalid range");
5164         }
5165
5166         if (requested_len * 2 + 1 > buflen)
5167                 return os_snprintf(buf, buflen, "FAIL-Too long response");
5168
5169         ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
5170                                requested_len);
5171
5172         if (start + requested_len == resp_len) {
5173                 /*
5174                  * Free memory by dropping the response after it has been
5175                  * fetched.
5176                  */
5177                 if (resp == wpa_s->prev_gas_resp) {
5178                         wpabuf_free(wpa_s->prev_gas_resp);
5179                         wpa_s->prev_gas_resp = NULL;
5180                 } else {
5181                         wpabuf_free(wpa_s->last_gas_resp);
5182                         wpa_s->last_gas_resp = NULL;
5183                 }
5184         }
5185
5186         return ret;
5187 }
5188 #endif /* CONFIG_INTERWORKING */
5189
5190
5191 #ifdef CONFIG_HS20
5192
5193 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
5194 {
5195         u8 dst_addr[ETH_ALEN];
5196         int used;
5197         char *pos;
5198         u32 subtypes = 0;
5199
5200         used = hwaddr_aton2(dst, dst_addr);
5201         if (used < 0)
5202                 return -1;
5203         pos = dst + used;
5204         for (;;) {
5205                 int num = atoi(pos);
5206                 if (num <= 0 || num > 31)
5207                         return -1;
5208                 subtypes |= BIT(num);
5209                 pos = os_strchr(pos + 1, ',');
5210                 if (pos == NULL)
5211                         break;
5212                 pos++;
5213         }
5214
5215         if (subtypes == 0)
5216                 return -1;
5217
5218         return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
5219 }
5220
5221
5222 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
5223                                     const u8 *addr, const char *realm)
5224 {
5225         u8 *buf;
5226         size_t rlen, len;
5227         int ret;
5228
5229         rlen = os_strlen(realm);
5230         len = 3 + rlen;
5231         buf = os_malloc(len);
5232         if (buf == NULL)
5233                 return -1;
5234         buf[0] = 1; /* NAI Home Realm Count */
5235         buf[1] = 0; /* Formatted in accordance with RFC 4282 */
5236         buf[2] = rlen;
5237         os_memcpy(buf + 3, realm, rlen);
5238
5239         ret = hs20_anqp_send_req(wpa_s, addr,
5240                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
5241                                  buf, len);
5242
5243         os_free(buf);
5244
5245         return ret;
5246 }
5247
5248
5249 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
5250                                         char *dst)
5251 {
5252         struct wpa_cred *cred = wpa_s->conf->cred;
5253         u8 dst_addr[ETH_ALEN];
5254         int used;
5255         u8 *buf;
5256         size_t len;
5257         int ret;
5258
5259         used = hwaddr_aton2(dst, dst_addr);
5260         if (used < 0)
5261                 return -1;
5262
5263         while (dst[used] == ' ')
5264                 used++;
5265         if (os_strncmp(dst + used, "realm=", 6) == 0)
5266                 return hs20_nai_home_realm_list(wpa_s, dst_addr,
5267                                                 dst + used + 6);
5268
5269         len = os_strlen(dst + used);
5270
5271         if (len == 0 && cred && cred->realm)
5272                 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
5273
5274         if (len % 1)
5275                 return -1;
5276         len /= 2;
5277         buf = os_malloc(len);
5278         if (buf == NULL)
5279                 return -1;
5280         if (hexstr2bin(dst + used, buf, len) < 0) {
5281                 os_free(buf);
5282                 return -1;
5283         }
5284
5285         ret = hs20_anqp_send_req(wpa_s, dst_addr,
5286                                  BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
5287                                  buf, len);
5288         os_free(buf);
5289
5290         return ret;
5291 }
5292
5293
5294 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
5295 {
5296         u8 dst_addr[ETH_ALEN];
5297         int used;
5298         char *icon;
5299
5300         used = hwaddr_aton2(cmd, dst_addr);
5301         if (used < 0)
5302                 return -1;
5303
5304         while (cmd[used] == ' ')
5305                 used++;
5306         icon = &cmd[used];
5307
5308         wpa_s->fetch_osu_icon_in_progress = 0;
5309         return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
5310                                   (u8 *) icon, os_strlen(icon));
5311 }
5312
5313 #endif /* CONFIG_HS20 */
5314
5315
5316 static int wpa_supplicant_ctrl_iface_sta_autoconnect(
5317         struct wpa_supplicant *wpa_s, char *cmd)
5318 {
5319         wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0;
5320         return 0;
5321 }
5322
5323
5324 #ifdef CONFIG_AUTOSCAN
5325
5326 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s,
5327                                               char *cmd)
5328 {
5329         enum wpa_states state = wpa_s->wpa_state;
5330         char *new_params = NULL;
5331
5332         if (os_strlen(cmd) > 0) {
5333                 new_params = os_strdup(cmd);
5334                 if (new_params == NULL)
5335                         return -1;
5336         }
5337
5338         os_free(wpa_s->conf->autoscan);
5339         wpa_s->conf->autoscan = new_params;
5340
5341         if (wpa_s->conf->autoscan == NULL)
5342                 autoscan_deinit(wpa_s);
5343         else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
5344                 autoscan_init(wpa_s, 1);
5345         else if (state == WPA_SCANNING)
5346                 wpa_supplicant_reinit_autoscan(wpa_s);
5347
5348         return 0;
5349 }
5350
5351 #endif /* CONFIG_AUTOSCAN */
5352
5353
5354 #ifdef CONFIG_WNM
5355
5356 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
5357 {
5358         int enter;
5359         int intval = 0;
5360         char *pos;
5361         int ret;
5362         struct wpabuf *tfs_req = NULL;
5363
5364         if (os_strncmp(cmd, "enter", 5) == 0)
5365                 enter = 1;
5366         else if (os_strncmp(cmd, "exit", 4) == 0)
5367                 enter = 0;
5368         else
5369                 return -1;
5370
5371         pos = os_strstr(cmd, " interval=");
5372         if (pos)
5373                 intval = atoi(pos + 10);
5374
5375         pos = os_strstr(cmd, " tfs_req=");
5376         if (pos) {
5377                 char *end;
5378                 size_t len;
5379                 pos += 9;
5380                 end = os_strchr(pos, ' ');
5381                 if (end)
5382                         len = end - pos;
5383                 else
5384                         len = os_strlen(pos);
5385                 if (len & 1)
5386                         return -1;
5387                 len /= 2;
5388                 tfs_req = wpabuf_alloc(len);
5389                 if (tfs_req == NULL)
5390                         return -1;
5391                 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
5392                         wpabuf_free(tfs_req);
5393                         return -1;
5394                 }
5395         }
5396
5397         ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER :
5398                                            WNM_SLEEP_MODE_EXIT, intval,
5399                                            tfs_req);
5400         wpabuf_free(tfs_req);
5401
5402         return ret;
5403 }
5404
5405
5406 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
5407 {
5408         int query_reason;
5409
5410         query_reason = atoi(cmd);
5411
5412         wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
5413                    query_reason);
5414
5415         return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
5416 }
5417
5418 #endif /* CONFIG_WNM */
5419
5420
5421 /* Get string representation of channel width */
5422 static const char * channel_width_name(enum chan_width width)
5423 {
5424         switch (width) {
5425         case CHAN_WIDTH_20_NOHT:
5426                 return "20 MHz (no HT)";
5427         case CHAN_WIDTH_20:
5428                 return "20 MHz";
5429         case CHAN_WIDTH_40:
5430                 return "40 MHz";
5431         case CHAN_WIDTH_80:
5432                 return "80 MHz";
5433         case CHAN_WIDTH_80P80:
5434                 return "80+80 MHz";
5435         case CHAN_WIDTH_160:
5436                 return "160 MHz";
5437         default:
5438                 return "unknown";
5439         }
5440 }
5441
5442
5443 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf,
5444                                       size_t buflen)
5445 {
5446         struct wpa_signal_info si;
5447         int ret;
5448         char *pos, *end;
5449
5450         ret = wpa_drv_signal_poll(wpa_s, &si);
5451         if (ret)
5452                 return -1;
5453
5454         pos = buf;
5455         end = buf + buflen;
5456
5457         ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n"
5458                           "NOISE=%d\nFREQUENCY=%u\n",
5459                           si.current_signal, si.current_txrate / 1000,
5460                           si.current_noise, si.frequency);
5461         if (ret < 0 || ret > end - pos)
5462                 return -1;
5463         pos += ret;
5464
5465         if (si.chanwidth != CHAN_WIDTH_UNKNOWN) {
5466                 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n",
5467                                   channel_width_name(si.chanwidth));
5468                 if (ret < 0 || ret > end - pos)
5469                         return -1;
5470                 pos += ret;
5471         }
5472
5473         if (si.center_frq1 > 0 && si.center_frq2 > 0) {
5474                 ret = os_snprintf(pos, end - pos,
5475                                   "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n",
5476                                   si.center_frq1, si.center_frq2);
5477                 if (ret < 0 || ret > end - pos)
5478                         return -1;
5479                 pos += ret;
5480         }
5481
5482         if (si.avg_signal) {
5483                 ret = os_snprintf(pos, end - pos,
5484                                   "AVG_RSSI=%d\n", si.avg_signal);
5485                 if (ret < 0 || ret >= end - pos)
5486                         return -1;
5487                 pos += ret;
5488         }
5489
5490         return pos - buf;
5491 }
5492
5493
5494 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
5495                                       size_t buflen)
5496 {
5497         struct hostap_sta_driver_data sta;
5498         int ret;
5499
5500         ret = wpa_drv_pktcnt_poll(wpa_s, &sta);
5501         if (ret)
5502                 return -1;
5503
5504         ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n",
5505                           sta.tx_packets, sta.tx_retry_failed, sta.rx_packets);
5506         if (ret < 0 || (size_t) ret > buflen)
5507                 return -1;
5508         return ret;
5509 }
5510
5511
5512 #ifdef ANDROID
5513 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5514                                      char *buf, size_t buflen)
5515 {
5516         int ret;
5517
5518         ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen);
5519         if (ret == 0) {
5520                 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
5521                         struct p2p_data *p2p = wpa_s->global->p2p;
5522                         if (p2p) {
5523                                 char country[3];
5524                                 country[0] = cmd[8];
5525                                 country[1] = cmd[9];
5526                                 country[2] = 0x04;
5527                                 p2p_set_country(p2p, country);
5528                         }
5529                 }
5530                 ret = os_snprintf(buf, buflen, "%s\n", "OK");
5531         }
5532         return ret;
5533 }
5534 #endif /* ANDROID */
5535
5536
5537 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd,
5538                                      char *buf, size_t buflen)
5539 {
5540         int ret;
5541         char *pos;
5542         u8 *data = NULL;
5543         unsigned int vendor_id, subcmd;
5544         struct wpabuf *reply;
5545         size_t data_len = 0;
5546
5547         /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
5548         vendor_id = strtoul(cmd, &pos, 16);
5549         if (!isblank(*pos))
5550                 return -EINVAL;
5551
5552         subcmd = strtoul(pos, &pos, 10);
5553
5554         if (*pos != '\0') {
5555                 if (!isblank(*pos++))
5556                         return -EINVAL;
5557                 data_len = os_strlen(pos);
5558         }
5559
5560         if (data_len) {
5561                 data_len /= 2;
5562                 data = os_malloc(data_len);
5563                 if (!data)
5564                         return -ENOBUFS;
5565
5566                 if (hexstr2bin(pos, data, data_len)) {
5567                         wpa_printf(MSG_DEBUG,
5568                                    "Vendor command: wrong parameter format");
5569                         os_free(data);
5570                         return -EINVAL;
5571                 }
5572         }
5573
5574         reply = wpabuf_alloc((buflen - 1) / 2);
5575         if (!reply) {
5576                 os_free(data);
5577                 return -ENOBUFS;
5578         }
5579
5580         ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
5581                                  reply);
5582
5583         if (ret == 0)
5584                 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
5585                                        wpabuf_len(reply));
5586
5587         wpabuf_free(reply);
5588         os_free(data);
5589
5590         return ret;
5591 }
5592
5593
5594 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
5595 {
5596         wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
5597
5598 #ifdef CONFIG_P2P
5599         wpas_p2p_stop_find(wpa_s);
5600         p2p_ctrl_flush(wpa_s);
5601         wpas_p2p_group_remove(wpa_s, "*");
5602         wpas_p2p_service_flush(wpa_s);
5603         wpa_s->global->p2p_disabled = 0;
5604         wpa_s->global->p2p_per_sta_psk = 0;
5605         wpa_s->conf->num_sec_device_types = 0;
5606         wpa_s->p2p_disable_ip_addr_req = 0;
5607 #endif /* CONFIG_P2P */
5608
5609 #ifdef CONFIG_WPS_TESTING
5610         wps_version_number = 0x20;
5611         wps_testing_dummy_cred = 0;
5612         wps_corrupt_pkhash = 0;
5613 #endif /* CONFIG_WPS_TESTING */
5614 #ifdef CONFIG_WPS
5615         wpa_s->wps_fragment_size = 0;
5616         wpas_wps_cancel(wpa_s);
5617 #endif /* CONFIG_WPS */
5618         wpa_s->after_wps = 0;
5619         wpa_s->known_wps_freq = 0;
5620
5621 #ifdef CONFIG_TDLS
5622 #ifdef CONFIG_TDLS_TESTING
5623         extern unsigned int tdls_testing;
5624         tdls_testing = 0;
5625 #endif /* CONFIG_TDLS_TESTING */
5626         wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
5627         wpa_tdls_enable(wpa_s->wpa, 1);
5628 #endif /* CONFIG_TDLS */
5629
5630         eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
5631         wpa_supplicant_stop_countermeasures(wpa_s, NULL);
5632
5633         wpa_s->no_keep_alive = 0;
5634
5635         os_free(wpa_s->disallow_aps_bssid);
5636         wpa_s->disallow_aps_bssid = NULL;
5637         wpa_s->disallow_aps_bssid_count = 0;
5638         os_free(wpa_s->disallow_aps_ssid);
5639         wpa_s->disallow_aps_ssid = NULL;
5640         wpa_s->disallow_aps_ssid_count = 0;
5641
5642         wpa_s->set_sta_uapsd = 0;
5643         wpa_s->sta_uapsd = 0;
5644
5645         wpa_drv_radio_disable(wpa_s, 0);
5646
5647         wpa_bss_flush(wpa_s);
5648         wpa_blacklist_clear(wpa_s);
5649         wpa_s->extra_blacklist_count = 0;
5650         wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
5651         wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
5652         wpa_config_flush_blobs(wpa_s->conf);
5653         wpa_s->conf->auto_interworking = 0;
5654         wpa_s->conf->okc = 0;
5655
5656         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
5657         wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
5658         wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
5659         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
5660
5661         radio_remove_works(wpa_s, NULL, 1);
5662
5663         wpa_s->next_ssid = NULL;
5664
5665 #ifdef CONFIG_INTERWORKING
5666         hs20_cancel_fetch_osu(wpa_s);
5667 #endif /* CONFIG_INTERWORKING */
5668
5669         wpa_s->ext_mgmt_frame_handling = 0;
5670 }
5671
5672
5673 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
5674                                      char *buf, size_t buflen)
5675 {
5676         struct wpa_radio_work *work;
5677         char *pos, *end;
5678         struct os_reltime now, diff;
5679
5680         pos = buf;
5681         end = buf + buflen;
5682
5683         os_get_reltime(&now);
5684
5685         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
5686         {
5687                 int ret;
5688
5689                 os_reltime_sub(&now, &work->time, &diff);
5690                 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
5691                                   work->type, work->wpa_s->ifname, work->freq,
5692                                   work->started, diff.sec, diff.usec);
5693                 if (ret < 0 || ret >= end - pos)
5694                         break;
5695                 pos += ret;
5696         }
5697
5698         return pos - buf;
5699 }
5700
5701
5702 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
5703 {
5704         struct wpa_radio_work *work = eloop_ctx;
5705         struct wpa_external_work *ework = work->ctx;
5706
5707         wpa_dbg(work->wpa_s, MSG_DEBUG,
5708                 "Timing out external radio work %u (%s)",
5709                 ework->id, work->type);
5710         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
5711         os_free(ework);
5712         radio_work_done(work);
5713 }
5714
5715
5716 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
5717 {
5718         struct wpa_external_work *ework = work->ctx;
5719
5720         if (deinit) {
5721                 if (work->started)
5722                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
5723                                              work, NULL);
5724
5725                 os_free(ework);
5726                 return;
5727         }
5728
5729         wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
5730                 ework->id, ework->type);
5731         wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
5732         if (!ework->timeout)
5733                 ework->timeout = 10;
5734         eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
5735                                work, NULL);
5736 }
5737
5738
5739 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
5740                                     char *buf, size_t buflen)
5741 {
5742         struct wpa_external_work *ework;
5743         char *pos, *pos2;
5744         size_t type_len;
5745         int ret;
5746         unsigned int freq = 0;
5747
5748         /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
5749
5750         ework = os_zalloc(sizeof(*ework));
5751         if (ework == NULL)
5752                 return -1;
5753
5754         pos = os_strchr(cmd, ' ');
5755         if (pos) {
5756                 type_len = pos - cmd;
5757                 pos++;
5758
5759                 pos2 = os_strstr(pos, "freq=");
5760                 if (pos2)
5761                         freq = atoi(pos2 + 5);
5762
5763                 pos2 = os_strstr(pos, "timeout=");
5764                 if (pos2)
5765                         ework->timeout = atoi(pos2 + 8);
5766         } else {
5767                 type_len = os_strlen(cmd);
5768         }
5769         if (4 + type_len >= sizeof(ework->type))
5770                 type_len = sizeof(ework->type) - 4 - 1;
5771         os_strlcpy(ework->type, "ext:", sizeof(ework->type));
5772         os_memcpy(ework->type + 4, cmd, type_len);
5773         ework->type[4 + type_len] = '\0';
5774
5775         wpa_s->ext_work_id++;
5776         if (wpa_s->ext_work_id == 0)
5777                 wpa_s->ext_work_id++;
5778         ework->id = wpa_s->ext_work_id;
5779
5780         if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
5781                            ework) < 0) {
5782                 os_free(ework);
5783                 return -1;
5784         }
5785
5786         ret = os_snprintf(buf, buflen, "%u", ework->id);
5787         if (ret < 0 || (size_t) ret >= buflen)
5788                 return -1;
5789         return ret;
5790 }
5791
5792
5793 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
5794 {
5795         struct wpa_radio_work *work;
5796         unsigned int id = atoi(cmd);
5797
5798         dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
5799         {
5800                 struct wpa_external_work *ework;
5801
5802                 if (os_strncmp(work->type, "ext:", 4) != 0)
5803                         continue;
5804                 ework = work->ctx;
5805                 if (id && ework->id != id)
5806                         continue;
5807                 wpa_dbg(wpa_s, MSG_DEBUG,
5808                         "Completed external radio work %u (%s)",
5809                         ework->id, ework->type);
5810                 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
5811                 radio_work_done(work);
5812                 os_free(ework);
5813                 return 3; /* "OK\n" */
5814         }
5815
5816         return -1;
5817 }
5818
5819
5820 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
5821                                 char *buf, size_t buflen)
5822 {
5823         if (os_strcmp(cmd, "show") == 0)
5824                 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
5825         if (os_strncmp(cmd, "add ", 4) == 0)
5826                 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
5827         if (os_strncmp(cmd, "done ", 5) == 0)
5828                 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
5829         return -1;
5830 }
5831
5832
5833 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
5834 {
5835         struct wpa_radio_work *work, *tmp;
5836
5837         if (!wpa_s || !wpa_s->radio)
5838                 return;
5839
5840         dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
5841                               struct wpa_radio_work, list) {
5842                 struct wpa_external_work *ework;
5843
5844                 if (os_strncmp(work->type, "ext:", 4) != 0)
5845                         continue;
5846                 ework = work->ctx;
5847                 wpa_dbg(wpa_s, MSG_DEBUG,
5848                         "Flushing %sexternal radio work %u (%s)",
5849                         work->started ? " started" : "", ework->id,
5850                         ework->type);
5851                 if (work->started)
5852                         eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
5853                                              work, NULL);
5854                 os_free(ework);
5855                 radio_work_done(work);
5856         }
5857 }
5858
5859
5860 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx)
5861 {
5862         struct wpa_supplicant *wpa_s = eloop_ctx;
5863         eapol_sm_notify_ctrl_response(wpa_s->eapol);
5864 }
5865
5866
5867 static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
5868 {
5869         int *freqs = NULL;
5870
5871         freqs = freq_range_to_channel_list(wpa_s, val);
5872         if (freqs == NULL)
5873                 return -1;
5874
5875         os_free(wpa_s->manual_scan_freqs);
5876         wpa_s->manual_scan_freqs = freqs;
5877
5878         return 0;
5879 }
5880
5881
5882 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
5883                            char *reply, int reply_size, int *reply_len)
5884 {
5885         char *pos;
5886
5887         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5888                 *reply_len = -1;
5889                 return;
5890         }
5891
5892         wpa_s->manual_scan_passive = 0;
5893         wpa_s->manual_scan_use_id = 0;
5894         wpa_s->manual_scan_only_new = 0;
5895
5896         if (params) {
5897                 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
5898                         wpa_s->scan_res_handler = scan_only_handler;
5899
5900                 pos = os_strstr(params, "freq=");
5901                 if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
5902                         *reply_len = -1;
5903                         return;
5904                 }
5905
5906                 pos = os_strstr(params, "passive=");
5907                 if (pos)
5908                         wpa_s->manual_scan_passive = !!atoi(pos + 8);
5909
5910                 pos = os_strstr(params, "use_id=");
5911                 if (pos)
5912                         wpa_s->manual_scan_use_id = atoi(pos + 7);
5913
5914                 pos = os_strstr(params, "only_new=1");
5915                 if (pos)
5916                         wpa_s->manual_scan_only_new = 1;
5917         } else {
5918                 os_free(wpa_s->manual_scan_freqs);
5919                 wpa_s->manual_scan_freqs = NULL;
5920                 if (wpa_s->scan_res_handler == scan_only_handler)
5921                         wpa_s->scan_res_handler = NULL;
5922         }
5923
5924         if (!wpa_s->sched_scanning && !wpa_s->scanning &&
5925             ((wpa_s->wpa_state <= WPA_SCANNING) ||
5926              (wpa_s->wpa_state == WPA_COMPLETED))) {
5927                 wpa_s->normal_scans = 0;
5928                 wpa_s->scan_req = MANUAL_SCAN_REQ;
5929                 wpa_s->after_wps = 0;
5930                 wpa_s->known_wps_freq = 0;
5931                 wpa_supplicant_req_scan(wpa_s, 0, 0);
5932                 if (wpa_s->manual_scan_use_id) {
5933                         wpa_s->manual_scan_id++;
5934                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
5935                                 wpa_s->manual_scan_id);
5936                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
5937                                                  wpa_s->manual_scan_id);
5938                 }
5939         } else if (wpa_s->sched_scanning) {
5940                 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
5941                 wpa_supplicant_cancel_sched_scan(wpa_s);
5942                 wpa_s->scan_req = MANUAL_SCAN_REQ;
5943                 wpa_supplicant_req_scan(wpa_s, 0, 0);
5944                 if (wpa_s->manual_scan_use_id) {
5945                         wpa_s->manual_scan_id++;
5946                         *reply_len = os_snprintf(reply, reply_size, "%u\n",
5947                                                  wpa_s->manual_scan_id);
5948                         wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
5949                                 wpa_s->manual_scan_id);
5950                 }
5951         } else {
5952                 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
5953                 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
5954         }
5955 }
5956
5957
5958 #ifdef CONFIG_TESTING_OPTIONS
5959
5960 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s,
5961                                        unsigned int freq, const u8 *dst,
5962                                        const u8 *src, const u8 *bssid,
5963                                        const u8 *data, size_t data_len,
5964                                        enum offchannel_send_action_result
5965                                        result)
5966 {
5967         wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR
5968                 " src=" MACSTR " bssid=" MACSTR " result=%s",
5969                 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
5970                 result == OFFCHANNEL_SEND_ACTION_SUCCESS ?
5971                 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ?
5972                              "NO_ACK" : "FAILED"));
5973 }
5974
5975
5976 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd)
5977 {
5978         char *pos, *param;
5979         size_t len;
5980         u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN];
5981         int res, used;
5982         int freq = 0, no_cck = 0, wait_time = 0;
5983
5984         /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1]
5985          *    <action=Action frame payload> */
5986
5987         wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
5988
5989         pos = cmd;
5990         used = hwaddr_aton2(pos, da);
5991         if (used < 0)
5992                 return -1;
5993         pos += used;
5994         while (*pos == ' ')
5995                 pos++;
5996         used = hwaddr_aton2(pos, bssid);
5997         if (used < 0)
5998                 return -1;
5999         pos += used;
6000
6001         param = os_strstr(pos, " freq=");
6002         if (param) {
6003                 param += 6;
6004                 freq = atoi(param);
6005         }
6006
6007         param = os_strstr(pos, " no_cck=");
6008         if (param) {
6009                 param += 8;
6010                 no_cck = atoi(param);
6011         }
6012
6013         param = os_strstr(pos, " wait_time=");
6014         if (param) {
6015                 param += 11;
6016                 wait_time = atoi(param);
6017         }
6018
6019         param = os_strstr(pos, " action=");
6020         if (param == NULL)
6021                 return -1;
6022         param += 8;
6023
6024         len = os_strlen(param);
6025         if (len & 1)
6026                 return -1;
6027         len /= 2;
6028
6029         buf = os_malloc(len);
6030         if (buf == NULL)
6031                 return -1;
6032
6033         if (hexstr2bin(param, buf, len) < 0) {
6034                 os_free(buf);
6035                 return -1;
6036         }
6037
6038         res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid,
6039                                      buf, len, wait_time,
6040                                      wpas_ctrl_iface_mgmt_tx_cb, no_cck);
6041         os_free(buf);
6042         return res;
6043 }
6044
6045
6046 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s)
6047 {
6048         wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting");
6049         offchannel_send_action_done(wpa_s);
6050 }
6051
6052 #endif /* CONFIG_TESTING_OPTIONS */
6053
6054
6055 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
6056                                          char *buf, size_t *resp_len)
6057 {
6058         char *reply;
6059         const int reply_size = 4096;
6060         int reply_len;
6061
6062         if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
6063             os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
6064                 if (wpa_debug_show_keys)
6065                         wpa_dbg(wpa_s, MSG_DEBUG,
6066                                 "Control interface command '%s'", buf);
6067                 else
6068                         wpa_dbg(wpa_s, MSG_DEBUG,
6069                                 "Control interface command '%s [REMOVED]'",
6070                                 os_strncmp(buf, WPA_CTRL_RSP,
6071                                            os_strlen(WPA_CTRL_RSP)) == 0 ?
6072                                 WPA_CTRL_RSP : "SET_NETWORK");
6073         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
6074                    os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
6075                    os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
6076                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
6077                                       (const u8 *) buf, os_strlen(buf));
6078         } else {
6079                 int level = MSG_DEBUG;
6080                 if (os_strcmp(buf, "PING") == 0)
6081                         level = MSG_EXCESSIVE;
6082                 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
6083         }
6084
6085         reply = os_malloc(reply_size);
6086         if (reply == NULL) {
6087                 *resp_len = 1;
6088                 return NULL;
6089         }
6090
6091         os_memcpy(reply, "OK\n", 3);
6092         reply_len = 3;
6093
6094         if (os_strcmp(buf, "PING") == 0) {
6095                 os_memcpy(reply, "PONG\n", 5);
6096                 reply_len = 5;
6097         } else if (os_strcmp(buf, "IFNAME") == 0) {
6098                 reply_len = os_strlen(wpa_s->ifname);
6099                 os_memcpy(reply, wpa_s->ifname, reply_len);
6100         } else if (os_strncmp(buf, "RELOG", 5) == 0) {
6101                 if (wpa_debug_reopen_file() < 0)
6102                         reply_len = -1;
6103         } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
6104                 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
6105         } else if (os_strcmp(buf, "MIB") == 0) {
6106                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
6107                 if (reply_len >= 0) {
6108                         int res;
6109                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
6110                                                reply_size - reply_len);
6111                         if (res < 0)
6112                                 reply_len = -1;
6113                         else
6114                                 reply_len += res;
6115                 }
6116         } else if (os_strncmp(buf, "STATUS", 6) == 0) {
6117                 reply_len = wpa_supplicant_ctrl_iface_status(
6118                         wpa_s, buf + 6, reply, reply_size);
6119         } else if (os_strcmp(buf, "PMKSA") == 0) {
6120                 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
6121                                                     reply_size);
6122         } else if (os_strncmp(buf, "SET ", 4) == 0) {
6123                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
6124                         reply_len = -1;
6125         } else if (os_strncmp(buf, "GET ", 4) == 0) {
6126                 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4,
6127                                                           reply, reply_size);
6128         } else if (os_strcmp(buf, "LOGON") == 0) {
6129                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
6130         } else if (os_strcmp(buf, "LOGOFF") == 0) {
6131                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
6132         } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
6133                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
6134                         reply_len = -1;
6135                 else
6136                         wpas_request_connection(wpa_s);
6137         } else if (os_strcmp(buf, "REATTACH") == 0) {
6138                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
6139                     !wpa_s->current_ssid)
6140                         reply_len = -1;
6141                 else {
6142                         wpa_s->reattach = 1;
6143                         wpas_request_connection(wpa_s);
6144                 }
6145         } else if (os_strcmp(buf, "RECONNECT") == 0) {
6146                 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
6147                         reply_len = -1;
6148                 else if (wpa_s->disconnected)
6149                         wpas_request_connection(wpa_s);
6150 #ifdef IEEE8021X_EAPOL
6151         } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
6152                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
6153                         reply_len = -1;
6154 #endif /* IEEE8021X_EAPOL */
6155 #ifdef CONFIG_PEERKEY
6156         } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
6157                 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
6158                         reply_len = -1;
6159 #endif /* CONFIG_PEERKEY */
6160 #ifdef CONFIG_IEEE80211R
6161         } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
6162                 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
6163                         reply_len = -1;
6164 #endif /* CONFIG_IEEE80211R */
6165 #ifdef CONFIG_WPS
6166         } else if (os_strcmp(buf, "WPS_PBC") == 0) {
6167                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL);
6168                 if (res == -2) {
6169                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6170                         reply_len = 17;
6171                 } else if (res)
6172                         reply_len = -1;
6173         } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
6174                 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8);
6175                 if (res == -2) {
6176                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6177                         reply_len = 17;
6178                 } else if (res)
6179                         reply_len = -1;
6180         } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
6181                 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
6182                                                               reply,
6183                                                               reply_size);
6184         } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
6185                 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin(
6186                         wpa_s, buf + 14, reply, reply_size);
6187         } else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
6188                 if (wpas_wps_cancel(wpa_s))
6189                         reply_len = -1;
6190 #ifdef CONFIG_WPS_NFC
6191         } else if (os_strcmp(buf, "WPS_NFC") == 0) {
6192                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL))
6193                         reply_len = -1;
6194         } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) {
6195                 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8))
6196                         reply_len = -1;
6197         } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
6198                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token(
6199                         wpa_s, buf + 21, reply, reply_size);
6200         } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
6201                 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token(
6202                         wpa_s, buf + 14, reply, reply_size);
6203         } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
6204                 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s,
6205                                                                buf + 17))
6206                         reply_len = -1;
6207         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) {
6208                 reply_len = wpas_ctrl_nfc_get_handover_req(
6209                         wpa_s, buf + 21, reply, reply_size);
6210         } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
6211                 reply_len = wpas_ctrl_nfc_get_handover_sel(
6212                         wpa_s, buf + 21, reply, reply_size);
6213         } else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) {
6214                 if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20))
6215                         reply_len = -1;
6216         } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
6217                 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20))
6218                         reply_len = -1;
6219 #endif /* CONFIG_WPS_NFC */
6220         } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
6221                 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
6222                         reply_len = -1;
6223 #ifdef CONFIG_AP
6224         } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
6225                 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin(
6226                         wpa_s, buf + 11, reply, reply_size);
6227 #endif /* CONFIG_AP */
6228 #ifdef CONFIG_WPS_ER
6229         } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
6230                 if (wpas_wps_er_start(wpa_s, NULL))
6231                         reply_len = -1;
6232         } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
6233                 if (wpas_wps_er_start(wpa_s, buf + 13))
6234                         reply_len = -1;
6235         } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
6236                 if (wpas_wps_er_stop(wpa_s))
6237                         reply_len = -1;
6238         } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
6239                 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
6240                         reply_len = -1;
6241         } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
6242                 int ret = wpas_wps_er_pbc(wpa_s, buf + 11);
6243                 if (ret == -2) {
6244                         os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17);
6245                         reply_len = 17;
6246                 } else if (ret == -3) {
6247                         os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18);
6248                         reply_len = 18;
6249                 } else if (ret == -4) {
6250                         os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20);
6251                         reply_len = 20;
6252                 } else if (ret)
6253                         reply_len = -1;
6254         } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
6255                 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
6256                         reply_len = -1;
6257         } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) {
6258                 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s,
6259                                                                 buf + 18))
6260                         reply_len = -1;
6261         } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
6262                 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
6263                         reply_len = -1;
6264 #ifdef CONFIG_WPS_NFC
6265         } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) {
6266                 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
6267                         wpa_s, buf + 24, reply, reply_size);
6268 #endif /* CONFIG_WPS_NFC */
6269 #endif /* CONFIG_WPS_ER */
6270 #endif /* CONFIG_WPS */
6271 #ifdef CONFIG_IBSS_RSN
6272         } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
6273                 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
6274                         reply_len = -1;
6275 #endif /* CONFIG_IBSS_RSN */
6276 #ifdef CONFIG_P2P
6277         } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
6278                 if (p2p_ctrl_find(wpa_s, buf + 9))
6279                         reply_len = -1;
6280         } else if (os_strcmp(buf, "P2P_FIND") == 0) {
6281                 if (p2p_ctrl_find(wpa_s, ""))
6282                         reply_len = -1;
6283         } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
6284                 wpas_p2p_stop_find(wpa_s);
6285         } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
6286                 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
6287                                              reply_size);
6288         } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) {
6289                 if (p2p_ctrl_listen(wpa_s, buf + 11))
6290                         reply_len = -1;
6291         } else if (os_strcmp(buf, "P2P_LISTEN") == 0) {
6292                 if (p2p_ctrl_listen(wpa_s, ""))
6293                         reply_len = -1;
6294         } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) {
6295                 if (wpas_p2p_group_remove(wpa_s, buf + 17))
6296                         reply_len = -1;
6297         } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) {
6298                 if (wpas_p2p_group_add(wpa_s, 0, 0, 0, 0))
6299                         reply_len = -1;
6300         } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
6301                 if (p2p_ctrl_group_add(wpa_s, buf + 14))
6302                         reply_len = -1;
6303         } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
6304                 if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
6305                         reply_len = -1;
6306         } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
6307                 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
6308         } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
6309                 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
6310                                                    reply_size);
6311         } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) {
6312                 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0)
6313                         reply_len = -1;
6314         } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) {
6315                 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0)
6316                         reply_len = -1;
6317         } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) {
6318                 wpas_p2p_sd_service_update(wpa_s);
6319         } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) {
6320                 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0)
6321                         reply_len = -1;
6322         } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) {
6323                 wpas_p2p_service_flush(wpa_s);
6324         } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) {
6325                 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0)
6326                         reply_len = -1;
6327         } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
6328                 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
6329                         reply_len = -1;
6330         } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
6331                 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
6332                         reply_len = -1;
6333         } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) {
6334                 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0)
6335                         reply_len = -1;
6336         } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) {
6337                 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply,
6338                                               reply_size);
6339         } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) {
6340                 if (p2p_ctrl_set(wpa_s, buf + 8) < 0)
6341                         reply_len = -1;
6342         } else if (os_strcmp(buf, "P2P_FLUSH") == 0) {
6343                 p2p_ctrl_flush(wpa_s);
6344         } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) {
6345                 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0)
6346                         reply_len = -1;
6347         } else if (os_strcmp(buf, "P2P_CANCEL") == 0) {
6348                 if (wpas_p2p_cancel(wpa_s))
6349                         reply_len = -1;
6350         } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) {
6351                 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0)
6352                         reply_len = -1;
6353         } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) {
6354                 if (p2p_ctrl_presence_req(wpa_s, "") < 0)
6355                         reply_len = -1;
6356         } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) {
6357                 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0)
6358                         reply_len = -1;
6359         } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) {
6360                 if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
6361                         reply_len = -1;
6362         } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
6363                 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
6364                         reply_len = -1;
6365 #endif /* CONFIG_P2P */
6366 #ifdef CONFIG_WIFI_DISPLAY
6367         } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
6368                 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0)
6369                         reply_len = -1;
6370         } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) {
6371                 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16,
6372                                                      reply, reply_size);
6373 #endif /* CONFIG_WIFI_DISPLAY */
6374 #ifdef CONFIG_INTERWORKING
6375         } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
6376                 if (interworking_fetch_anqp(wpa_s) < 0)
6377                         reply_len = -1;
6378         } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
6379                 interworking_stop_fetch_anqp(wpa_s);
6380         } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
6381                 if (ctrl_interworking_select(wpa_s, NULL) < 0)
6382                         reply_len = -1;
6383         } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
6384                 if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
6385                         reply_len = -1;
6386         } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
6387                 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
6388                         reply_len = -1;
6389         } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
6390                 if (get_anqp(wpa_s, buf + 9) < 0)
6391                         reply_len = -1;
6392         } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) {
6393                 if (gas_request(wpa_s, buf + 12) < 0)
6394                         reply_len = -1;
6395         } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) {
6396                 reply_len = gas_response_get(wpa_s, buf + 17, reply,
6397                                              reply_size);
6398 #endif /* CONFIG_INTERWORKING */
6399 #ifdef CONFIG_HS20
6400         } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
6401                 if (get_hs20_anqp(wpa_s, buf + 14) < 0)
6402                         reply_len = -1;
6403         } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
6404                 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
6405                         reply_len = -1;
6406         } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
6407                 if (hs20_icon_request(wpa_s, buf + 18) < 0)
6408                         reply_len = -1;
6409         } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
6410                 if (hs20_fetch_osu(wpa_s) < 0)
6411                         reply_len = -1;
6412         } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
6413                 hs20_cancel_fetch_osu(wpa_s);
6414 #endif /* CONFIG_HS20 */
6415         } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
6416         {
6417                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
6418                             wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
6419                         reply_len = -1;
6420                 else {
6421                         /*
6422                          * Notify response from timeout to allow the control
6423                          * interface response to be sent first.
6424                          */
6425                         eloop_register_timeout(0, 0, wpas_ctrl_eapol_response,
6426                                                wpa_s, NULL);
6427                 }
6428         } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
6429                 if (wpa_supplicant_reload_configuration(wpa_s))
6430                         reply_len = -1;
6431         } else if (os_strcmp(buf, "TERMINATE") == 0) {
6432                 wpa_supplicant_terminate_proc(wpa_s->global);
6433         } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
6434                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
6435                         reply_len = -1;
6436         } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
6437                 reply_len = wpa_supplicant_ctrl_iface_blacklist(
6438                         wpa_s, buf + 9, reply, reply_size);
6439         } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
6440                 reply_len = wpa_supplicant_ctrl_iface_log_level(
6441                         wpa_s, buf + 9, reply, reply_size);
6442         } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
6443                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
6444                         wpa_s, reply, reply_size);
6445         } else if (os_strcmp(buf, "DISCONNECT") == 0) {
6446 #ifdef CONFIG_SME
6447                 wpa_s->sme.prev_bssid_set = 0;
6448 #endif /* CONFIG_SME */
6449                 wpa_s->reassociate = 0;
6450                 wpa_s->disconnected = 1;
6451                 wpa_supplicant_cancel_sched_scan(wpa_s);
6452                 wpa_supplicant_cancel_scan(wpa_s);
6453                 wpa_supplicant_deauthenticate(wpa_s,
6454                                               WLAN_REASON_DEAUTH_LEAVING);
6455         } else if (os_strcmp(buf, "SCAN") == 0) {
6456                 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
6457         } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
6458                 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
6459         } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
6460                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
6461                         wpa_s, reply, reply_size);
6462         } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
6463                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
6464                         reply_len = -1;
6465         } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
6466                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
6467                         reply_len = -1;
6468         } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
6469                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
6470                         reply_len = -1;
6471         } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
6472                 reply_len = wpa_supplicant_ctrl_iface_add_network(
6473                         wpa_s, reply, reply_size);
6474         } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
6475                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
6476                         reply_len = -1;
6477         } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
6478                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
6479                         reply_len = -1;
6480         } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
6481                 reply_len = wpa_supplicant_ctrl_iface_get_network(
6482                         wpa_s, buf + 12, reply, reply_size);
6483         } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
6484                 reply_len = wpa_supplicant_ctrl_iface_list_creds(
6485                         wpa_s, reply, reply_size);
6486         } else if (os_strcmp(buf, "ADD_CRED") == 0) {
6487                 reply_len = wpa_supplicant_ctrl_iface_add_cred(
6488                         wpa_s, reply, reply_size);
6489         } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
6490                 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
6491                         reply_len = -1;
6492         } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
6493                 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
6494                         reply_len = -1;
6495         } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
6496                 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
6497                                                                reply,
6498                                                                reply_size);
6499 #ifndef CONFIG_NO_CONFIG_WRITE
6500         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
6501                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
6502                         reply_len = -1;
6503 #endif /* CONFIG_NO_CONFIG_WRITE */
6504         } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
6505                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
6506                         wpa_s, buf + 15, reply, reply_size);
6507         } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
6508                 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
6509                         reply_len = -1;
6510         } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) {
6511                 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14))
6512                         reply_len = -1;
6513         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
6514                 reply_len = wpa_supplicant_global_iface_list(
6515                         wpa_s->global, reply, reply_size);
6516         } else if (os_strcmp(buf, "INTERFACES") == 0) {
6517                 reply_len = wpa_supplicant_global_iface_interfaces(
6518                         wpa_s->global, reply, reply_size);
6519         } else if (os_strncmp(buf, "BSS ", 4) == 0) {
6520                 reply_len = wpa_supplicant_ctrl_iface_bss(
6521                         wpa_s, buf + 4, reply, reply_size);
6522 #ifdef CONFIG_AP
6523         } else if (os_strcmp(buf, "STA-FIRST") == 0) {
6524                 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
6525         } else if (os_strncmp(buf, "STA ", 4) == 0) {
6526                 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
6527                                               reply_size);
6528         } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
6529                 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
6530                                                    reply_size);
6531         } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
6532                 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
6533                         reply_len = -1;
6534         } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
6535                 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
6536                         reply_len = -1;
6537         } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
6538                 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
6539                         reply_len = -1;
6540 #endif /* CONFIG_AP */
6541         } else if (os_strcmp(buf, "SUSPEND") == 0) {
6542                 wpas_notify_suspend(wpa_s->global);
6543         } else if (os_strcmp(buf, "RESUME") == 0) {
6544                 wpas_notify_resume(wpa_s->global);
6545 #ifdef CONFIG_TESTING_OPTIONS
6546         } else if (os_strcmp(buf, "DROP_SA") == 0) {
6547                 wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
6548 #endif /* CONFIG_TESTING_OPTIONS */
6549         } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
6550                 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
6551                         reply_len = -1;
6552         } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
6553                 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
6554                         reply_len = -1;
6555         } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) {
6556                 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15))
6557                         reply_len = -1;
6558         } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) {
6559                 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s,
6560                                                                buf + 17))
6561                         reply_len = -1;
6562         } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) {
6563                 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10))
6564                         reply_len = -1;
6565 #ifdef CONFIG_TDLS
6566         } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
6567                 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
6568                         reply_len = -1;
6569         } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
6570                 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
6571                         reply_len = -1;
6572         } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
6573                 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
6574                         reply_len = -1;
6575 #endif /* CONFIG_TDLS */
6576         } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
6577                 reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
6578                                                        reply_size);
6579         } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
6580                 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
6581                                                        reply_size);
6582 #ifdef CONFIG_AUTOSCAN
6583         } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) {
6584                 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
6585                         reply_len = -1;
6586 #endif /* CONFIG_AUTOSCAN */
6587 #ifdef ANDROID
6588         } else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
6589                 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
6590                                                       reply_size);
6591 #endif /* ANDROID */
6592         } else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
6593                 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply,
6594                                                       reply_size);
6595         } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
6596                 pmksa_cache_clear_current(wpa_s->wpa);
6597                 eapol_sm_request_reauth(wpa_s->eapol);
6598 #ifdef CONFIG_WNM
6599         } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) {
6600                 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10))
6601                         reply_len = -1;
6602         } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 10) == 0) {
6603                 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 10))
6604                                 reply_len = -1;
6605 #endif /* CONFIG_WNM */
6606         } else if (os_strcmp(buf, "FLUSH") == 0) {
6607                 wpa_supplicant_ctrl_iface_flush(wpa_s);
6608         } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
6609                 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
6610                                                  reply_size);
6611 #ifdef CONFIG_TESTING_OPTIONS
6612         } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
6613                 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0)
6614                         reply_len = -1;
6615         } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
6616                 wpas_ctrl_iface_mgmt_tx_done(wpa_s);
6617 #endif /* CONFIG_TESTING_OPTIONS */
6618         } else {
6619                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
6620                 reply_len = 16;
6621         }
6622
6623         if (reply_len < 0) {
6624                 os_memcpy(reply, "FAIL\n", 5);
6625                 reply_len = 5;
6626         }
6627
6628         *resp_len = reply_len;
6629         return reply;
6630 }
6631
6632
6633 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
6634                                            char *cmd)
6635 {
6636         struct wpa_interface iface;
6637         char *pos;
6638
6639         /*
6640          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
6641          * TAB<bridge_ifname>
6642          */
6643         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
6644
6645         os_memset(&iface, 0, sizeof(iface));
6646
6647         do {
6648                 iface.ifname = pos = cmd;
6649                 pos = os_strchr(pos, '\t');
6650                 if (pos)
6651                         *pos++ = '\0';
6652                 if (iface.ifname[0] == '\0')
6653                         return -1;
6654                 if (pos == NULL)
6655                         break;
6656
6657                 iface.confname = pos;
6658                 pos = os_strchr(pos, '\t');
6659                 if (pos)
6660                         *pos++ = '\0';
6661                 if (iface.confname[0] == '\0')
6662                         iface.confname = NULL;
6663                 if (pos == NULL)
6664                         break;
6665
6666                 iface.driver = pos;
6667                 pos = os_strchr(pos, '\t');
6668                 if (pos)
6669                         *pos++ = '\0';
6670                 if (iface.driver[0] == '\0')
6671                         iface.driver = NULL;
6672                 if (pos == NULL)
6673                         break;
6674
6675                 iface.ctrl_interface = pos;
6676                 pos = os_strchr(pos, '\t');
6677                 if (pos)
6678                         *pos++ = '\0';
6679                 if (iface.ctrl_interface[0] == '\0')
6680                         iface.ctrl_interface = NULL;
6681                 if (pos == NULL)
6682                         break;
6683
6684                 iface.driver_param = pos;
6685                 pos = os_strchr(pos, '\t');
6686                 if (pos)
6687                         *pos++ = '\0';
6688                 if (iface.driver_param[0] == '\0')
6689                         iface.driver_param = NULL;
6690                 if (pos == NULL)
6691                         break;
6692
6693                 iface.bridge_ifname = pos;
6694                 pos = os_strchr(pos, '\t');
6695                 if (pos)
6696                         *pos++ = '\0';
6697                 if (iface.bridge_ifname[0] == '\0')
6698                         iface.bridge_ifname = NULL;
6699                 if (pos == NULL)
6700                         break;
6701         } while (0);
6702
6703         if (wpa_supplicant_get_iface(global, iface.ifname))
6704                 return -1;
6705
6706         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
6707 }
6708
6709
6710 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
6711                                               char *cmd)
6712 {
6713         struct wpa_supplicant *wpa_s;
6714
6715         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
6716
6717         wpa_s = wpa_supplicant_get_iface(global, cmd);
6718         if (wpa_s == NULL)
6719                 return -1;
6720         return wpa_supplicant_remove_iface(global, wpa_s, 0);
6721 }
6722
6723
6724 static void wpa_free_iface_info(struct wpa_interface_info *iface)
6725 {
6726         struct wpa_interface_info *prev;
6727
6728         while (iface) {
6729                 prev = iface;
6730                 iface = iface->next;
6731
6732                 os_free(prev->ifname);
6733                 os_free(prev->desc);
6734                 os_free(prev);
6735         }
6736 }
6737
6738
6739 static int wpa_supplicant_global_iface_list(struct wpa_global *global,
6740                                             char *buf, int len)
6741 {
6742         int i, res;
6743         struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
6744         char *pos, *end;
6745
6746         for (i = 0; wpa_drivers[i]; i++) {
6747                 struct wpa_driver_ops *drv = wpa_drivers[i];
6748                 if (drv->get_interfaces == NULL)
6749                         continue;
6750                 tmp = drv->get_interfaces(global->drv_priv[i]);
6751                 if (tmp == NULL)
6752                         continue;
6753
6754                 if (last == NULL)
6755                         iface = last = tmp;
6756                 else
6757                         last->next = tmp;
6758                 while (last->next)
6759                         last = last->next;
6760         }
6761
6762         pos = buf;
6763         end = buf + len;
6764         for (tmp = iface; tmp; tmp = tmp->next) {
6765                 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
6766                                   tmp->drv_name, tmp->ifname,
6767                                   tmp->desc ? tmp->desc : "");
6768                 if (res < 0 || res >= end - pos) {
6769                         *pos = '\0';
6770                         break;
6771                 }
6772                 pos += res;
6773         }
6774
6775         wpa_free_iface_info(iface);
6776
6777         return pos - buf;
6778 }
6779
6780
6781 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
6782                                                   char *buf, int len)
6783 {
6784         int res;
6785         char *pos, *end;
6786         struct wpa_supplicant *wpa_s;
6787
6788         wpa_s = global->ifaces;
6789         pos = buf;
6790         end = buf + len;
6791
6792         while (wpa_s) {
6793                 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
6794                 if (res < 0 || res >= end - pos) {
6795                         *pos = '\0';
6796                         break;
6797                 }
6798                 pos += res;
6799                 wpa_s = wpa_s->next;
6800         }
6801         return pos - buf;
6802 }
6803
6804
6805 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global,
6806                                             const char *ifname,
6807                                             char *cmd, size_t *resp_len)
6808 {
6809         struct wpa_supplicant *wpa_s;
6810
6811         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6812                 if (os_strcmp(ifname, wpa_s->ifname) == 0)
6813                         break;
6814         }
6815
6816         if (wpa_s == NULL) {
6817                 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n");
6818                 if (resp)
6819                         *resp_len = os_strlen(resp);
6820                 else
6821                         *resp_len = 1;
6822                 return resp;
6823         }
6824
6825         return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len);
6826 }
6827
6828
6829 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
6830                                                char *buf, size_t *resp_len)
6831 {
6832 #ifdef CONFIG_P2P
6833         static const char * cmd[] = {
6834                 "LIST_NETWORKS",
6835                 "SAVE_CONFIG",
6836                 "P2P_FIND",
6837                 "P2P_STOP_FIND",
6838                 "P2P_LISTEN",
6839                 "P2P_GROUP_ADD",
6840                 "P2P_GET_PASSPHRASE",
6841                 "P2P_SERVICE_UPDATE",
6842                 "P2P_SERVICE_FLUSH",
6843                 "P2P_FLUSH",
6844                 "P2P_CANCEL",
6845                 "P2P_PRESENCE_REQ",
6846                 "P2P_EXT_LISTEN",
6847                 NULL
6848         };
6849         static const char * prefix[] = {
6850 #ifdef ANDROID
6851                 "DRIVER ",
6852 #endif /* ANDROID */
6853                 "GET_NETWORK ",
6854                 "REMOVE_NETWORK ",
6855                 "SET ",
6856                 "P2P_FIND ",
6857                 "P2P_CONNECT ",
6858                 "P2P_LISTEN ",
6859                 "P2P_GROUP_REMOVE ",
6860                 "P2P_GROUP_ADD ",
6861                 "P2P_PROV_DISC ",
6862                 "P2P_SERV_DISC_REQ ",
6863                 "P2P_SERV_DISC_CANCEL_REQ ",
6864                 "P2P_SERV_DISC_RESP ",
6865                 "P2P_SERV_DISC_EXTERNAL ",
6866                 "P2P_SERVICE_ADD ",
6867                 "P2P_SERVICE_DEL ",
6868                 "P2P_REJECT ",
6869                 "P2P_INVITE ",
6870                 "P2P_PEER ",
6871                 "P2P_SET ",
6872                 "P2P_UNAUTHORIZE ",
6873                 "P2P_PRESENCE_REQ ",
6874                 "P2P_EXT_LISTEN ",
6875                 "P2P_REMOVE_CLIENT ",
6876                 NULL
6877         };
6878         int found = 0;
6879         int i;
6880
6881         if (global->p2p_init_wpa_s == NULL)
6882                 return NULL;
6883
6884         for (i = 0; !found && cmd[i]; i++) {
6885                 if (os_strcmp(buf, cmd[i]) == 0)
6886                         found = 1;
6887         }
6888
6889         for (i = 0; !found && prefix[i]; i++) {
6890                 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0)
6891                         found = 1;
6892         }
6893
6894         if (found)
6895                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6896                                                          buf, resp_len);
6897 #endif /* CONFIG_P2P */
6898         return NULL;
6899 }
6900
6901
6902 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global,
6903                                                char *buf, size_t *resp_len)
6904 {
6905 #ifdef CONFIG_WIFI_DISPLAY
6906         if (global->p2p_init_wpa_s == NULL)
6907                 return NULL;
6908         if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 ||
6909             os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0)
6910                 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s,
6911                                                          buf, resp_len);
6912 #endif /* CONFIG_WIFI_DISPLAY */
6913         return NULL;
6914 }
6915
6916
6917 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global,
6918                                            char *buf, size_t *resp_len)
6919 {
6920         char *ret;
6921
6922         ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len);
6923         if (ret)
6924                 return ret;
6925
6926         ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len);
6927         if (ret)
6928                 return ret;
6929
6930         return NULL;
6931 }
6932
6933
6934 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd)
6935 {
6936         char *value;
6937
6938         value = os_strchr(cmd, ' ');
6939         if (value == NULL)
6940                 return -1;
6941         *value++ = '\0';
6942
6943         wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value);
6944
6945 #ifdef CONFIG_WIFI_DISPLAY
6946         if (os_strcasecmp(cmd, "wifi_display") == 0) {
6947                 wifi_display_enable(global, !!atoi(value));
6948                 return 0;
6949         }
6950 #endif /* CONFIG_WIFI_DISPLAY */
6951
6952         return -1;
6953 }
6954
6955
6956 #ifndef CONFIG_NO_CONFIG_WRITE
6957 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global)
6958 {
6959         int ret = 0;
6960         struct wpa_supplicant *wpa_s;
6961
6962         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6963                 if (!wpa_s->conf->update_config) {
6964                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)");
6965                         continue;
6966                 }
6967
6968                 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
6969                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration");
6970                         ret = 1;
6971                 } else {
6972                         wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated");
6973                 }
6974         }
6975
6976         return ret;
6977 }
6978 #endif /* CONFIG_NO_CONFIG_WRITE */
6979
6980
6981 static int wpas_global_ctrl_iface_status(struct wpa_global *global,
6982                                          char *buf, size_t buflen)
6983 {
6984         char *pos, *end;
6985         int ret;
6986         struct wpa_supplicant *wpa_s;
6987
6988         pos = buf;
6989         end = buf + buflen;
6990
6991 #ifdef CONFIG_P2P
6992         if (global->p2p && !global->p2p_disabled) {
6993                 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
6994                                   "\n"
6995                                   "p2p_state=%s\n",
6996                                   MAC2STR(global->p2p_dev_addr),
6997                                   p2p_get_state_txt(global->p2p));
6998                 if (ret < 0 || ret >= end - pos)
6999                         return pos - buf;
7000                 pos += ret;
7001         } else if (global->p2p) {
7002                 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n");
7003                 if (ret < 0 || ret >= end - pos)
7004                         return pos - buf;
7005                 pos += ret;
7006         }
7007 #endif /* CONFIG_P2P */
7008
7009 #ifdef CONFIG_WIFI_DISPLAY
7010         ret = os_snprintf(pos, end - pos, "wifi_display=%d\n",
7011                           !!global->wifi_display);
7012         if (ret < 0 || ret >= end - pos)
7013                 return pos - buf;
7014         pos += ret;
7015 #endif /* CONFIG_WIFI_DISPLAY */
7016
7017         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7018                 ret = os_snprintf(pos, end - pos, "ifname=%s\n"
7019                                   "address=" MACSTR "\n",
7020                                   wpa_s->ifname, MAC2STR(wpa_s->own_addr));
7021                 if (ret < 0 || ret >= end - pos)
7022                         return pos - buf;
7023                 pos += ret;
7024         }
7025
7026         return pos - buf;
7027 }
7028
7029
7030 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
7031                                                 char *buf, size_t *resp_len)
7032 {
7033         char *reply;
7034         const int reply_size = 2048;
7035         int reply_len;
7036         int level = MSG_DEBUG;
7037
7038         if (os_strncmp(buf, "IFNAME=", 7) == 0) {
7039                 char *pos = os_strchr(buf + 7, ' ');
7040                 if (pos) {
7041                         *pos++ = '\0';
7042                         return wpas_global_ctrl_iface_ifname(global,
7043                                                              buf + 7, pos,
7044                                                              resp_len);
7045                 }
7046         }
7047
7048         reply = wpas_global_ctrl_iface_redir(global, buf, resp_len);
7049         if (reply)
7050                 return reply;
7051
7052         if (os_strcmp(buf, "PING") == 0)
7053                 level = MSG_EXCESSIVE;
7054         wpa_hexdump_ascii(level, "RX global ctrl_iface",
7055                           (const u8 *) buf, os_strlen(buf));
7056
7057         reply = os_malloc(reply_size);
7058         if (reply == NULL) {
7059                 *resp_len = 1;
7060                 return NULL;
7061         }
7062
7063         os_memcpy(reply, "OK\n", 3);
7064         reply_len = 3;
7065
7066         if (os_strcmp(buf, "PING") == 0) {
7067                 os_memcpy(reply, "PONG\n", 5);
7068                 reply_len = 5;
7069         } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
7070                 if (wpa_supplicant_global_iface_add(global, buf + 14))
7071                         reply_len = -1;
7072         } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
7073                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
7074                         reply_len = -1;
7075         } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
7076                 reply_len = wpa_supplicant_global_iface_list(
7077                         global, reply, reply_size);
7078         } else if (os_strcmp(buf, "INTERFACES") == 0) {
7079                 reply_len = wpa_supplicant_global_iface_interfaces(
7080                         global, reply, reply_size);
7081         } else if (os_strcmp(buf, "TERMINATE") == 0) {
7082                 wpa_supplicant_terminate_proc(global);
7083         } else if (os_strcmp(buf, "SUSPEND") == 0) {
7084                 wpas_notify_suspend(global);
7085         } else if (os_strcmp(buf, "RESUME") == 0) {
7086                 wpas_notify_resume(global);
7087         } else if (os_strncmp(buf, "SET ", 4) == 0) {
7088                 if (wpas_global_ctrl_iface_set(global, buf + 4))
7089                         reply_len = -1;
7090 #ifndef CONFIG_NO_CONFIG_WRITE
7091         } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
7092                 if (wpas_global_ctrl_iface_save_config(global))
7093                         reply_len = -1;
7094 #endif /* CONFIG_NO_CONFIG_WRITE */
7095         } else if (os_strcmp(buf, "STATUS") == 0) {
7096                 reply_len = wpas_global_ctrl_iface_status(global, reply,
7097                                                           reply_size);
7098 #ifdef CONFIG_MODULE_TESTS
7099         } else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
7100                 int wpas_module_tests(void);
7101                 if (wpas_module_tests() < 0)
7102                         reply_len = -1;
7103 #endif /* CONFIG_MODULE_TESTS */
7104         } else {
7105                 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
7106                 reply_len = 16;
7107         }
7108
7109         if (reply_len < 0) {
7110                 os_memcpy(reply, "FAIL\n", 5);
7111                 reply_len = 5;
7112         }
7113
7114         *resp_len = reply_len;
7115         return reply;
7116 }