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