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