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