1/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2013, 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 "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
21#include "utils/list.h"
22#include "common/version.h"
23#include "common/ieee802_11_defs.h"
24#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
31"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
32
33
34static const char *wpa_cli_license =
35"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
37
38static const char *wpa_cli_full_license =
39"This software may be distributed under the terms of the BSD license.\n"
40"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46"   notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49"   notice, this list of conditions and the following disclaimer in the\n"
50"   documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53"   names of its contributors may be used to endorse or promote products\n"
54"   derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
73static int wpa_cli_connected = -1;
74static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
84static char *ifname_prefix = NULL;
85
86struct cli_txt_entry {
87	struct dl_list list;
88	char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
94static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
95
96
97static void print_help(const char *cmd);
98static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
99static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
102
103
104static void usage(void)
105{
106	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107	       "[-a<action file>] \\\n"
108	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  "
109	       "[command..]\n"
110	       "  -h = help (show this usage text)\n"
111	       "  -v = shown version information\n"
112	       "  -a = run in daemon mode executing the action file based on "
113	       "events from\n"
114	       "       wpa_supplicant\n"
115	       "  -B = run a daemon in the background\n"
116	       "  default path: " CONFIG_CTRL_IFACE_DIR "\n"
117	       "  default interface: first interface found in socket path\n");
118	print_help(NULL);
119}
120
121
122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124	dl_list_del(&e->list);
125	os_free(e->txt);
126	os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132	struct cli_txt_entry *e;
133	while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134		cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139					       const char *txt)
140{
141	struct cli_txt_entry *e;
142	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143		if (os_strcmp(e->txt, txt) == 0)
144			return e;
145	}
146	return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152	struct cli_txt_entry *e;
153	e = cli_txt_list_get(txt_list, txt);
154	if (e)
155		cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161	u8 addr[ETH_ALEN];
162	char buf[18];
163	if (hwaddr_aton(txt, addr) < 0)
164		return;
165	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166	cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173	const char *end;
174	char *buf;
175	end = os_strchr(txt, ' ');
176	if (end == NULL)
177		end = txt + os_strlen(txt);
178	buf = dup_binstr(txt, end - txt);
179	if (buf == NULL)
180		return;
181	cli_txt_list_del(txt_list, buf);
182	os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189	struct cli_txt_entry *e;
190	e = cli_txt_list_get(txt_list, txt);
191	if (e)
192		return 0;
193	e = os_zalloc(sizeof(*e));
194	if (e == NULL)
195		return -1;
196	e->txt = os_strdup(txt);
197	if (e->txt == NULL) {
198		os_free(e);
199		return -1;
200	}
201	dl_list_add(txt_list, &e->list);
202	return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209	u8 addr[ETH_ALEN];
210	char buf[18];
211	if (hwaddr_aton(txt, addr) < 0)
212		return -1;
213	os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214	return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220	const char *end;
221	char *buf;
222	int ret;
223	end = os_strchr(txt, ' ');
224	if (end == NULL)
225		end = txt + os_strlen(txt);
226	buf = dup_binstr(txt, end - txt);
227	if (buf == NULL)
228		return -1;
229	ret = cli_txt_list_add(txt_list, buf);
230	os_free(buf);
231	return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238	unsigned int i, count = dl_list_len(txt_list);
239	char **res;
240	struct cli_txt_entry *e;
241
242	res = os_calloc(count + 1, sizeof(char *));
243	if (res == NULL)
244		return NULL;
245
246	i = 0;
247	dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248		res[i] = os_strdup(e->txt);
249		if (res[i] == NULL)
250			break;
251		i++;
252	}
253
254	return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260	int arg = 0, i;
261
262	for (i = 0; i <= pos; i++) {
263		if (str[i] != ' ') {
264			arg++;
265			while (i <= pos && str[i] != ' ')
266				i++;
267		}
268	}
269
270	if (arg > 0)
271		arg--;
272	return arg;
273}
274
275
276static int str_starts(const char *src, const char *match)
277{
278	return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284	const char *start;
285
286	start = os_strchr(event, '>');
287	if (start == NULL)
288		return 1;
289
290	start++;
291	/*
292	 * Skip BSS added/removed events since they can be relatively frequent
293	 * and are likely of not much use for an interactive user.
294	 */
295	if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296	    str_starts(start, WPA_EVENT_BSS_REMOVED))
297		return 0;
298
299	return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306	ctrl_conn = wpa_ctrl_open(ifname);
307	if (ctrl_conn == NULL)
308		return -1;
309
310	if (attach && interactive)
311		mon_conn = wpa_ctrl_open(ifname);
312	else
313		mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315	char *cfile = NULL;
316	int flen, res;
317
318	if (ifname == NULL)
319		return -1;
320
321#ifdef ANDROID
322	if (access(ctrl_iface_dir, F_OK) < 0) {
323		cfile = os_strdup(ifname);
324		if (cfile == NULL)
325			return -1;
326	}
327#endif /* ANDROID */
328
329	if (cfile == NULL) {
330		flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331		cfile = os_malloc(flen);
332		if (cfile == NULL)
333			return -1;
334		res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335				  ifname);
336		if (res < 0 || res >= flen) {
337			os_free(cfile);
338			return -1;
339		}
340	}
341
342	ctrl_conn = wpa_ctrl_open(cfile);
343	if (ctrl_conn == NULL) {
344		os_free(cfile);
345		return -1;
346	}
347
348	if (attach && interactive)
349		mon_conn = wpa_ctrl_open(cfile);
350	else
351		mon_conn = NULL;
352	os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355	if (mon_conn) {
356		if (wpa_ctrl_attach(mon_conn) == 0) {
357			wpa_cli_attached = 1;
358			if (interactive)
359				eloop_register_read_sock(
360					wpa_ctrl_get_fd(mon_conn),
361					wpa_cli_mon_receive, NULL, NULL);
362		} else {
363			printf("Warning: Failed to attach to "
364			       "wpa_supplicant.\n");
365			wpa_cli_close_connection();
366			return -1;
367		}
368	}
369
370	return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376	if (ctrl_conn == NULL)
377		return;
378
379	if (wpa_cli_attached) {
380		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381		wpa_cli_attached = 0;
382	}
383	wpa_ctrl_close(ctrl_conn);
384	ctrl_conn = NULL;
385	if (mon_conn) {
386		eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387		wpa_ctrl_close(mon_conn);
388		mon_conn = NULL;
389	}
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395	printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
401	char buf[4096];
402	size_t len;
403	int ret;
404
405	if (ctrl_conn == NULL) {
406		printf("Not connected to wpa_supplicant - command dropped.\n");
407		return -1;
408	}
409	if (ifname_prefix) {
410		os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411			    ifname_prefix, cmd);
412		buf[sizeof(buf) - 1] = '\0';
413		cmd = buf;
414	}
415	len = sizeof(buf) - 1;
416	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417			       wpa_cli_msg_cb);
418	if (ret == -2) {
419		printf("'%s' command timed out.\n", cmd);
420		return -2;
421	} else if (ret < 0) {
422		printf("'%s' command failed.\n", cmd);
423		return -1;
424	}
425	if (print) {
426		buf[len] = '\0';
427		printf("%s", buf);
428		if (interactive && len > 0 && buf[len - 1] != '\n')
429			printf("\n");
430	}
431	return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437	return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442		     char *argv[])
443{
444	int i, res;
445	char *pos, *end;
446
447	pos = buf;
448	end = buf + buflen;
449
450	res = os_snprintf(pos, end - pos, "%s", cmd);
451	if (res < 0 || res >= end - pos)
452		goto fail;
453	pos += res;
454
455	for (i = 0; i < argc; i++) {
456		res = os_snprintf(pos, end - pos, " %s", argv[i]);
457		if (res < 0 || res >= end - pos)
458			goto fail;
459		pos += res;
460	}
461
462	buf[buflen - 1] = '\0';
463	return 0;
464
465fail:
466	printf("Too long command\n");
467	return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472		       int argc, char *argv[])
473{
474	char buf[4096];
475	if (argc < min_args) {
476		printf("Invalid %s command - at least %d argument%s "
477		       "required.\n", cmd, min_args,
478		       min_args > 1 ? "s are" : " is");
479		return -1;
480	}
481	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482		return -1;
483	return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489	return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
495	if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496		return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497	if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498		return wpa_ctrl_command(ctrl, "STATUS-WPS");
499	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
501	return wpa_ctrl_command(ctrl, "STATUS");
502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507	return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513	return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
519	return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525	return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531	return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
537	print_help(argc > 0 ? argv[0] : NULL);
538	return 0;
539}
540
541
542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544	int arg = get_cmd_arg_num(str, pos);
545	char **res = NULL;
546
547	switch (arg) {
548	case 1:
549		res = wpa_list_cmd_list();
550		break;
551	}
552
553	return res;
554}
555
556
557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559	printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560	return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566	wpa_cli_quit = 1;
567	if (interactive)
568		eloop_terminate();
569	return 0;
570}
571
572
573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575	char cmd[256];
576	int res;
577
578	if (argc == 1) {
579		res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
580		if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581			printf("Too long SET command.\n");
582			return -1;
583		}
584		return wpa_ctrl_command(ctrl, cmd);
585	}
586
587	return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
588}
589
590
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593	int arg = get_cmd_arg_num(str, pos);
594	const char *fields[] = {
595		/* runtime values */
596		"EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597		"EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598		"dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599		"wps_fragment_size", "wps_version_number", "ampdu",
600		"tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601		"uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602		"no_keep_alive",
603		/* global configuration parameters */
604		"eapol_version", "ap_scan", "disable_scan_offload",
605		"fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606		"pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607		"driver_param", "dot11RSNAConfigPMKLifetime",
608		"dot11RSNAConfigPMKReauthThreshold",
609		"dot11RSNAConfigSATimeout",
610		"update_config", "load_dynamic_eap", "uuid", "device_name",
611		"manufacturer", "model_name", "model_number", "serial_number",
612		"device_type", "os_version", "config_methods",
613		"wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614		"p2p_listen_reg_class", "p2p_listen_channel",
615		"p2p_oper_reg_class", "p2p_oper_channel",
616		"p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617		"p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
618		"p2p_no_go_freq",
619		"p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
620		"p2p_go_vht",
621		"p2p_ignore_shared_freq", "country", "bss_max_count",
622		"bss_expiration_age", "bss_expiration_scan_count",
623		"filter_ssids", "filter_rssi", "max_num_sta",
624		"disassoc_low_ack", "hs20", "interworking", "hessid",
625		"access_network_type", "pbc_in_m1", "autoscan",
626		"wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
627		"wps_nfc_dev_pw", "ext_password_backend",
628		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
629		"sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
630		"ignore_old_scan_res", "freq_list", "external_sim",
631		"tdls_external_control", "p2p_search_delay"
632	};
633	int i, num_fields = ARRAY_SIZE(fields);
634
635	if (arg == 1) {
636		char **res = os_calloc(num_fields + 1, sizeof(char *));
637		if (res == NULL)
638			return NULL;
639		for (i = 0; i < num_fields; i++) {
640			res[i] = os_strdup(fields[i]);
641			if (res[i] == NULL)
642				return res;
643		}
644		return res;
645	}
646
647	if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
648		return cli_txt_list_array(&bsses);
649
650	return NULL;
651}
652
653
654static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
656	return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
657}
658
659
660static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
661{
662	return wpa_ctrl_command(ctrl, "LOGOFF");
663}
664
665
666static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
667{
668	return wpa_ctrl_command(ctrl, "LOGON");
669}
670
671
672static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
673				   char *argv[])
674{
675	return wpa_ctrl_command(ctrl, "REASSOCIATE");
676}
677
678
679static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
680{
681	return wpa_ctrl_command(ctrl, "REATTACH");
682}
683
684
685static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
686				       char *argv[])
687{
688	return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
689}
690
691
692static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
693{
694	return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
695}
696
697
698static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
699				     char *argv[])
700{
701	return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
702}
703
704
705static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
706				      char *argv[])
707{
708	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
709}
710
711
712static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
713				        char *argv[])
714{
715	return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
716}
717
718
719static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
720{
721	char cmd[256];
722	int res;
723
724	if (argc < 1)
725		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
726	else
727		res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
728	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
729		printf("Too long BSS_FLUSH command.\n");
730		return -1;
731	}
732	return wpa_ctrl_command(ctrl, cmd);
733}
734
735
736static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
737				char *argv[])
738{
739	return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
740}
741
742
743static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
744{
745	return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
746}
747
748
749static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
750{
751	return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
752}
753
754
755static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
757	if (argc == 0) {
758		printf("Invalid WPS_PIN command: need one or two arguments:\n"
759		       "- BSSID: use 'any' to select any\n"
760		       "- PIN: optional, used only with devices that have no "
761		       "display\n");
762		return -1;
763	}
764
765	return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
766}
767
768
769static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
770				     char *argv[])
771{
772	return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
773}
774
775
776static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
777				  char *argv[])
778{
779	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
780}
781
782
783#ifdef CONFIG_WPS_NFC
784
785static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
786{
787	return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
788}
789
790
791static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
792					    char *argv[])
793{
794	return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
795}
796
797
798static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
799				     char *argv[])
800{
801	return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
802}
803
804
805static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
806					char *argv[])
807{
808	int ret;
809	char *buf;
810	size_t buflen;
811
812	if (argc != 1) {
813		printf("Invalid 'wps_nfc_tag_read' command - one argument "
814		       "is required.\n");
815		return -1;
816	}
817
818	buflen = 18 + os_strlen(argv[0]);
819	buf = os_malloc(buflen);
820	if (buf == NULL)
821		return -1;
822	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
823
824	ret = wpa_ctrl_command(ctrl, buf);
825	os_free(buf);
826
827	return ret;
828}
829
830
831static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
832					    char *argv[])
833{
834	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
835}
836
837
838static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
839					    char *argv[])
840{
841	return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
842}
843
844
845static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
846					   char *argv[])
847{
848	return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
849}
850
851#endif /* CONFIG_WPS_NFC */
852
853
854static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
855{
856	char cmd[256];
857	int res;
858
859	if (argc == 2)
860		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
861				  argv[0], argv[1]);
862	else if (argc == 5 || argc == 6) {
863		char ssid_hex[2 * 32 + 1];
864		char key_hex[2 * 64 + 1];
865		int i;
866
867		ssid_hex[0] = '\0';
868		for (i = 0; i < 32; i++) {
869			if (argv[2][i] == '\0')
870				break;
871			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
872		}
873
874		key_hex[0] = '\0';
875		if (argc == 6) {
876			for (i = 0; i < 64; i++) {
877				if (argv[5][i] == '\0')
878					break;
879				os_snprintf(&key_hex[i * 2], 3, "%02x",
880					    argv[5][i]);
881			}
882		}
883
884		res = os_snprintf(cmd, sizeof(cmd),
885				  "WPS_REG %s %s %s %s %s %s",
886				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
887				  key_hex);
888	} else {
889		printf("Invalid WPS_REG command: need two arguments:\n"
890		       "- BSSID of the target AP\n"
891		       "- AP PIN\n");
892		printf("Alternatively, six arguments can be used to "
893		       "reconfigure the AP:\n"
894		       "- BSSID of the target AP\n"
895		       "- AP PIN\n"
896		       "- new SSID\n"
897		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
898		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
899		       "- new key\n");
900		return -1;
901	}
902
903	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
904		printf("Too long WPS_REG command.\n");
905		return -1;
906	}
907	return wpa_ctrl_command(ctrl, cmd);
908}
909
910
911static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
912				  char *argv[])
913{
914	return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
915}
916
917
918static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
919				    char *argv[])
920{
921	return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
922}
923
924
925static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
926				   char *argv[])
927{
928	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
929
930}
931
932
933static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
934				  char *argv[])
935{
936	if (argc < 2) {
937		printf("Invalid WPS_ER_PIN command: need at least two "
938		       "arguments:\n"
939		       "- UUID: use 'any' to select any\n"
940		       "- PIN: Enrollee PIN\n"
941		       "optional: - Enrollee MAC address\n");
942		return -1;
943	}
944
945	return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
946}
947
948
949static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
950				  char *argv[])
951{
952	return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
953}
954
955
956static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
957				    char *argv[])
958{
959	if (argc != 2) {
960		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
961		       "- UUID: specify which AP to use\n"
962		       "- PIN: AP PIN\n");
963		return -1;
964	}
965
966	return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
967}
968
969
970static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
971					 char *argv[])
972{
973	if (argc != 2) {
974		printf("Invalid WPS_ER_SET_CONFIG command: need two "
975		       "arguments:\n"
976		       "- UUID: specify which AP to use\n"
977		       "- Network configuration id\n");
978		return -1;
979	}
980
981	return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
982}
983
984
985static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
986				     char *argv[])
987{
988	char cmd[256];
989	int res;
990
991	if (argc == 5 || argc == 6) {
992		char ssid_hex[2 * 32 + 1];
993		char key_hex[2 * 64 + 1];
994		int i;
995
996		ssid_hex[0] = '\0';
997		for (i = 0; i < 32; i++) {
998			if (argv[2][i] == '\0')
999				break;
1000			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1001		}
1002
1003		key_hex[0] = '\0';
1004		if (argc == 6) {
1005			for (i = 0; i < 64; i++) {
1006				if (argv[5][i] == '\0')
1007					break;
1008				os_snprintf(&key_hex[i * 2], 3, "%02x",
1009					    argv[5][i]);
1010			}
1011		}
1012
1013		res = os_snprintf(cmd, sizeof(cmd),
1014				  "WPS_ER_CONFIG %s %s %s %s %s %s",
1015				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
1016				  key_hex);
1017	} else {
1018		printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1019		       "- AP UUID\n"
1020		       "- AP PIN\n"
1021		       "- new SSID\n"
1022		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1023		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
1024		       "- new key\n");
1025		return -1;
1026	}
1027
1028	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1029		printf("Too long WPS_ER_CONFIG command.\n");
1030		return -1;
1031	}
1032	return wpa_ctrl_command(ctrl, cmd);
1033}
1034
1035
1036#ifdef CONFIG_WPS_NFC
1037static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1038					       char *argv[])
1039{
1040	if (argc != 2) {
1041		printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1042		       "arguments:\n"
1043		       "- WPS/NDEF: token format\n"
1044		       "- UUID: specify which AP to use\n");
1045		return -1;
1046	}
1047
1048	return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1049}
1050#endif /* CONFIG_WPS_NFC */
1051
1052
1053static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1054{
1055	return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
1056}
1057
1058
1059static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1060{
1061	return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
1062}
1063
1064
1065static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1066{
1067	char cmd[256], *pos, *end;
1068	int i, ret;
1069
1070	if (argc < 2) {
1071		printf("Invalid IDENTITY command: needs two arguments "
1072		       "(network id and identity)\n");
1073		return -1;
1074	}
1075
1076	end = cmd + sizeof(cmd);
1077	pos = cmd;
1078	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1079			  argv[0], argv[1]);
1080	if (ret < 0 || ret >= end - pos) {
1081		printf("Too long IDENTITY command.\n");
1082		return -1;
1083	}
1084	pos += ret;
1085	for (i = 2; i < argc; i++) {
1086		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1087		if (ret < 0 || ret >= end - pos) {
1088			printf("Too long IDENTITY command.\n");
1089			return -1;
1090		}
1091		pos += ret;
1092	}
1093
1094	return wpa_ctrl_command(ctrl, cmd);
1095}
1096
1097
1098static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099{
1100	char cmd[256], *pos, *end;
1101	int i, ret;
1102
1103	if (argc < 2) {
1104		printf("Invalid PASSWORD command: needs two arguments "
1105		       "(network id and password)\n");
1106		return -1;
1107	}
1108
1109	end = cmd + sizeof(cmd);
1110	pos = cmd;
1111	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1112			  argv[0], argv[1]);
1113	if (ret < 0 || ret >= end - pos) {
1114		printf("Too long PASSWORD command.\n");
1115		return -1;
1116	}
1117	pos += ret;
1118	for (i = 2; i < argc; i++) {
1119		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1120		if (ret < 0 || ret >= end - pos) {
1121			printf("Too long PASSWORD command.\n");
1122			return -1;
1123		}
1124		pos += ret;
1125	}
1126
1127	return wpa_ctrl_command(ctrl, cmd);
1128}
1129
1130
1131static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1132				    char *argv[])
1133{
1134	char cmd[256], *pos, *end;
1135	int i, ret;
1136
1137	if (argc < 2) {
1138		printf("Invalid NEW_PASSWORD command: needs two arguments "
1139		       "(network id and password)\n");
1140		return -1;
1141	}
1142
1143	end = cmd + sizeof(cmd);
1144	pos = cmd;
1145	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1146			  argv[0], argv[1]);
1147	if (ret < 0 || ret >= end - pos) {
1148		printf("Too long NEW_PASSWORD command.\n");
1149		return -1;
1150	}
1151	pos += ret;
1152	for (i = 2; i < argc; i++) {
1153		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1154		if (ret < 0 || ret >= end - pos) {
1155			printf("Too long NEW_PASSWORD command.\n");
1156			return -1;
1157		}
1158		pos += ret;
1159	}
1160
1161	return wpa_ctrl_command(ctrl, cmd);
1162}
1163
1164
1165static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1166{
1167	char cmd[256], *pos, *end;
1168	int i, ret;
1169
1170	if (argc < 2) {
1171		printf("Invalid PIN command: needs two arguments "
1172		       "(network id and pin)\n");
1173		return -1;
1174	}
1175
1176	end = cmd + sizeof(cmd);
1177	pos = cmd;
1178	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1179			  argv[0], argv[1]);
1180	if (ret < 0 || ret >= end - pos) {
1181		printf("Too long PIN command.\n");
1182		return -1;
1183	}
1184	pos += ret;
1185	for (i = 2; i < argc; i++) {
1186		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1187		if (ret < 0 || ret >= end - pos) {
1188			printf("Too long PIN command.\n");
1189			return -1;
1190		}
1191		pos += ret;
1192	}
1193	return wpa_ctrl_command(ctrl, cmd);
1194}
1195
1196
1197static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1198{
1199	char cmd[256], *pos, *end;
1200	int i, ret;
1201
1202	if (argc < 2) {
1203		printf("Invalid OTP command: needs two arguments (network "
1204		       "id and password)\n");
1205		return -1;
1206	}
1207
1208	end = cmd + sizeof(cmd);
1209	pos = cmd;
1210	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1211			  argv[0], argv[1]);
1212	if (ret < 0 || ret >= end - pos) {
1213		printf("Too long OTP command.\n");
1214		return -1;
1215	}
1216	pos += ret;
1217	for (i = 2; i < argc; i++) {
1218		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1219		if (ret < 0 || ret >= end - pos) {
1220			printf("Too long OTP command.\n");
1221			return -1;
1222		}
1223		pos += ret;
1224	}
1225
1226	return wpa_ctrl_command(ctrl, cmd);
1227}
1228
1229
1230static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1231{
1232	char cmd[256], *pos, *end;
1233	int i, ret;
1234
1235	if (argc < 2) {
1236		printf("Invalid SIM command: needs two arguments "
1237		       "(network id and SIM operation response)\n");
1238		return -1;
1239	}
1240
1241	end = cmd + sizeof(cmd);
1242	pos = cmd;
1243	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1244			  argv[0], argv[1]);
1245	if (ret < 0 || ret >= end - pos) {
1246		printf("Too long SIM command.\n");
1247		return -1;
1248	}
1249	pos += ret;
1250	for (i = 2; i < argc; i++) {
1251		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1252		if (ret < 0 || ret >= end - pos) {
1253			printf("Too long SIM command.\n");
1254			return -1;
1255		}
1256		pos += ret;
1257	}
1258	return wpa_ctrl_command(ctrl, cmd);
1259}
1260
1261
1262static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1263				  char *argv[])
1264{
1265	char cmd[256], *pos, *end;
1266	int i, ret;
1267
1268	if (argc < 2) {
1269		printf("Invalid PASSPHRASE command: needs two arguments "
1270		       "(network id and passphrase)\n");
1271		return -1;
1272	}
1273
1274	end = cmd + sizeof(cmd);
1275	pos = cmd;
1276	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1277			  argv[0], argv[1]);
1278	if (ret < 0 || ret >= end - pos) {
1279		printf("Too long PASSPHRASE command.\n");
1280		return -1;
1281	}
1282	pos += ret;
1283	for (i = 2; i < argc; i++) {
1284		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1285		if (ret < 0 || ret >= end - pos) {
1286			printf("Too long PASSPHRASE command.\n");
1287			return -1;
1288		}
1289		pos += ret;
1290	}
1291
1292	return wpa_ctrl_command(ctrl, cmd);
1293}
1294
1295
1296static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297{
1298	if (argc < 2) {
1299		printf("Invalid BSSID command: needs two arguments (network "
1300		       "id and BSSID)\n");
1301		return -1;
1302	}
1303
1304	return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
1305}
1306
1307
1308static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1309{
1310	return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1311}
1312
1313
1314static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1315{
1316	return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
1317}
1318
1319
1320static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1321				     char *argv[])
1322{
1323	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1324}
1325
1326
1327static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1328				      char *argv[])
1329{
1330	return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
1331}
1332
1333
1334static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1335				      char *argv[])
1336{
1337	return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
1338}
1339
1340
1341static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1342				       char *argv[])
1343{
1344	return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
1345}
1346
1347
1348static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1349				   char *argv[])
1350{
1351	return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1352}
1353
1354
1355static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1356				      char *argv[])
1357{
1358	return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1359}
1360
1361
1362static void wpa_cli_show_network_variables(void)
1363{
1364	printf("set_network variables:\n"
1365	       "  ssid (network name, SSID)\n"
1366	       "  psk (WPA passphrase or pre-shared key)\n"
1367	       "  key_mgmt (key management protocol)\n"
1368	       "  identity (EAP identity)\n"
1369	       "  password (EAP password)\n"
1370	       "  ...\n"
1371	       "\n"
1372	       "Note: Values are entered in the same format as the "
1373	       "configuration file is using,\n"
1374	       "i.e., strings values need to be inside double quotation "
1375	       "marks.\n"
1376	       "For example: set_network 1 ssid \"network name\"\n"
1377	       "\n"
1378	       "Please see wpa_supplicant.conf documentation for full list "
1379	       "of\navailable variables.\n");
1380}
1381
1382
1383static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1384				   char *argv[])
1385{
1386	if (argc == 0) {
1387		wpa_cli_show_network_variables();
1388		return 0;
1389	}
1390
1391	if (argc < 3) {
1392		printf("Invalid SET_NETWORK command: needs three arguments\n"
1393		       "(network id, variable name, and value)\n");
1394		return -1;
1395	}
1396
1397	return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
1398}
1399
1400
1401static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1402				   char *argv[])
1403{
1404	if (argc == 0) {
1405		wpa_cli_show_network_variables();
1406		return 0;
1407	}
1408
1409	if (argc != 2) {
1410		printf("Invalid GET_NETWORK command: needs two arguments\n"
1411		       "(network id and variable name)\n");
1412		return -1;
1413	}
1414
1415	return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1416}
1417
1418
1419static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1420				   char *argv[])
1421{
1422	if (argc == 0) {
1423		wpa_cli_show_network_variables();
1424		return 0;
1425	}
1426
1427	if (argc < 3) {
1428		printf("Invalid DUP_NETWORK command: needs three arguments\n"
1429		       "(src netid, dest netid, and variable name)\n");
1430		return -1;
1431	}
1432
1433	return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1434}
1435
1436
1437static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1438				  char *argv[])
1439{
1440	return wpa_ctrl_command(ctrl, "LIST_CREDS");
1441}
1442
1443
1444static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1445{
1446	return wpa_ctrl_command(ctrl, "ADD_CRED");
1447}
1448
1449
1450static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1451				   char *argv[])
1452{
1453	return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1454}
1455
1456
1457static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458{
1459	if (argc != 3) {
1460		printf("Invalid SET_CRED command: needs three arguments\n"
1461		       "(cred id, variable name, and value)\n");
1462		return -1;
1463	}
1464
1465	return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
1466}
1467
1468
1469static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1470{
1471	if (argc != 2) {
1472		printf("Invalid GET_CRED command: needs two arguments\n"
1473		       "(cred id, variable name)\n");
1474		return -1;
1475	}
1476
1477	return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1478}
1479
1480
1481static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1482				  char *argv[])
1483{
1484	return wpa_ctrl_command(ctrl, "DISCONNECT");
1485}
1486
1487
1488static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1489				  char *argv[])
1490{
1491	return wpa_ctrl_command(ctrl, "RECONNECT");
1492}
1493
1494
1495static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1496				   char *argv[])
1497{
1498	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1499}
1500
1501
1502static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1503{
1504	return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
1505}
1506
1507
1508static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1509				    char *argv[])
1510{
1511	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1512}
1513
1514
1515static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516{
1517	return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1518}
1519
1520
1521static char ** wpa_cli_complete_bss(const char *str, int pos)
1522{
1523	int arg = get_cmd_arg_num(str, pos);
1524	char **res = NULL;
1525
1526	switch (arg) {
1527	case 1:
1528		res = cli_txt_list_array(&bsses);
1529		break;
1530	}
1531
1532	return res;
1533}
1534
1535
1536static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1537				      char *argv[])
1538{
1539	if (argc < 1 || argc > 2) {
1540		printf("Invalid GET_CAPABILITY command: need either one or "
1541		       "two arguments\n");
1542		return -1;
1543	}
1544
1545	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1546		printf("Invalid GET_CAPABILITY command: second argument, "
1547		       "if any, must be 'strict'\n");
1548		return -1;
1549	}
1550
1551	return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1552}
1553
1554
1555static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1556{
1557	printf("Available interfaces:\n");
1558	return wpa_ctrl_command(ctrl, "INTERFACES");
1559}
1560
1561
1562static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1563{
1564	if (argc < 1) {
1565		wpa_cli_list_interfaces(ctrl);
1566		return 0;
1567	}
1568
1569	wpa_cli_close_connection();
1570	os_free(ctrl_ifname);
1571	ctrl_ifname = os_strdup(argv[0]);
1572
1573	if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
1574		printf("Connected to interface '%s.\n", ctrl_ifname);
1575	} else {
1576		printf("Could not connect to interface '%s' - re-trying\n",
1577		       ctrl_ifname);
1578	}
1579	return 0;
1580}
1581
1582
1583static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1584				   char *argv[])
1585{
1586	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1587}
1588
1589
1590static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1591				 char *argv[])
1592{
1593	return wpa_ctrl_command(ctrl, "TERMINATE");
1594}
1595
1596
1597static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1598				     char *argv[])
1599{
1600	char cmd[256];
1601	int res;
1602
1603	if (argc < 1) {
1604		printf("Invalid INTERFACE_ADD command: needs at least one "
1605		       "argument (interface name)\n"
1606		       "All arguments: ifname confname driver ctrl_interface "
1607		       "driver_param bridge_name\n");
1608		return -1;
1609	}
1610
1611	/*
1612	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1613	 * <driver_param>TAB<bridge_name>
1614	 */
1615	res = os_snprintf(cmd, sizeof(cmd),
1616			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1617			  argv[0],
1618			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1619			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1620			  argc > 5 ? argv[5] : "");
1621	if (res < 0 || (size_t) res >= sizeof(cmd))
1622		return -1;
1623	cmd[sizeof(cmd) - 1] = '\0';
1624	return wpa_ctrl_command(ctrl, cmd);
1625}
1626
1627
1628static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1629					char *argv[])
1630{
1631	return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1632}
1633
1634
1635static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1636				      char *argv[])
1637{
1638	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1639}
1640
1641
1642#ifdef CONFIG_AP
1643static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1644{
1645	return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1646}
1647
1648
1649static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1650				char *addr, size_t addr_len)
1651{
1652	char buf[4096], *pos;
1653	size_t len;
1654	int ret;
1655
1656	if (ctrl_conn == NULL) {
1657		printf("Not connected to hostapd - command dropped.\n");
1658		return -1;
1659	}
1660	len = sizeof(buf) - 1;
1661	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1662			       wpa_cli_msg_cb);
1663	if (ret == -2) {
1664		printf("'%s' command timed out.\n", cmd);
1665		return -2;
1666	} else if (ret < 0) {
1667		printf("'%s' command failed.\n", cmd);
1668		return -1;
1669	}
1670
1671	buf[len] = '\0';
1672	if (os_memcmp(buf, "FAIL", 4) == 0)
1673		return -1;
1674	printf("%s", buf);
1675
1676	pos = buf;
1677	while (*pos != '\0' && *pos != '\n')
1678		pos++;
1679	*pos = '\0';
1680	os_strlcpy(addr, buf, addr_len);
1681	return 0;
1682}
1683
1684
1685static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1686{
1687	char addr[32], cmd[64];
1688
1689	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1690		return 0;
1691	do {
1692		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1693	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1694
1695	return -1;
1696}
1697
1698
1699static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1700				      char *argv[])
1701{
1702	return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1703}
1704
1705
1706static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1707				    char *argv[])
1708{
1709	return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1710}
1711
1712static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1713				    char *argv[])
1714{
1715	return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1716}
1717
1718#endif /* CONFIG_AP */
1719
1720
1721static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1722{
1723	return wpa_ctrl_command(ctrl, "SUSPEND");
1724}
1725
1726
1727static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1728{
1729	return wpa_ctrl_command(ctrl, "RESUME");
1730}
1731
1732
1733#ifdef CONFIG_TESTING_OPTIONS
1734static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1735{
1736	return wpa_ctrl_command(ctrl, "DROP_SA");
1737}
1738#endif /* CONFIG_TESTING_OPTIONS */
1739
1740
1741static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
1743	return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
1744}
1745
1746
1747#ifdef CONFIG_P2P
1748
1749static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1750{
1751	return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1752}
1753
1754
1755static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1756{
1757	char **res = NULL;
1758	int arg = get_cmd_arg_num(str, pos);
1759
1760	res = os_calloc(6, sizeof(char *));
1761	if (res == NULL)
1762		return NULL;
1763	res[0] = os_strdup("type=social");
1764	if (res[0] == NULL) {
1765		os_free(res);
1766		return NULL;
1767	}
1768	res[1] = os_strdup("type=progressive");
1769	if (res[1] == NULL)
1770		return res;
1771	res[2] = os_strdup("delay=");
1772	if (res[2] == NULL)
1773		return res;
1774	res[3] = os_strdup("dev_id=");
1775	if (res[3] == NULL)
1776		return res;
1777	if (arg == 1)
1778		res[4] = os_strdup("[timeout]");
1779
1780	return res;
1781}
1782
1783
1784static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1785				     char *argv[])
1786{
1787	return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1788}
1789
1790
1791static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1792				   char *argv[])
1793{
1794	return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
1795}
1796
1797
1798static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1799{
1800	int arg = get_cmd_arg_num(str, pos);
1801	char **res = NULL;
1802
1803	switch (arg) {
1804	case 1:
1805		res = cli_txt_list_array(&p2p_peers);
1806		break;
1807	}
1808
1809	return res;
1810}
1811
1812
1813static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1814				  char *argv[])
1815{
1816	return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
1817}
1818
1819
1820static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1821					char *argv[])
1822{
1823	return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
1824}
1825
1826
1827static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1828{
1829	int arg = get_cmd_arg_num(str, pos);
1830	char **res = NULL;
1831
1832	switch (arg) {
1833	case 1:
1834		res = cli_txt_list_array(&p2p_groups);
1835		break;
1836	}
1837
1838	return res;
1839}
1840
1841
1842static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1843					char *argv[])
1844{
1845	return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
1846}
1847
1848
1849static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1850				     char *argv[])
1851{
1852	if (argc != 2 && argc != 3) {
1853		printf("Invalid P2P_PROV_DISC command: needs at least "
1854		       "two arguments, address and config method\n"
1855		       "(display, keypad, or pbc) and an optional join\n");
1856		return -1;
1857	}
1858
1859	return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
1860}
1861
1862
1863static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1864					  char *argv[])
1865{
1866	return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1867}
1868
1869
1870static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1871					 char *argv[])
1872{
1873	char cmd[4096];
1874
1875	if (argc != 2 && argc != 4) {
1876		printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1877		       "arguments (address and TLVs) or four arguments "
1878		       "(address, \"upnp\", version, search target "
1879		       "(SSDP ST:)\n");
1880		return -1;
1881	}
1882
1883	if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
1884		return -1;
1885	return wpa_ctrl_command(ctrl, cmd);
1886}
1887
1888
1889static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1890						int argc, char *argv[])
1891{
1892	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
1893}
1894
1895
1896static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1897					  char *argv[])
1898{
1899	char cmd[4096];
1900	int res;
1901
1902	if (argc != 4) {
1903		printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1904		       "arguments (freq, address, dialog token, and TLVs)\n");
1905		return -1;
1906	}
1907
1908	res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1909			  argv[0], argv[1], argv[2], argv[3]);
1910	if (res < 0 || (size_t) res >= sizeof(cmd))
1911		return -1;
1912	cmd[sizeof(cmd) - 1] = '\0';
1913	return wpa_ctrl_command(ctrl, cmd);
1914}
1915
1916
1917static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1918					  char *argv[])
1919{
1920	return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1921}
1922
1923
1924static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1925					      int argc, char *argv[])
1926{
1927	return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
1928}
1929
1930
1931static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1932					 char *argv[])
1933{
1934	return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1935}
1936
1937
1938static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1939				       char *argv[])
1940{
1941	char cmd[4096];
1942	int res;
1943
1944	if (argc != 3 && argc != 4) {
1945		printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1946		       "arguments\n");
1947		return -1;
1948	}
1949
1950	if (argc == 4)
1951		res = os_snprintf(cmd, sizeof(cmd),
1952				  "P2P_SERVICE_ADD %s %s %s %s",
1953				  argv[0], argv[1], argv[2], argv[3]);
1954	else
1955		res = os_snprintf(cmd, sizeof(cmd),
1956				  "P2P_SERVICE_ADD %s %s %s",
1957				  argv[0], argv[1], argv[2]);
1958	if (res < 0 || (size_t) res >= sizeof(cmd))
1959		return -1;
1960	cmd[sizeof(cmd) - 1] = '\0';
1961	return wpa_ctrl_command(ctrl, cmd);
1962}
1963
1964
1965static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1966				       char *argv[])
1967{
1968	char cmd[4096];
1969	int res;
1970
1971	if (argc != 2 && argc != 3) {
1972		printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1973		       "arguments\n");
1974		return -1;
1975	}
1976
1977	if (argc == 3)
1978		res = os_snprintf(cmd, sizeof(cmd),
1979				  "P2P_SERVICE_DEL %s %s %s",
1980				  argv[0], argv[1], argv[2]);
1981	else
1982		res = os_snprintf(cmd, sizeof(cmd),
1983				  "P2P_SERVICE_DEL %s %s",
1984				  argv[0], argv[1]);
1985	if (res < 0 || (size_t) res >= sizeof(cmd))
1986		return -1;
1987	cmd[sizeof(cmd) - 1] = '\0';
1988	return wpa_ctrl_command(ctrl, cmd);
1989}
1990
1991
1992static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1993				  int argc, char *argv[])
1994{
1995	return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
1996}
1997
1998
1999static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2000				  int argc, char *argv[])
2001{
2002	return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
2003}
2004
2005
2006static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2007{
2008	return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
2009}
2010
2011
2012static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2013{
2014	int arg = get_cmd_arg_num(str, pos);
2015	char **res = NULL;
2016
2017	switch (arg) {
2018	case 1:
2019		res = cli_txt_list_array(&p2p_peers);
2020		break;
2021	}
2022
2023	return res;
2024}
2025
2026
2027static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2028				     char *addr, size_t addr_len,
2029				     int discovered)
2030{
2031	char buf[4096], *pos;
2032	size_t len;
2033	int ret;
2034
2035	if (ctrl_conn == NULL)
2036		return -1;
2037	len = sizeof(buf) - 1;
2038	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2039			       wpa_cli_msg_cb);
2040	if (ret == -2) {
2041		printf("'%s' command timed out.\n", cmd);
2042		return -2;
2043	} else if (ret < 0) {
2044		printf("'%s' command failed.\n", cmd);
2045		return -1;
2046	}
2047
2048	buf[len] = '\0';
2049	if (os_memcmp(buf, "FAIL", 4) == 0)
2050		return -1;
2051
2052	pos = buf;
2053	while (*pos != '\0' && *pos != '\n')
2054		pos++;
2055	*pos++ = '\0';
2056	os_strlcpy(addr, buf, addr_len);
2057	if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2058		printf("%s\n", addr);
2059	return 0;
2060}
2061
2062
2063static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2064{
2065	char addr[32], cmd[64];
2066	int discovered;
2067
2068	discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2069
2070	if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2071				      addr, sizeof(addr), discovered))
2072		return -1;
2073	do {
2074		os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2075	} while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2076			 discovered) == 0);
2077
2078	return 0;
2079}
2080
2081
2082static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2083{
2084	return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2085}
2086
2087
2088static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2089{
2090	int arg = get_cmd_arg_num(str, pos);
2091	const char *fields[] = {
2092		"discoverability",
2093		"managed",
2094		"listen_channel",
2095		"ssid_postfix",
2096		"noa",
2097		"ps",
2098		"oppps",
2099		"ctwindow",
2100		"disabled",
2101		"conc_pref",
2102		"force_long_sd",
2103		"peer_filter",
2104		"cross_connect",
2105		"go_apsd",
2106		"client_apsd",
2107		"disallow_freq",
2108		"disc_int",
2109		"per_sta_psk",
2110	};
2111	int i, num_fields = ARRAY_SIZE(fields);
2112
2113	if (arg == 1) {
2114		char **res = os_calloc(num_fields + 1, sizeof(char *));
2115		if (res == NULL)
2116			return NULL;
2117		for (i = 0; i < num_fields; i++) {
2118			res[i] = os_strdup(fields[i]);
2119			if (res[i] == NULL)
2120				return res;
2121		}
2122		return res;
2123	}
2124
2125	if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2126		return cli_txt_list_array(&p2p_peers);
2127
2128	return NULL;
2129}
2130
2131
2132static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2133{
2134	return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2135}
2136
2137
2138static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2139				  char *argv[])
2140{
2141	return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2142}
2143
2144
2145static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2146				       char *argv[])
2147{
2148	return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2149}
2150
2151
2152static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2153					char *argv[])
2154{
2155	if (argc != 0 && argc != 2 && argc != 4) {
2156		printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2157		       "(preferred duration, interval; in microsecods).\n"
2158		       "Optional second pair can be used to provide "
2159		       "acceptable values.\n");
2160		return -1;
2161	}
2162
2163	return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2164}
2165
2166
2167static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2168				      char *argv[])
2169{
2170	if (argc != 0 && argc != 2) {
2171		printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2172		       "(availability period, availability interval; in "
2173		       "millisecods).\n"
2174		       "Extended Listen Timing can be cancelled with this "
2175		       "command when used without parameters.\n");
2176		return -1;
2177	}
2178
2179	return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2180}
2181
2182
2183static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2184					 char *argv[])
2185{
2186	return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2187}
2188
2189#endif /* CONFIG_P2P */
2190
2191#ifdef CONFIG_WIFI_DISPLAY
2192
2193static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2194				       char *argv[])
2195{
2196	char cmd[100];
2197	int res;
2198
2199	if (argc != 1 && argc != 2) {
2200		printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2201		       "arguments (subelem, hexdump)\n");
2202		return -1;
2203	}
2204
2205	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2206			  argv[0], argc > 1 ? argv[1] : "");
2207	if (res < 0 || (size_t) res >= sizeof(cmd))
2208		return -1;
2209	cmd[sizeof(cmd) - 1] = '\0';
2210	return wpa_ctrl_command(ctrl, cmd);
2211}
2212
2213
2214static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2215				       char *argv[])
2216{
2217	char cmd[100];
2218	int res;
2219
2220	if (argc != 1) {
2221		printf("Invalid WFD_SUBELEM_GET command: needs one "
2222		       "argument (subelem)\n");
2223		return -1;
2224	}
2225
2226	res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2227			  argv[0]);
2228	if (res < 0 || (size_t) res >= sizeof(cmd))
2229		return -1;
2230	cmd[sizeof(cmd) - 1] = '\0';
2231	return wpa_ctrl_command(ctrl, cmd);
2232}
2233#endif /* CONFIG_WIFI_DISPLAY */
2234
2235
2236#ifdef CONFIG_INTERWORKING
2237static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2238				  char *argv[])
2239{
2240	return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2241}
2242
2243
2244static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2245				       char *argv[])
2246{
2247	return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2248}
2249
2250
2251static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2252					   char *argv[])
2253{
2254	return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2255}
2256
2257
2258static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2259					    char *argv[])
2260{
2261	return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2262}
2263
2264
2265static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2266{
2267	return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2268}
2269
2270
2271static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2272				   char *argv[])
2273{
2274	return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2275}
2276
2277
2278static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2279					char *argv[])
2280{
2281	return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2282}
2283#endif /* CONFIG_INTERWORKING */
2284
2285
2286#ifdef CONFIG_HS20
2287
2288static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2289				     char *argv[])
2290{
2291	return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2292}
2293
2294
2295static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2296					       char *argv[])
2297{
2298	char cmd[512];
2299
2300	if (argc == 0) {
2301		printf("Command needs one or two arguments (dst mac addr and "
2302		       "optional home realm)\n");
2303		return -1;
2304	}
2305
2306	if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2307		      argc, argv) < 0)
2308		return -1;
2309
2310	return wpa_ctrl_command(ctrl, cmd);
2311}
2312
2313
2314static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2315					 char *argv[])
2316{
2317	char cmd[512];
2318
2319	if (argc < 2) {
2320		printf("Command needs two arguments (dst mac addr and "
2321		       "icon name)\n");
2322		return -1;
2323	}
2324
2325	if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2326		return -1;
2327
2328	return wpa_ctrl_command(ctrl, cmd);
2329}
2330
2331
2332static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2333{
2334	return wpa_ctrl_command(ctrl, "FETCH_OSU");
2335}
2336
2337
2338static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2339					char *argv[])
2340{
2341	return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2342}
2343
2344#endif /* CONFIG_HS20 */
2345
2346
2347static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2348				       char *argv[])
2349{
2350	return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2351}
2352
2353
2354static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2355				     char *argv[])
2356{
2357	return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2358}
2359
2360
2361static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2362				  char *argv[])
2363{
2364	return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2365}
2366
2367
2368static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2369				     char *argv[])
2370{
2371	return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2372}
2373
2374
2375static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2376				   char *argv[])
2377{
2378	return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2379}
2380
2381
2382static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2383				   char *argv[])
2384{
2385	return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2386}
2387
2388
2389static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2390				      char *argv[])
2391{
2392	return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2393}
2394
2395
2396#ifdef CONFIG_AUTOSCAN
2397
2398static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2399{
2400	if (argc == 0)
2401		return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2402
2403	return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2404}
2405
2406#endif /* CONFIG_AUTOSCAN */
2407
2408
2409#ifdef CONFIG_WNM
2410
2411static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2412{
2413	return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2414}
2415
2416
2417static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2418{
2419	return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2420}
2421
2422#endif /* CONFIG_WNM */
2423
2424
2425static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2426{
2427	if (argc == 0)
2428		return -1;
2429	return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2430}
2431
2432
2433#ifdef ANDROID
2434static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2435{
2436	return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2437}
2438#endif /* ANDROID */
2439
2440
2441static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2442{
2443	return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2444}
2445
2446
2447static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2448{
2449	return wpa_ctrl_command(ctrl, "FLUSH");
2450}
2451
2452
2453static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2454{
2455	return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2456}
2457
2458
2459enum wpa_cli_cmd_flags {
2460	cli_cmd_flag_none		= 0x00,
2461	cli_cmd_flag_sensitive		= 0x01
2462};
2463
2464struct wpa_cli_cmd {
2465	const char *cmd;
2466	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2467	char ** (*completion)(const char *str, int pos);
2468	enum wpa_cli_cmd_flags flags;
2469	const char *usage;
2470};
2471
2472static struct wpa_cli_cmd wpa_cli_commands[] = {
2473	{ "status", wpa_cli_cmd_status, NULL,
2474	  cli_cmd_flag_none,
2475	  "[verbose] = get current WPA/EAPOL/EAP status" },
2476	{ "ifname", wpa_cli_cmd_ifname, NULL,
2477	  cli_cmd_flag_none,
2478	  "= get current interface name" },
2479	{ "ping", wpa_cli_cmd_ping, NULL,
2480	  cli_cmd_flag_none,
2481	  "= pings wpa_supplicant" },
2482	{ "relog", wpa_cli_cmd_relog, NULL,
2483	  cli_cmd_flag_none,
2484	  "= re-open log-file (allow rolling logs)" },
2485	{ "note", wpa_cli_cmd_note, NULL,
2486	  cli_cmd_flag_none,
2487	  "<text> = add a note to wpa_supplicant debug log" },
2488	{ "mib", wpa_cli_cmd_mib, NULL,
2489	  cli_cmd_flag_none,
2490	  "= get MIB variables (dot1x, dot11)" },
2491	{ "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2492	  cli_cmd_flag_none,
2493	  "[command] = show usage help" },
2494	{ "interface", wpa_cli_cmd_interface, NULL,
2495	  cli_cmd_flag_none,
2496	  "[ifname] = show interfaces/select interface" },
2497	{ "level", wpa_cli_cmd_level, NULL,
2498	  cli_cmd_flag_none,
2499	  "<debug level> = change debug level" },
2500	{ "license", wpa_cli_cmd_license, NULL,
2501	  cli_cmd_flag_none,
2502	  "= show full wpa_cli license" },
2503	{ "quit", wpa_cli_cmd_quit, NULL,
2504	  cli_cmd_flag_none,
2505	  "= exit wpa_cli" },
2506	{ "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2507	  cli_cmd_flag_none,
2508	  "= set variables (shows list of variables when run without "
2509	  "arguments)" },
2510	{ "get", wpa_cli_cmd_get, NULL,
2511	  cli_cmd_flag_none,
2512	  "<name> = get information" },
2513	{ "logon", wpa_cli_cmd_logon, NULL,
2514	  cli_cmd_flag_none,
2515	  "= IEEE 802.1X EAPOL state machine logon" },
2516	{ "logoff", wpa_cli_cmd_logoff, NULL,
2517	  cli_cmd_flag_none,
2518	  "= IEEE 802.1X EAPOL state machine logoff" },
2519	{ "pmksa", wpa_cli_cmd_pmksa, NULL,
2520	  cli_cmd_flag_none,
2521	  "= show PMKSA cache" },
2522	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
2523	  cli_cmd_flag_none,
2524	  "= force reassociation" },
2525	{ "reattach", wpa_cli_cmd_reattach, NULL,
2526	  cli_cmd_flag_none,
2527	  "= force reassociation back to the same BSS" },
2528	{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2529	  cli_cmd_flag_none,
2530	  "<BSSID> = force preauthentication" },
2531	{ "identity", wpa_cli_cmd_identity, NULL,
2532	  cli_cmd_flag_none,
2533	  "<network id> <identity> = configure identity for an SSID" },
2534	{ "password", wpa_cli_cmd_password, NULL,
2535	  cli_cmd_flag_sensitive,
2536	  "<network id> <password> = configure password for an SSID" },
2537	{ "new_password", wpa_cli_cmd_new_password, NULL,
2538	  cli_cmd_flag_sensitive,
2539	  "<network id> <password> = change password for an SSID" },
2540	{ "pin", wpa_cli_cmd_pin, NULL,
2541	  cli_cmd_flag_sensitive,
2542	  "<network id> <pin> = configure pin for an SSID" },
2543	{ "otp", wpa_cli_cmd_otp, NULL,
2544	  cli_cmd_flag_sensitive,
2545	  "<network id> <password> = configure one-time-password for an SSID"
2546	},
2547	{ "passphrase", wpa_cli_cmd_passphrase, NULL,
2548	  cli_cmd_flag_sensitive,
2549	  "<network id> <passphrase> = configure private key passphrase\n"
2550	  "  for an SSID" },
2551	{ "sim", wpa_cli_cmd_sim, NULL,
2552	  cli_cmd_flag_sensitive,
2553	  "<network id> <pin> = report SIM operation result" },
2554	{ "bssid", wpa_cli_cmd_bssid, NULL,
2555	  cli_cmd_flag_none,
2556	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
2557	{ "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2558	  cli_cmd_flag_none,
2559	  "<BSSID> = add a BSSID to the blacklist\n"
2560	  "blacklist clear = clear the blacklist\n"
2561	  "blacklist = display the blacklist" },
2562	{ "log_level", wpa_cli_cmd_log_level, NULL,
2563	  cli_cmd_flag_none,
2564	  "<level> [<timestamp>] = update the log level/timestamp\n"
2565	  "log_level = display the current log level and log options" },
2566	{ "list_networks", wpa_cli_cmd_list_networks, NULL,
2567	  cli_cmd_flag_none,
2568	  "= list configured networks" },
2569	{ "select_network", wpa_cli_cmd_select_network, NULL,
2570	  cli_cmd_flag_none,
2571	  "<network id> = select a network (disable others)" },
2572	{ "enable_network", wpa_cli_cmd_enable_network, NULL,
2573	  cli_cmd_flag_none,
2574	  "<network id> = enable a network" },
2575	{ "disable_network", wpa_cli_cmd_disable_network, NULL,
2576	  cli_cmd_flag_none,
2577	  "<network id> = disable a network" },
2578	{ "add_network", wpa_cli_cmd_add_network, NULL,
2579	  cli_cmd_flag_none,
2580	  "= add a network" },
2581	{ "remove_network", wpa_cli_cmd_remove_network, NULL,
2582	  cli_cmd_flag_none,
2583	  "<network id> = remove a network" },
2584	{ "set_network", wpa_cli_cmd_set_network, NULL,
2585	  cli_cmd_flag_sensitive,
2586	  "<network id> <variable> <value> = set network variables (shows\n"
2587	  "  list of variables when run without arguments)" },
2588	{ "get_network", wpa_cli_cmd_get_network, NULL,
2589	  cli_cmd_flag_none,
2590	  "<network id> <variable> = get network variables" },
2591	{ "dup_network", wpa_cli_cmd_dup_network, NULL,
2592	  cli_cmd_flag_none,
2593	  "<src network id> <dst network id> <variable> = duplicate network variables"
2594	},
2595	{ "list_creds", wpa_cli_cmd_list_creds, NULL,
2596	  cli_cmd_flag_none,
2597	  "= list configured credentials" },
2598	{ "add_cred", wpa_cli_cmd_add_cred, NULL,
2599	  cli_cmd_flag_none,
2600	  "= add a credential" },
2601	{ "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2602	  cli_cmd_flag_none,
2603	  "<cred id> = remove a credential" },
2604	{ "set_cred", wpa_cli_cmd_set_cred, NULL,
2605	  cli_cmd_flag_sensitive,
2606	  "<cred id> <variable> <value> = set credential variables" },
2607	{ "get_cred", wpa_cli_cmd_get_cred, NULL,
2608	  cli_cmd_flag_none,
2609	  "<cred id> <variable> = get credential variables" },
2610	{ "save_config", wpa_cli_cmd_save_config, NULL,
2611	  cli_cmd_flag_none,
2612	  "= save the current configuration" },
2613	{ "disconnect", wpa_cli_cmd_disconnect, NULL,
2614	  cli_cmd_flag_none,
2615	  "= disconnect and wait for reassociate/reconnect command before\n"
2616	  "  connecting" },
2617	{ "reconnect", wpa_cli_cmd_reconnect, NULL,
2618	  cli_cmd_flag_none,
2619	  "= like reassociate, but only takes effect if already disconnected"
2620	},
2621	{ "scan", wpa_cli_cmd_scan, NULL,
2622	  cli_cmd_flag_none,
2623	  "= request new BSS scan" },
2624	{ "scan_results", wpa_cli_cmd_scan_results, NULL,
2625	  cli_cmd_flag_none,
2626	  "= get latest scan results" },
2627	{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2628	  cli_cmd_flag_none,
2629	  "<<idx> | <bssid>> = get detailed scan result info" },
2630	{ "get_capability", wpa_cli_cmd_get_capability, NULL,
2631	  cli_cmd_flag_none,
2632	  "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
2633	  "= get capabilies" },
2634	{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2635	  cli_cmd_flag_none,
2636	  "= force wpa_supplicant to re-read its configuration file" },
2637	{ "terminate", wpa_cli_cmd_terminate, NULL,
2638	  cli_cmd_flag_none,
2639	  "= terminate wpa_supplicant" },
2640	{ "interface_add", wpa_cli_cmd_interface_add, NULL,
2641	  cli_cmd_flag_none,
2642	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2643	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2644	  "  are optional" },
2645	{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2646	  cli_cmd_flag_none,
2647	  "<ifname> = removes the interface" },
2648	{ "interface_list", wpa_cli_cmd_interface_list, NULL,
2649	  cli_cmd_flag_none,
2650	  "= list available interfaces" },
2651	{ "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2652	  cli_cmd_flag_none,
2653	  "<value> = set ap_scan parameter" },
2654	{ "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2655	  cli_cmd_flag_none,
2656	  "<value> = set scan_interval parameter (in seconds)" },
2657	{ "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2658	  cli_cmd_flag_none,
2659	  "<value> = set BSS expiration age parameter" },
2660	{ "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2661	  cli_cmd_flag_none,
2662	  "<value> = set BSS expiration scan count parameter" },
2663	{ "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2664	  cli_cmd_flag_none,
2665	  "<value> = set BSS flush age (0 by default)" },
2666	{ "stkstart", wpa_cli_cmd_stkstart, NULL,
2667	  cli_cmd_flag_none,
2668	  "<addr> = request STK negotiation with <addr>" },
2669	{ "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2670	  cli_cmd_flag_none,
2671	  "<addr> = request over-the-DS FT with <addr>" },
2672	{ "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2673	  cli_cmd_flag_none,
2674	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2675	{ "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2676	  cli_cmd_flag_sensitive,
2677	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2678	  "hardcoded)" },
2679	{ "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2680	  cli_cmd_flag_sensitive,
2681	  "<PIN> = verify PIN checksum" },
2682	{ "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2683	  "Cancels the pending WPS operation" },
2684#ifdef CONFIG_WPS_NFC
2685	{ "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2686	  cli_cmd_flag_none,
2687	  "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2688	{ "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2689	  cli_cmd_flag_none,
2690	  "<WPS|NDEF> = build configuration token" },
2691	{ "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2692	  cli_cmd_flag_none,
2693	  "<WPS|NDEF> = create password token" },
2694	{ "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2695	  cli_cmd_flag_sensitive,
2696	  "<hexdump of payload> = report read NFC tag with WPS data" },
2697	{ "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2698	  cli_cmd_flag_none,
2699	  "<NDEF> <WPS> = create NFC handover request" },
2700	{ "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2701	  cli_cmd_flag_none,
2702	  "<NDEF> <WPS> = create NFC handover select" },
2703	{ "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2704	  cli_cmd_flag_none,
2705	  "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2706	  "NFC handover" },
2707#endif /* CONFIG_WPS_NFC */
2708	{ "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2709	  cli_cmd_flag_sensitive,
2710	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2711	{ "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2712	  cli_cmd_flag_sensitive,
2713	  "[params..] = enable/disable AP PIN" },
2714	{ "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2715	  cli_cmd_flag_none,
2716	  "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2717	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2718	  cli_cmd_flag_none,
2719	  "= stop Wi-Fi Protected Setup External Registrar" },
2720	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2721	  cli_cmd_flag_sensitive,
2722	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2723	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2724	  cli_cmd_flag_none,
2725	  "<UUID> = accept an Enrollee PBC using External Registrar" },
2726	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2727	  cli_cmd_flag_sensitive,
2728	  "<UUID> <PIN> = learn AP configuration" },
2729	{ "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2730	  cli_cmd_flag_none,
2731	  "<UUID> <network id> = set AP configuration for enrolling" },
2732	{ "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2733	  cli_cmd_flag_sensitive,
2734	  "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2735#ifdef CONFIG_WPS_NFC
2736	{ "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2737	  cli_cmd_flag_none,
2738	  "<WPS/NDEF> <UUID> = build NFC configuration token" },
2739#endif /* CONFIG_WPS_NFC */
2740	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2741	  cli_cmd_flag_none,
2742	  "<addr> = request RSN authentication with <addr> in IBSS" },
2743#ifdef CONFIG_AP
2744	{ "sta", wpa_cli_cmd_sta, NULL,
2745	  cli_cmd_flag_none,
2746	  "<addr> = get information about an associated station (AP)" },
2747	{ "all_sta", wpa_cli_cmd_all_sta, NULL,
2748	  cli_cmd_flag_none,
2749	  "= get information about all associated stations (AP)" },
2750	{ "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2751	  cli_cmd_flag_none,
2752	  "<addr> = deauthenticate a station" },
2753	{ "disassociate", wpa_cli_cmd_disassociate, NULL,
2754	  cli_cmd_flag_none,
2755	  "<addr> = disassociate a station" },
2756	{ "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2757	  cli_cmd_flag_none,
2758	  "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2759	  " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2760	  " = CSA parameters" },
2761#endif /* CONFIG_AP */
2762	{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2763	  "= notification of suspend/hibernate" },
2764	{ "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2765	  "= notification of resume/thaw" },
2766#ifdef CONFIG_TESTING_OPTIONS
2767	{ "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2768	  "= drop SA without deauth/disassoc (test command)" },
2769#endif /* CONFIG_TESTING_OPTIONS */
2770	{ "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2771	  cli_cmd_flag_none,
2772	  "<addr> = roam to the specified BSS" },
2773#ifdef CONFIG_P2P
2774	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2775	  cli_cmd_flag_none,
2776	  "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2777	{ "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2778	  "= stop P2P Devices search" },
2779	{ "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2780	  cli_cmd_flag_none,
2781	  "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2782	{ "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2783	  "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2784	{ "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2785	  wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2786	  "<ifname> = remove P2P group interface (terminate group if GO)" },
2787	{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2788	  "[ht40] = add a new P2P group (local end as GO)" },
2789	{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2790	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2791	  "<addr> <method> = request provisioning discovery" },
2792	{ "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2793	  cli_cmd_flag_none,
2794	  "= get the passphrase for a group (GO only)" },
2795	{ "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2796	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2797	  "<addr> <TLVs> = schedule service discovery request" },
2798	{ "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2799	  NULL, cli_cmd_flag_none,
2800	  "<id> = cancel pending service discovery request" },
2801	{ "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2802	  cli_cmd_flag_none,
2803	  "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2804	{ "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2805	  cli_cmd_flag_none,
2806	  "= indicate change in local services" },
2807	{ "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2808	  cli_cmd_flag_none,
2809	  "<external> = set external processing of service discovery" },
2810	{ "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2811	  cli_cmd_flag_none,
2812	  "= remove all stored service entries" },
2813	{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2814	  cli_cmd_flag_none,
2815	  "<bonjour|upnp> <query|version> <response|service> = add a local "
2816	  "service" },
2817	{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2818	  cli_cmd_flag_none,
2819	  "<bonjour|upnp> <query|version> [|service] = remove a local "
2820	  "service" },
2821	{ "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2822	  cli_cmd_flag_none,
2823	  "<addr> = reject connection attempts from a specific peer" },
2824	{ "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2825	  cli_cmd_flag_none,
2826	  "<cmd> [peer=addr] = invite peer" },
2827	{ "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2828	  "[discovered] = list known (optionally, only fully discovered) P2P "
2829	  "peers" },
2830	{ "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2831	  cli_cmd_flag_none,
2832	  "<address> = show information about known P2P peer" },
2833	{ "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2834	  cli_cmd_flag_none,
2835	  "<field> <value> = set a P2P parameter" },
2836	{ "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2837	  "= flush P2P state" },
2838	{ "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2839	  "= cancel P2P group formation" },
2840	{ "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2841	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2842	  "<address> = unauthorize a peer" },
2843	{ "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2844	  cli_cmd_flag_none,
2845	  "[<duration> <interval>] [<duration> <interval>] = request GO "
2846	  "presence" },
2847	{ "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2848	  cli_cmd_flag_none,
2849	  "[<period> <interval>] = set extended listen timing" },
2850	{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2851	  wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2852	  "<address|iface=address> = remove a peer from all groups" },
2853#endif /* CONFIG_P2P */
2854#ifdef CONFIG_WIFI_DISPLAY
2855	{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2856	  cli_cmd_flag_none,
2857	  "<subelem> [contents] = set Wi-Fi Display subelement" },
2858	{ "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2859	  cli_cmd_flag_none,
2860	  "<subelem> = get Wi-Fi Display subelement" },
2861#endif /* CONFIG_WIFI_DISPLAY */
2862#ifdef CONFIG_INTERWORKING
2863	{ "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
2864	  "= fetch ANQP information for all APs" },
2865	{ "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2866	  cli_cmd_flag_none,
2867	  "= stop fetch_anqp operation" },
2868	{ "interworking_select", wpa_cli_cmd_interworking_select, NULL,
2869	  cli_cmd_flag_none,
2870	  "[auto] = perform Interworking network selection" },
2871	{ "interworking_connect", wpa_cli_cmd_interworking_connect,
2872	  wpa_cli_complete_bss, cli_cmd_flag_none,
2873	  "<BSSID> = connect using Interworking credentials" },
2874	{ "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2875	  cli_cmd_flag_none,
2876	  "<addr> <info id>[,<info id>]... = request ANQP information" },
2877	{ "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2878	  cli_cmd_flag_none,
2879	  "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2880	{ "gas_response_get", wpa_cli_cmd_gas_response_get,
2881	  wpa_cli_complete_bss, cli_cmd_flag_none,
2882	  "<addr> <dialog token> [start,len] = Fetch last GAS response" },
2883#endif /* CONFIG_INTERWORKING */
2884#ifdef CONFIG_HS20
2885	{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2886	  cli_cmd_flag_none,
2887	  "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2888	},
2889	{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
2890	  wpa_cli_complete_bss, cli_cmd_flag_none,
2891	  "<addr> <home realm> = get HS20 nai home realm list" },
2892	{ "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2893	  wpa_cli_complete_bss, cli_cmd_flag_none,
2894	  "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
2895	{ "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2896	  "= fetch OSU provider information from all APs" },
2897	{ "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2898	  cli_cmd_flag_none,
2899	  "= cancel fetch_osu command" },
2900#endif /* CONFIG_HS20 */
2901	{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2902	  cli_cmd_flag_none,
2903	  "<0/1> = disable/enable automatic reconnection" },
2904	{ "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
2905	  cli_cmd_flag_none,
2906	  "<addr> = request TDLS discovery with <addr>" },
2907	{ "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
2908	  cli_cmd_flag_none,
2909	  "<addr> = request TDLS setup with <addr>" },
2910	{ "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
2911	  cli_cmd_flag_none,
2912	  "<addr> = tear down TDLS with <addr>" },
2913	{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
2914	  cli_cmd_flag_none,
2915	  "= get signal parameters" },
2916	{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
2917	  cli_cmd_flag_none,
2918	  "= get TX/RX packet counters" },
2919	{ "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2920	  cli_cmd_flag_none,
2921	  "= trigger IEEE 802.1X/EAPOL reauthentication" },
2922#ifdef CONFIG_AUTOSCAN
2923	{ "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2924	  "[params] = Set or unset (if none) autoscan parameters" },
2925#endif /* CONFIG_AUTOSCAN */
2926#ifdef CONFIG_WNM
2927	{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2928	  "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2929	{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2930	  "<query reason> = Send BSS Transition Management Query" },
2931#endif /* CONFIG_WNM */
2932	{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2933	  "<params..> = Sent unprocessed command" },
2934	{ "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2935	  "= flush wpa_supplicant state" },
2936#ifdef ANDROID
2937	{ "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
2938	  "<command> = driver private commands" },
2939#endif /* ANDROID */
2940	{ "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2941	  "= radio_work <show/add/done>" },
2942	{ "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2943	  "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2944	},
2945	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
2946};
2947
2948
2949/*
2950 * Prints command usage, lines are padded with the specified string.
2951 */
2952static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2953{
2954	char c;
2955	size_t n;
2956
2957	printf("%s%s ", pad, cmd->cmd);
2958	for (n = 0; (c = cmd->usage[n]); n++) {
2959		printf("%c", c);
2960		if (c == '\n')
2961			printf("%s", pad);
2962	}
2963	printf("\n");
2964}
2965
2966
2967static void print_help(const char *cmd)
2968{
2969	int n;
2970	printf("commands:\n");
2971	for (n = 0; wpa_cli_commands[n].cmd; n++) {
2972		if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2973			print_cmd_help(&wpa_cli_commands[n], "  ");
2974	}
2975}
2976
2977
2978static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2979{
2980	const char *c, *delim;
2981	int n;
2982	size_t len;
2983
2984	delim = os_strchr(cmd, ' ');
2985	if (delim)
2986		len = delim - cmd;
2987	else
2988		len = os_strlen(cmd);
2989
2990	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2991		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2992			return (wpa_cli_commands[n].flags &
2993				cli_cmd_flag_sensitive);
2994	}
2995	return 0;
2996}
2997
2998
2999static char ** wpa_list_cmd_list(void)
3000{
3001	char **res;
3002	int i, count;
3003	struct cli_txt_entry *e;
3004
3005	count = ARRAY_SIZE(wpa_cli_commands);
3006	count += dl_list_len(&p2p_groups);
3007	count += dl_list_len(&ifnames);
3008	res = os_calloc(count + 1, sizeof(char *));
3009	if (res == NULL)
3010		return NULL;
3011
3012	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3013		res[i] = os_strdup(wpa_cli_commands[i].cmd);
3014		if (res[i] == NULL)
3015			break;
3016	}
3017
3018	dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3019		size_t len = 8 + os_strlen(e->txt);
3020		res[i] = os_malloc(len);
3021		if (res[i] == NULL)
3022			break;
3023		os_snprintf(res[i], len, "ifname=%s", e->txt);
3024		i++;
3025	}
3026
3027	dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3028		res[i] = os_strdup(e->txt);
3029		if (res[i] == NULL)
3030			break;
3031		i++;
3032	}
3033
3034	return res;
3035}
3036
3037
3038static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3039				      int pos)
3040{
3041	int i;
3042
3043	for (i = 0; wpa_cli_commands[i].cmd; i++) {
3044		if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3045			if (wpa_cli_commands[i].completion)
3046				return wpa_cli_commands[i].completion(str,
3047								      pos);
3048			edit_clear_line();
3049			printf("\r%s\n", wpa_cli_commands[i].usage);
3050			edit_redraw();
3051			break;
3052		}
3053	}
3054
3055	return NULL;
3056}
3057
3058
3059static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3060{
3061	char **res;
3062	const char *end;
3063	char *cmd;
3064
3065	if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3066		end = os_strchr(str, ' ');
3067		if (end && pos > end - str) {
3068			pos -= end - str + 1;
3069			str = end + 1;
3070		}
3071	}
3072
3073	end = os_strchr(str, ' ');
3074	if (end == NULL || str + pos < end)
3075		return wpa_list_cmd_list();
3076
3077	cmd = os_malloc(pos + 1);
3078	if (cmd == NULL)
3079		return NULL;
3080	os_memcpy(cmd, str, pos);
3081	cmd[end - str] = '\0';
3082	res = wpa_cli_cmd_completion(cmd, str, pos);
3083	os_free(cmd);
3084	return res;
3085}
3086
3087
3088static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3089{
3090	struct wpa_cli_cmd *cmd, *match = NULL;
3091	int count;
3092	int ret = 0;
3093
3094	if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3095		ifname_prefix = argv[0] + 7;
3096		argv = &argv[1];
3097		argc--;
3098	} else
3099		ifname_prefix = NULL;
3100
3101	if (argc == 0)
3102		return -1;
3103
3104	count = 0;
3105	cmd = wpa_cli_commands;
3106	while (cmd->cmd) {
3107		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3108		{
3109			match = cmd;
3110			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3111				/* we have an exact match */
3112				count = 1;
3113				break;
3114			}
3115			count++;
3116		}
3117		cmd++;
3118	}
3119
3120	if (count > 1) {
3121		printf("Ambiguous command '%s'; possible commands:", argv[0]);
3122		cmd = wpa_cli_commands;
3123		while (cmd->cmd) {
3124			if (os_strncasecmp(cmd->cmd, argv[0],
3125					   os_strlen(argv[0])) == 0) {
3126				printf(" %s", cmd->cmd);
3127			}
3128			cmd++;
3129		}
3130		printf("\n");
3131		ret = 1;
3132	} else if (count == 0) {
3133		printf("Unknown command '%s'\n", argv[0]);
3134		ret = 1;
3135	} else {
3136		ret = match->handler(ctrl, argc - 1, &argv[1]);
3137	}
3138
3139	return ret;
3140}
3141
3142
3143static int str_match(const char *a, const char *b)
3144{
3145	return os_strncmp(a, b, os_strlen(b)) == 0;
3146}
3147
3148
3149static int wpa_cli_exec(const char *program, const char *arg1,
3150			const char *arg2)
3151{
3152	char *arg;
3153	size_t len;
3154	int res;
3155
3156	len = os_strlen(arg1) + os_strlen(arg2) + 2;
3157	arg = os_malloc(len);
3158	if (arg == NULL)
3159		return -1;
3160	os_snprintf(arg, len, "%s %s", arg1, arg2);
3161	res = os_exec(program, arg, 1);
3162	os_free(arg);
3163
3164	return res;
3165}
3166
3167
3168static void wpa_cli_action_process(const char *msg)
3169{
3170	const char *pos;
3171	char *copy = NULL, *id, *pos2;
3172
3173	pos = msg;
3174	if (*pos == '<') {
3175		/* skip priority */
3176		pos = os_strchr(pos, '>');
3177		if (pos)
3178			pos++;
3179		else
3180			pos = msg;
3181	}
3182
3183	if (str_match(pos, WPA_EVENT_CONNECTED)) {
3184		int new_id = -1;
3185		os_unsetenv("WPA_ID");
3186		os_unsetenv("WPA_ID_STR");
3187		os_unsetenv("WPA_CTRL_DIR");
3188
3189		pos = os_strstr(pos, "[id=");
3190		if (pos)
3191			copy = os_strdup(pos + 4);
3192
3193		if (copy) {
3194			pos2 = id = copy;
3195			while (*pos2 && *pos2 != ' ')
3196				pos2++;
3197			*pos2++ = '\0';
3198			new_id = atoi(id);
3199			os_setenv("WPA_ID", id, 1);
3200			while (*pos2 && *pos2 != '=')
3201				pos2++;
3202			if (*pos2 == '=')
3203				pos2++;
3204			id = pos2;
3205			while (*pos2 && *pos2 != ']')
3206				pos2++;
3207			*pos2 = '\0';
3208			os_setenv("WPA_ID_STR", id, 1);
3209			os_free(copy);
3210		}
3211
3212		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3213
3214		if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3215			wpa_cli_connected = 1;
3216			wpa_cli_last_id = new_id;
3217			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3218		}
3219	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3220		if (wpa_cli_connected) {
3221			wpa_cli_connected = 0;
3222			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3223		}
3224	} else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3225		wpa_cli_exec(action_file, ctrl_ifname, pos);
3226	} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3227		wpa_cli_exec(action_file, ctrl_ifname, pos);
3228	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3229		wpa_cli_exec(action_file, ctrl_ifname, pos);
3230	} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3231		wpa_cli_exec(action_file, ctrl_ifname, pos);
3232	} else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3233		wpa_cli_exec(action_file, ctrl_ifname, pos);
3234	} else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3235		wpa_cli_exec(action_file, ctrl_ifname, pos);
3236	} else if (str_match(pos, WPS_EVENT_FAIL)) {
3237		wpa_cli_exec(action_file, ctrl_ifname, pos);
3238	} else if (str_match(pos, AP_STA_CONNECTED)) {
3239		wpa_cli_exec(action_file, ctrl_ifname, pos);
3240	} else if (str_match(pos, AP_STA_DISCONNECTED)) {
3241		wpa_cli_exec(action_file, ctrl_ifname, pos);
3242	} else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3243		wpa_cli_exec(action_file, ctrl_ifname, pos);
3244	} else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3245		wpa_cli_exec(action_file, ctrl_ifname, pos);
3246	} else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3247		wpa_cli_exec(action_file, ctrl_ifname, pos);
3248	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3249		printf("wpa_supplicant is terminating - stop monitoring\n");
3250		wpa_cli_quit = 1;
3251	}
3252}
3253
3254
3255#ifndef CONFIG_ANSI_C_EXTRA
3256static void wpa_cli_action_cb(char *msg, size_t len)
3257{
3258	wpa_cli_action_process(msg);
3259}
3260#endif /* CONFIG_ANSI_C_EXTRA */
3261
3262
3263static void wpa_cli_reconnect(void)
3264{
3265	wpa_cli_close_connection();
3266	if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3267		return;
3268
3269	if (interactive) {
3270		edit_clear_line();
3271		printf("\rConnection to wpa_supplicant re-established\n");
3272		edit_redraw();
3273	}
3274}
3275
3276
3277static void cli_event(const char *str)
3278{
3279	const char *start, *s;
3280
3281	start = os_strchr(str, '>');
3282	if (start == NULL)
3283		return;
3284
3285	start++;
3286
3287	if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3288		s = os_strchr(start, ' ');
3289		if (s == NULL)
3290			return;
3291		s = os_strchr(s + 1, ' ');
3292		if (s == NULL)
3293			return;
3294		cli_txt_list_add(&bsses, s + 1);
3295		return;
3296	}
3297
3298	if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3299		s = os_strchr(start, ' ');
3300		if (s == NULL)
3301			return;
3302		s = os_strchr(s + 1, ' ');
3303		if (s == NULL)
3304			return;
3305		cli_txt_list_del_addr(&bsses, s + 1);
3306		return;
3307	}
3308
3309#ifdef CONFIG_P2P
3310	if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3311		s = os_strstr(start, " p2p_dev_addr=");
3312		if (s == NULL)
3313			return;
3314		cli_txt_list_add_addr(&p2p_peers, s + 14);
3315		return;
3316	}
3317
3318	if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3319		s = os_strstr(start, " p2p_dev_addr=");
3320		if (s == NULL)
3321			return;
3322		cli_txt_list_del_addr(&p2p_peers, s + 14);
3323		return;
3324	}
3325
3326	if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3327		s = os_strchr(start, ' ');
3328		if (s == NULL)
3329			return;
3330		cli_txt_list_add_word(&p2p_groups, s + 1);
3331		return;
3332	}
3333
3334	if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3335		s = os_strchr(start, ' ');
3336		if (s == NULL)
3337			return;
3338		cli_txt_list_del_word(&p2p_groups, s + 1);
3339		return;
3340	}
3341#endif /* CONFIG_P2P */
3342}
3343
3344
3345static int check_terminating(const char *msg)
3346{
3347	const char *pos = msg;
3348
3349	if (*pos == '<') {
3350		/* skip priority */
3351		pos = os_strchr(pos, '>');
3352		if (pos)
3353			pos++;
3354		else
3355			pos = msg;
3356	}
3357
3358	if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3359		edit_clear_line();
3360		printf("\rConnection to wpa_supplicant lost - trying to "
3361		       "reconnect\n");
3362		edit_redraw();
3363		wpa_cli_attached = 0;
3364		wpa_cli_close_connection();
3365		return 1;
3366	}
3367
3368	return 0;
3369}
3370
3371
3372static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3373{
3374	if (ctrl_conn == NULL) {
3375		wpa_cli_reconnect();
3376		return;
3377	}
3378	while (wpa_ctrl_pending(ctrl) > 0) {
3379		char buf[256];
3380		size_t len = sizeof(buf) - 1;
3381		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3382			buf[len] = '\0';
3383			if (action_monitor)
3384				wpa_cli_action_process(buf);
3385			else {
3386				cli_event(buf);
3387				if (wpa_cli_show_event(buf)) {
3388					edit_clear_line();
3389					printf("\r%s\n", buf);
3390					edit_redraw();
3391				}
3392
3393				if (interactive && check_terminating(buf) > 0)
3394					return;
3395			}
3396		} else {
3397			printf("Could not read pending message.\n");
3398			break;
3399		}
3400	}
3401
3402	if (wpa_ctrl_pending(ctrl) < 0) {
3403		printf("Connection to wpa_supplicant lost - trying to "
3404		       "reconnect\n");
3405		wpa_cli_reconnect();
3406	}
3407}
3408
3409#define max_args 10
3410
3411static int tokenize_cmd(char *cmd, char *argv[])
3412{
3413	char *pos;
3414	int argc = 0;
3415
3416	pos = cmd;
3417	for (;;) {
3418		while (*pos == ' ')
3419			pos++;
3420		if (*pos == '\0')
3421			break;
3422		argv[argc] = pos;
3423		argc++;
3424		if (argc == max_args)
3425			break;
3426		if (*pos == '"') {
3427			char *pos2 = os_strrchr(pos, '"');
3428			if (pos2)
3429				pos = pos2 + 1;
3430		}
3431		while (*pos != '\0' && *pos != ' ')
3432			pos++;
3433		if (*pos == ' ')
3434			*pos++ = '\0';
3435	}
3436
3437	return argc;
3438}
3439
3440
3441static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3442{
3443	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3444		printf("Connection to wpa_supplicant lost - trying to "
3445		       "reconnect\n");
3446		wpa_cli_close_connection();
3447	}
3448	if (!ctrl_conn)
3449		wpa_cli_reconnect();
3450	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3451}
3452
3453
3454static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3455{
3456	wpa_cli_recv_pending(mon_conn, 0);
3457}
3458
3459
3460static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3461{
3462	char *argv[max_args];
3463	int argc;
3464	argc = tokenize_cmd(cmd, argv);
3465	if (argc)
3466		wpa_request(ctrl_conn, argc, argv);
3467}
3468
3469
3470static void wpa_cli_edit_eof_cb(void *ctx)
3471{
3472	eloop_terminate();
3473}
3474
3475
3476static int warning_displayed = 0;
3477static char *hfile = NULL;
3478static int edit_started = 0;
3479
3480static void start_edit(void)
3481{
3482	char *home;
3483	char *ps = NULL;
3484
3485#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3486	ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3487#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3488
3489	home = getenv("HOME");
3490	if (home) {
3491		const char *fname = ".wpa_cli_history";
3492		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3493		hfile = os_malloc(hfile_len);
3494		if (hfile)
3495			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3496	}
3497
3498	if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3499		      wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3500		eloop_terminate();
3501		return;
3502	}
3503
3504	edit_started = 1;
3505	eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3506}
3507
3508
3509static void update_bssid_list(struct wpa_ctrl *ctrl)
3510{
3511	char buf[4096];
3512	size_t len = sizeof(buf);
3513	int ret;
3514	char *cmd = "BSS RANGE=ALL MASK=0x2";
3515	char *pos, *end;
3516
3517	if (ctrl == NULL)
3518		return;
3519	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3520	if (ret < 0)
3521		return;
3522	buf[len] = '\0';
3523
3524	pos = buf;
3525	while (pos) {
3526		pos = os_strstr(pos, "bssid=");
3527		if (pos == NULL)
3528			break;
3529		pos += 6;
3530		end = os_strchr(pos, '\n');
3531		if (end == NULL)
3532			break;
3533		*end = '\0';
3534		cli_txt_list_add(&bsses, pos);
3535		pos = end + 1;
3536	}
3537}
3538
3539
3540static void update_ifnames(struct wpa_ctrl *ctrl)
3541{
3542	char buf[4096];
3543	size_t len = sizeof(buf);
3544	int ret;
3545	char *cmd = "INTERFACES";
3546	char *pos, *end;
3547	char txt[200];
3548
3549	cli_txt_list_flush(&ifnames);
3550
3551	if (ctrl == NULL)
3552		return;
3553	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3554	if (ret < 0)
3555		return;
3556	buf[len] = '\0';
3557
3558	pos = buf;
3559	while (pos) {
3560		end = os_strchr(pos, '\n');
3561		if (end == NULL)
3562			break;
3563		*end = '\0';
3564		ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3565		if (ret > 0 && ret < (int) sizeof(txt))
3566			cli_txt_list_add(&ifnames, txt);
3567		pos = end + 1;
3568	}
3569}
3570
3571
3572static void try_connection(void *eloop_ctx, void *timeout_ctx)
3573{
3574	if (ctrl_conn)
3575		goto done;
3576
3577	if (ctrl_ifname == NULL)
3578		ctrl_ifname = wpa_cli_get_default_ifname();
3579
3580	if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3581		if (!warning_displayed) {
3582			printf("Could not connect to wpa_supplicant: "
3583			       "%s - re-trying\n", ctrl_ifname);
3584			warning_displayed = 1;
3585		}
3586		eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3587		return;
3588	}
3589
3590	update_bssid_list(ctrl_conn);
3591
3592	if (warning_displayed)
3593		printf("Connection established.\n");
3594
3595done:
3596	start_edit();
3597}
3598
3599
3600static void wpa_cli_interactive(void)
3601{
3602	printf("\nInteractive mode\n\n");
3603
3604	eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3605	eloop_run();
3606	eloop_cancel_timeout(try_connection, NULL, NULL);
3607
3608	cli_txt_list_flush(&p2p_peers);
3609	cli_txt_list_flush(&p2p_groups);
3610	cli_txt_list_flush(&bsses);
3611	cli_txt_list_flush(&ifnames);
3612	if (edit_started)
3613		edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3614	os_free(hfile);
3615	eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3616	wpa_cli_close_connection();
3617}
3618
3619
3620static void wpa_cli_action(struct wpa_ctrl *ctrl)
3621{
3622#ifdef CONFIG_ANSI_C_EXTRA
3623	/* TODO: ANSI C version(?) */
3624	printf("Action processing not supported in ANSI C build.\n");
3625#else /* CONFIG_ANSI_C_EXTRA */
3626	fd_set rfds;
3627	int fd, res;
3628	struct timeval tv;
3629	char buf[256]; /* note: large enough to fit in unsolicited messages */
3630	size_t len;
3631
3632	fd = wpa_ctrl_get_fd(ctrl);
3633
3634	while (!wpa_cli_quit) {
3635		FD_ZERO(&rfds);
3636		FD_SET(fd, &rfds);
3637		tv.tv_sec = ping_interval;
3638		tv.tv_usec = 0;
3639		res = select(fd + 1, &rfds, NULL, NULL, &tv);
3640		if (res < 0 && errno != EINTR) {
3641			perror("select");
3642			break;
3643		}
3644
3645		if (FD_ISSET(fd, &rfds))
3646			wpa_cli_recv_pending(ctrl, 1);
3647		else {
3648			/* verify that connection is still working */
3649			len = sizeof(buf) - 1;
3650			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3651					     wpa_cli_action_cb) < 0 ||
3652			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3653				printf("wpa_supplicant did not reply to PING "
3654				       "command - exiting\n");
3655				break;
3656			}
3657		}
3658	}
3659#endif /* CONFIG_ANSI_C_EXTRA */
3660}
3661
3662
3663static void wpa_cli_cleanup(void)
3664{
3665	wpa_cli_close_connection();
3666	if (pid_file)
3667		os_daemonize_terminate(pid_file);
3668
3669	os_program_deinit();
3670}
3671
3672
3673static void wpa_cli_terminate(int sig, void *ctx)
3674{
3675	eloop_terminate();
3676}
3677
3678
3679static char * wpa_cli_get_default_ifname(void)
3680{
3681	char *ifname = NULL;
3682
3683#ifdef CONFIG_CTRL_IFACE_UNIX
3684	struct dirent *dent;
3685	DIR *dir = opendir(ctrl_iface_dir);
3686	if (!dir) {
3687#ifdef ANDROID
3688		char ifprop[PROPERTY_VALUE_MAX];
3689		if (property_get("wifi.interface", ifprop, NULL) != 0) {
3690			ifname = os_strdup(ifprop);
3691			printf("Using interface '%s'\n", ifname);
3692			return ifname;
3693		}
3694#endif /* ANDROID */
3695		return NULL;
3696	}
3697	while ((dent = readdir(dir))) {
3698#ifdef _DIRENT_HAVE_D_TYPE
3699		/*
3700		 * Skip the file if it is not a socket. Also accept
3701		 * DT_UNKNOWN (0) in case the C library or underlying
3702		 * file system does not support d_type.
3703		 */
3704		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3705			continue;
3706#endif /* _DIRENT_HAVE_D_TYPE */
3707		if (os_strcmp(dent->d_name, ".") == 0 ||
3708		    os_strcmp(dent->d_name, "..") == 0)
3709			continue;
3710		printf("Selected interface '%s'\n", dent->d_name);
3711		ifname = os_strdup(dent->d_name);
3712		break;
3713	}
3714	closedir(dir);
3715#endif /* CONFIG_CTRL_IFACE_UNIX */
3716
3717#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3718	char buf[4096], *pos;
3719	size_t len;
3720	struct wpa_ctrl *ctrl;
3721	int ret;
3722
3723	ctrl = wpa_ctrl_open(NULL);
3724	if (ctrl == NULL)
3725		return NULL;
3726
3727	len = sizeof(buf) - 1;
3728	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3729	if (ret >= 0) {
3730		buf[len] = '\0';
3731		pos = os_strchr(buf, '\n');
3732		if (pos)
3733			*pos = '\0';
3734		ifname = os_strdup(buf);
3735	}
3736	wpa_ctrl_close(ctrl);
3737#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3738
3739	return ifname;
3740}
3741
3742
3743int main(int argc, char *argv[])
3744{
3745	int c;
3746	int daemonize = 0;
3747	int ret = 0;
3748	const char *global = NULL;
3749
3750	if (os_program_init())
3751		return -1;
3752
3753	for (;;) {
3754		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3755		if (c < 0)
3756			break;
3757		switch (c) {
3758		case 'a':
3759			action_file = optarg;
3760			break;
3761		case 'B':
3762			daemonize = 1;
3763			break;
3764		case 'g':
3765			global = optarg;
3766			break;
3767		case 'G':
3768			ping_interval = atoi(optarg);
3769			break;
3770		case 'h':
3771			usage();
3772			return 0;
3773		case 'v':
3774			printf("%s\n", wpa_cli_version);
3775			return 0;
3776		case 'i':
3777			os_free(ctrl_ifname);
3778			ctrl_ifname = os_strdup(optarg);
3779			break;
3780		case 'p':
3781			ctrl_iface_dir = optarg;
3782			break;
3783		case 'P':
3784			pid_file = optarg;
3785			break;
3786		default:
3787			usage();
3788			return -1;
3789		}
3790	}
3791
3792	interactive = (argc == optind) && (action_file == NULL);
3793
3794	if (interactive)
3795		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3796
3797	if (eloop_init())
3798		return -1;
3799
3800	if (global) {
3801#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3802		ctrl_conn = wpa_ctrl_open(NULL);
3803#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3804		ctrl_conn = wpa_ctrl_open(global);
3805#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3806		if (ctrl_conn == NULL) {
3807			fprintf(stderr, "Failed to connect to wpa_supplicant "
3808				"global interface: %s  error: %s\n",
3809				global, strerror(errno));
3810			return -1;
3811		}
3812
3813		if (interactive) {
3814			update_ifnames(ctrl_conn);
3815			mon_conn = wpa_ctrl_open(global);
3816			if (mon_conn) {
3817				if (wpa_ctrl_attach(mon_conn) == 0) {
3818					wpa_cli_attached = 1;
3819					eloop_register_read_sock(
3820						wpa_ctrl_get_fd(mon_conn),
3821						wpa_cli_mon_receive,
3822						NULL, NULL);
3823				} else {
3824					printf("Failed to open monitor "
3825					       "connection through global "
3826					       "control interface\n");
3827				}
3828			}
3829		}
3830	}
3831
3832	eloop_register_signal_terminate(wpa_cli_terminate, NULL);
3833
3834	if (ctrl_ifname == NULL)
3835		ctrl_ifname = wpa_cli_get_default_ifname();
3836
3837	if (interactive) {
3838		wpa_cli_interactive();
3839	} else {
3840		if (!global &&
3841		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3842			fprintf(stderr, "Failed to connect to non-global "
3843				"ctrl_ifname: %s  error: %s\n",
3844				ctrl_ifname, strerror(errno));
3845			return -1;
3846		}
3847
3848		if (action_file) {
3849			if (wpa_ctrl_attach(ctrl_conn) == 0) {
3850				wpa_cli_attached = 1;
3851			} else {
3852				printf("Warning: Failed to attach to "
3853				       "wpa_supplicant.\n");
3854				return -1;
3855			}
3856		}
3857
3858		if (daemonize && os_daemonize(pid_file))
3859			return -1;
3860
3861		if (action_file)
3862			wpa_cli_action(ctrl_conn);
3863		else
3864			ret = wpa_request(ctrl_conn, argc - optind,
3865					  &argv[optind]);
3866	}
3867
3868	os_free(ctrl_ifname);
3869	eloop_destroy();
3870	wpa_cli_cleanup();
3871
3872	return ret;
3873}
3874
3875#else /* CONFIG_CTRL_IFACE */
3876int main(int argc, char *argv[])
3877{
3878	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3879	return -1;
3880}
3881#endif /* CONFIG_CTRL_IFACE */
3882