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