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